Class FcCommandMetrics

java.lang.Object
org.frontcache.resilience.FcCommandMetrics

public class FcCommandMetrics extends Object
Rolling metrics for one command, shaped to the Hystrix dashboard JSON rather than to Resilience4j's data model. Resilience4j's CircuitBreaker.Metrics carries failure and slow-call rates and buffered/failed/ successful/not-permitted counts - and no per-event-type rolling counters and no latency percentiles. The dashboard asserts 36 keys and throws on the first missing one, so the counter set has to be shaped like the JSON. That is what this class is: a ring of 1-second buckets of LongAdder per FcEventType plus an HdrHistogram ring, read as a merged snapshot. See proposal section 7.3. Keyed by command key alone. One Frontcache node serves one site, so there is exactly one group at runtime and nothing to disambiguate - the composite (domain, commandKey) key an earlier draft of the proposal needed became unnecessary when multi-domain support was retired (section 6.6). This class also owns the in-flight registry, which does double duty: it produces currentConcurrentExecutionCount for the dashboard, and it is what the semaphore-path watchdog sweeps (section 6.2). Keeping one registry rather than two means the watchdog costs no per-request allocation beyond what the concurrency gauge already needs.
  • Method Details

    • getInstance

      public static FcCommandMetrics getInstance(String commandKey, String group, int rollingStatsMs)
    • all

      public static Collection<FcCommandMetrics> all()
    • existing

      public static FcCommandMetrics existing(String commandKey)
    • getCommandKey

      public String getCommandKey()
    • getGroup

      public String getGroup()
    • markEvent

      public void markEvent(FcEventType event)
    • recordLatency

      public void recordLatency(long millis)
    • markStart

      public org.frontcache.resilience.FcCommandMetrics.InFlight markStart(long budgetMs, String description)
      Registers an execution and returns its token, which must be handed back to markEnd(FcCommandMetrics.InFlight).
      Parameters:
      budgetMs - the configured timeout for the command, or 0 for "not watched". Only the semaphore path passes a budget: the thread path is bounded by a real TimeLimiter, so watching it too would double-report the same overrun.
      Returns:
      the token to pass to markEnd(FcCommandMetrics.InFlight), or null when the execution is not watched - markEnd accepts null and still maintains the concurrency gauge
    • markEnd

      public void markEnd(org.frontcache.resilience.FcCommandMetrics.InFlight execution)
      Parameters:
      execution - the token from markStart(long, String); null for an execution that was not watched
    • getCurrentConcurrentExecutionCount

      public int getCurrentConcurrentExecutionCount()
    • getRollingMaxConcurrentExecutionCount

      public int getRollingMaxConcurrentExecutionCount()
    • getTotalCount

      public long getTotalCount(FcEventType event)
      Monotonic count since JVM start - what the Prometheus exporter reads.
    • getRollingCount

      public long getRollingCount(FcEventType event)
    • getRollingTotalRequests

      public long getRollingTotalRequests()
      Hystrix's HealthCounts total: successes plus the outcomes that mean the dependency call did not complete. Short-circuits are deliberately excluded, matching Hystrix - counting them would let an open circuit keep its own error rate pinned at 100% and never recover.
    • getRollingErrorCount

      public long getRollingErrorCount()
    • getErrorPercentage

      public int getErrorPercentage()
    • latencySnapshot

      public FcCommandMetrics.LatencySnapshot latencySnapshot()
      One merge of the rolling ring. This is deliberately NOT cached here. A cache would need a TTL, and a TTL inside the accessor would make "record a latency, then read it back" quietly wrong for anything that does the two in quick succession - the tests among them. Callers that read repeatedly within one logical operation (a dashboard frame, a Prometheus scrape) hold the returned snapshot instead.
    • getLatencyMean

      public long getLatencyMean()
      Convenience for a caller that wants only the mean. Costs a full merge - see latencySnapshot().
    • getLatencyPercentiles

      public Map<String,Long> getLatencyPercentiles()
      The percentile map the dashboard expects, with its exact key set - it divides and plots these directly, so the shape matters as much as the numbers. Costs a full merge - see latencySnapshot().