All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.sitebricks.routing.InMemorySystemMetrics Maven / Gradle / Ivy

The newest version!
package com.google.sitebricks.routing;

import com.google.common.collect.MapMaker;
import com.google.inject.Singleton;
import com.google.sitebricks.compiler.CompileError;
import net.jcip.annotations.ThreadSafe;

import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Logger;

/**
 * This class is completely lock and wait free. It provides the
 * "last seen" metrics, optimistically.
 *
 * @author Dhanji R. Prasanna ([email protected])
 */
@ThreadSafe
@Singleton
class InMemorySystemMetrics implements SystemMetrics {
  private final ConcurrentMap, Metric> pages = new MapMaker().weakKeys().makeMap();
  private final AtomicBoolean active = new AtomicBoolean(false);

  private final Logger log = Logger.getLogger(SystemMetrics.class.getName());

  public void logPageRenderTime(Class page, long time) {
    Metric metric = putIfAbsent(page);

    // Requests fight it out for who wins this set().
    metric.lastRenderTime.set(time);
  }

  public void logErrorsAndWarnings(Class page, List errors, List warnings) {
    Metric metric = putIfAbsent(page);

    // These must always be set in unison, so we are forced to use a wrapper to avoid synchronization.
    ErrorTuple errorTuple = new ErrorTuple(errors, warnings);
    metric.lastErrors.set(errorTuple);

    // Spit out to log.
    log.warning(errorTuple.toString());
  }

  public void activate() {
    active.set(true);
  }

  public boolean isActive() {
    return active.get();
  }

  private Metric putIfAbsent(Class page) {
    Metric metric = pages.get(page);

    // Concurrent put-if-absent.
    if (null == metric) {
      Metric newMetric = new Metric();

      // Attempt to put it using CAS.
      final Metric returned = pages.putIfAbsent(page, newMetric);

      // If the put succeeded, use it (otherwise get it from the map).
      if (null == returned)
        metric = newMetric;
      else
        metric = returned;
    }

    return metric;
  }

  /**
   * Associates various metrics with a given page It is not guaranteed to represent any
   * particular request, rather metrics are collected over time.
   * 

* Except for the errors and warnings, which are always the last ones available (roughly!) */ private static class Metric { private final AtomicLong lastRenderTime = new AtomicLong(0); private final AtomicReference lastErrors = new AtomicReference(); } //wrapper helps avoid locking when setting errors and warnings for a page atomically private static class ErrorTuple { private final List errors; private final List warnings; public ErrorTuple(List errors, List warnings) { this.errors = errors; this.warnings = warnings; } @Override public String toString() { return "Template compile summary: errors=" + errors + ", warnings=" + warnings; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy