Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.x MTimer#toString and the JSON output for timer values use seconds (change from 3.x) #9717

Open
tjquinno opened this issue Jan 30, 2025 · 0 comments
Labels
4.x Version 4.x metrics

Comments

@tjquinno
Copy link
Member

Environment Details

  • Helidon Version: 4.x
  • Helidon SE or Helidon MP both
  • JDK version:
  • OS:

Problem Description

In two places, output related to Timer values is expressed in seconds, regardless of the setting of baseUnit:

  • MTimer#toString() - uses Duration output with seconds units which is often not enough precision to display meaningful data for small values
  • JSON-formatted output - uses seconds as units. Here the output is decimal (not truncated to an integer) but is a change from 3.x behavior.

Some notes

The Micrometer Timer to which Helidon's API delegates does not itself support baseUnits as a builder setting. Micrometer's timer stores values in nanoseconds internally. The various methods on Micrometer's Timer which return the timer's data do accept a TimeUnit parameter which determines the units in which the returned value (a double) is expressed.

That said, the Helidon Timer.Builder by virtue of extending Meter.Builder, does expose a baseUnit(String) method. The current Helidon implementation ignores that setting entirely when it builds the Micrometer Timer; there is no way to communicate this value to the Micrometer Timer.Builder.

The Micrometer Timer does expose a baseTimeUnit method with this Javadoc:

The base time unit of the timer to which all published metrics will be scaled

but Micrometer decides internally what this value will be based on what lower-level timer implementation(s) are used by the higher-level timer. For example, typically the actual timer Micrometer uses is a PrometheusTimer and its baseTimeUnit is seconds.

One possibility could be for the Helidon MTimer implementation to save the specified base unit when the Helidon Timer.Builder#baseUnit(String) method is invoked and then for the Helidon code to use that in the toString() output.

Helidon could also use such a saved base unit value in formatting the JSON output. If the developer never specified a base unit to use, the default could be nanoseconds which (IIRC) would reinstate the 3.x behavior.

Steps to reproduce

  1. Add a Timer to the SE QuickStart app's GreetService:

    private Timer greetingTimer;
    

    In the constructor:

       greetTimer = Metrics.globalRegistry().getOrCreate(Timer.builder("greetTimer");
    

    As the new first lines of getDefaultMessageHandler:

       greetTimer.record(123, TimeUnit.MILLISECONDS);
       LOGGER.log(System.Logger.Level.INFO, "Timer is now " + greetTimer);
    
  2. Build and run the app.

  3. curl http://localhost:8080/greet # to update the timer

  4. curl http://localhost:8080/observe/metrics -H "Accept: application/json"

The server console output contains

Timer is now MTimer[id=PlainId[name='greetTimer', tags=[MTag[scope=application]]], scope='application', count=1, totalTime=PT0S]

(note the 0 reported time) and the metrics output includes

"greetTimer": {
      "count": 1,
      "max": 0.123,
      "mean": 0.123,
      "elapsedTime": 0.123,
      "p0.5": 0.121634816,
      "p0.75": 0.121634816,
      "p0.95": 0.121634816,
      "p0.98": 0.121634816,
      "p0.99": 0.121634816,
      "p0.999": 0.121634816
    }

The output is expressed in seconds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.x Version 4.x metrics
Projects
Status: Triage
Development

No branches or pull requests

1 participant