Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Goals

...

  • Allow routing measurements to statistics, Micrometer meters, or both as appropriate, to allow publishing each measurement to the appropriate places.

...

  • Minimize the intrusiveness of new and existing metrics instrumentation.

...

  • Minimize the amount of code that must know how to route measurements to stats and meters.

...

  • Maintain Geode performance.

...

  • Not preclude any options for deprecating and removing Geode’s statistics mechanism in the future. And take steps to make deprecating and removing the existing statistics mechanism easier.

Proposal

...

  • Continue to use Geode’s existing style of instrumentation class (e.g. CachePerfStats) to instrument code.

...

  • Enhance the instrumentation classes to create and register meters when appropriate, and to route each measurement to the appropriate stats and meters.

...

  • When we want to route a given measurement to both a statistic and a meter, use the "legacy meter" wrapper mechanism (described below).

...

  • Incrementally improve the instrumentation classes to focus more on reporting domain events (e.g. regionAdded()) and less on reporting measurements (e.g. incRegions()).

Legacy Meter Wrappers

To route a given measurement to both a Micrometer meter and a Geode statistic, do the following in the instrumentation class's constructor:-

  • Create and register a normal Micrometer meter in the cache's meter registry.

...

  • Wrap the registered meter in a custom "legacy meter" that reads and writes the stat, and also writes to the registered meter.

In the instrumentation methods (e.g. endPut()):-

  • Use the legacy meter to report measurements.

Diagrams

PlantUML
titleLegacy Meter Structure
@startuml

hide footbox

MeterRegistry *-- Counter

class InstrumentationClass {
MeterRegistry registry
Statistics statistics
}
note right of InstrumentationClass: e.g. CacheServerStats

class LegacyCounterBuilder {
intStatistic(statistics, id)
longStatistic(statistics, id)
register(registry)
}

class LegacyCounter {
LegacyCounter(counter, binding)
increment(amount)
count()
Counter counter
StatisticsBinding binding
}

class Counter {
increment(amount)
count()
}

class StatisticsBinding {
Statistics statistics
int statId
increment(amount)
long longValue()
double doubleValue()
}

InstrumentedCode --> InstrumentationClass

InstrumentationClass --> LegacyCounterBuilder
InstrumentationClass --> LegacyCounter : increment(amount)
InstrumentationClass *-- Statistics

LegacyCounterBuilder --> MeterRegistry
LegacyCounterBuilder --> LegacyCounter

LegacyCounter --> StatisticsBinding : increment(amount)
LegacyCounter --> Counter : increment(amount)

StatisticsBinding --> Statistics : incInt(id, amount)

note right of LegacyCounterBuilder : New class
note right of LegacyCounter : New class (implements Counter)
note right of StatisticsBinding : New class

@enduml

...