Add extended key performance indicators metrics support #3021
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Resolves #2688
Resolves #2689
Overview
A key performance indicator (KPI) can be useful not only for measuring the performance of a server but also for building application-specific health checks using the KPI.
Existing ("basic") KPI metrics and implementation
Previously, in any app including
metrics/metrics
, Helidon has published two KPI metrics whenever the app includes the modulemetrics/metrics
:counter
-Counter
of the total number of requests received by the servermeter
-Meter
(rate) for above count.The full metric names are the routing name for the routing (if any) plus
request.
so, typically, users seerequests.count
andrequests.meter
.Recall that a
Meter
reports an overall count, mean rate, and rates over the previous 1, 5, and 15-minute intervals.These were created in
MetricsSupport#configureVendorMetrics
and a handler lambda declared in that same method would update the metrics before invokingrequest.next()
.New ("extended") KPI metrics
The extended metrics are disabled by default, enabled by configuration or builder methods.
inFlight
-ConcurrentGauge
of requests actively being processed at a given momentload
-Meter
ofinFlight
longRunning
-Meter
- requests which take longer than a configurable threshold to complete their processingdeferred
-Meter
- received requests were not processed immediatelySome requests (for example, but not limited to, those executed by Jersey) might be deferred--received by Helidon but then delayed for some reason (e.g, queued due to a shortage of available threads) before actually being processed. This means there can be a difference between when Helidon receives a request and when it starts processing the request.
Similarly, some requests (again, for example, but not limited to, Jersey ones) might complete their work asynchronously, after the user code has invoked
request.next()
and, therefore, separate from when theMetricsSupport
handler's call torequest.next()
returns.Some of the new KPI metrics require action after as well as before each request is handled and processed.
These complexities lead to code changes that are a little more more extensive and complicated than might be expected at first glance.
Design
Introduce two abstractions:
Context
which tracks the key events in a request's life cycle that are relevant to KPI metricsMetrics
interface which encapsulates whether the basic or extended KPI metrics are set up and how to update them at various stages in the request's lifecycleMake some small changes in the current request workflow:
microprofile/server
ServerCdiExtension
places a new instance of the KPIContext
into the request's context store.webserver/jersey
JerseySupport
, just before it submits each request to Jersey for processing, gets the KPIContext
and, if found, reports to it that request processing is starting.MetricsSupport
, in its existing KPI-related handler:Context
from the request's request context, or, if there is no KPIContext
present, creates one;Metrics
abstraction mentioned above;Context
to report the handling and processing of the request, passing theMetrics
object mentioned just above.This way, with no change needed in an MP app's code, the KPI metrics distinguish between Helidon's handling vs. processing of JAX-RS requests. By default, in SE apps Helidon treats the start of handling the request as the start of processing the request as well. An SE developer has the option of changing the app code slightly so the KPI metrics reflect the distinction between handling and processing. (See the Other Notes section below.)
The basic or extended KPI metrics are registered in the vendor registry when
MetricsSupport
instantiates theMetrics
abstraction.Changed components
webserver/webserver
KeyPerformanceIndicatorSupport
- defines the KPI behavior through nested interfacesMetrics
- abstracts the creation and collection of original (simple) and new (extended) KPI metricsContext
- abstracts the stages in a request's life cycle that are relevant to KPI metricsDeferrableRequestContext
- sub-interface ofContext
KeyPerformanceIndicatorContextImpls
- impls for the aboveContext
interfaces.The specific type of
Context
needed for a request varies from request to request.Callers of the
Context
factory methods always know which type they need.webserver/jersey
JerseySupport
class now, just before starting the processing of the request, retrieves the KPIDeferrableRequestContext
from the requestContext
and invokesrequestProcessingStarted
.JerseySupport
always invokes theDeferrableRequestContext
if it's present. Ifmetrics/metrics
is not on the class or module path, theDeferrableRequestContext#requestProcessingStarted
invocation done here acts as a no-op.metrics/metrics
New interface
KeyPerformanceIndicatorMetricsSettings
A POJO which holds all the configurable settings related to KPI metrics, currently:
A buildable object which encapsulates the KPI metrics settings (whether extended metrics are enabled and the threshold for long-running requests). The builder is used as a "sub-builder" for
MetricsSupport
.KeyPerformanceIndicatorMetricsSettingsImpl
- impl for aboveKeyPerformanceIndicatorMetricsImpls
Metrics
abstractionMetricsSupport
Builder
and constructor to incorporate KPI metrics config settingsconfigureVendorMetrics
Metrics
via theKeyPerformanceIndicatorMetricsImpls
factory methodconfigureVendorMetrics
:Context
from the request Context or creates a suitable onerequestHandlingStarted
,requestProcessingCompleted
, andrequestHandlingCompleted
from appropriate points. This handler cannot invokerequestProcessingStarted
because the request's processing might be deferred by a handler later in the chain.microprofile/metrics
Revise and add tests to check the extended KPI metrics.
microprofile/server
ServerCdiExtension
now adds a new handler to the handler chain. The handler adds a newDeferrableRequestContext
to each app's handler chain in a position earlier than the handler added byMetricsSupport
.This means:
MetricsSupport
will find thatContext
and use it, rather than creating and using a non-extended one.JerseySupport
will also find thatDeferrableRequestContext
and use it to track when the processing of the request begins.examples/metrics/kpi
New example app showing config and explicit set-up of extended KPI metrics.
docs
Updates to the SE and MP metrics guides, involving refactoring duplicated text into a new common file.
Other notes
Non-Jersey apps with deferred requests
Users can write their own non-Jersey apps which defer processing of requests. To work correctly with the enhanced KPI support, the developer needs to add code to:
DeferrableRequestContext
to the request'sContext
(soMetricsSupport
will use that KPIContext
when it updates the KPI metrics), andrequestProcessingStarted()
method at the appropriate moment.Note that if developers do not make these changes, nothing fails. The KPI metrics will not accurately reflect deferred requests; it will seem as if all requests are processed immediately upon receipt--the default SE behavior.
SE apps using
JerseySupport
Although we do not promote it (and coming changes in other technologies might remove this use case), developers can currently use
JerseySupport
in SE apps. Such apps can benefit from the KPI metrics improvements.To do so, these apps must add a handler to each routing that should participate in extended KPI metrics (as just described above) which adds a new
DeferrableRequestContext
to the request's context store. The application must add that handler earlier in the handler chain than it registers theMetricsSupport
instance as a service.