Skip to content

Commit

Permalink
Merge branch 'micrometer-metrics:main' into micrometer-metricsgh-1441
Browse files Browse the repository at this point in the history
  • Loading branch information
jkemming committed Feb 13, 2024
2 parents 5cb55eb + c69180d commit ef0869d
Show file tree
Hide file tree
Showing 103 changed files with 2,943 additions and 5,155 deletions.
8 changes: 4 additions & 4 deletions .circleci/config.yml
Expand Up @@ -7,25 +7,25 @@ executors:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
resource_class: medium+
docker:
- image: cimg/openjdk:21.0.0
- image: cimg/openjdk:21.0.2
circle-jdk17-executor:
working_directory: ~/micrometer
environment:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
resource_class: medium+
docker:
- image: cimg/openjdk:17.0.9
- image: cimg/openjdk:17.0.10
circle-jdk11-executor:
working_directory: ~/micrometer
environment:
GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"'
resource_class: medium+
docker:
- image: cimg/openjdk:11.0.21
- image: cimg/openjdk:11.0.22
machine-executor:
working_directory: ~/micrometer
machine:
image: ubuntu-2204:2023.10.1
image: ubuntu-2204:2024.01.1

commands:
gradlew-build:
Expand Down
17 changes: 0 additions & 17 deletions .github/dependabot.yml
Expand Up @@ -22,23 +22,6 @@ updates:
- version-update:semver-major
- version-update:semver-minor
open-pull-requests-limit: 10
- package-ecosystem: gradle
directory: "/"
schedule:
interval: monthly
target-branch: "1.10.x"
milestone: 159
ignore:
# metrics are better with https://github.com/Netflix/Hystrix/pull/1568 introduced
# in hystrix 1.5.12, but Netflix re-released 1.5.11 as 1.5.18 late in 2018.
# <=1.5.11 or 1.5.18 doesn't break with Micrometer, but open metrics won't be correct necessarily.
- dependency-name: "com.netflix.hystrix:hystrix-core"
# only upgrade patch versions
- dependency-name: "*"
update-types:
- version-update:semver-major
- version-update:semver-minor
open-pull-requests-limit: 10
- package-ecosystem: gradle
directory: "/"
schedule:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/gradle-wrapper-validation.yml
Expand Up @@ -10,4 +10,4 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v1
- uses: gradle/wrapper-validation-action@v2
6 changes: 4 additions & 2 deletions build.gradle
Expand Up @@ -337,7 +337,7 @@ subprojects {

check.dependsOn("testModules")

if (!(project.name in ['micrometer-jakarta9'])) { // add projects here that do not exist in the previous minor so should be excluded from japicmp
if (!(project.name in ['micrometer-jakarta9', 'micrometer-java11'])) { // add projects here that do not exist in the previous minor so should be excluded from japicmp
apply plugin: 'me.champeau.gradle.japicmp'
apply plugin: 'de.undercouch.download'

Expand Down Expand Up @@ -380,6 +380,8 @@ subprojects {
ignoreMissingClasses = true
includeSynthetic = true

// TODO remove MetricsDSLContext from excludes in 1.14 when comparing against 1.13
classExcludes = [ 'io.micrometer.core.instrument.binder.db.MetricsDSLContext' ]
compatibilityChangeExcludes = [ "METHOD_NEW_DEFAULT" ]

packageExcludes = ['io.micrometer.shaded.*', 'io.micrometer.statsd.internal']
Expand Down Expand Up @@ -423,7 +425,7 @@ nexusPublishing {
}

wrapper {
gradleVersion = '8.5'
gradleVersion = '8.6'
}

defaultTasks 'build'
6 changes: 2 additions & 4 deletions dependencies.gradle
@@ -1,14 +1,12 @@
def VERSIONS = [
libs.logback,
libs.logback12,
libs.colt,
libs.aws.javaSdkCloudwatch,
libs.dynatraceUtils,
libs.jacksonDatabind,
libs.caffeine,
libs.kafkaJunit,
libs.wiremock,
libs.googleOauth2Http,
libs.googleCloudMonitoring,
libs.dagger,
libs.daggerCompiler,
libs.guava,
Expand All @@ -33,6 +31,7 @@ def VERSIONS = [
libs.grpcStubs,
libs.grpcAlts,
libs.grpcTestingProto,
libs.grpcKotlinStub,
libs.gmetric4j,
libs.prometheusClient,
libs.prometheusPushgateway,
Expand Down Expand Up @@ -66,7 +65,6 @@ def VERSIONS = [
libs.hdrhistogram,
libs.hibernateEntitymanager,
libs.hsqldb,
libs.jooq,
libs.jsr107,
libs.junitJupiter,
libs.junitPlatformLauncher,
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/nav.adoc
Expand Up @@ -61,7 +61,7 @@
* xref:observation.adoc[Micrometer Observation]
** xref:observation/installing.adoc[Installing]
** xref:observation/introduction.adoc[Introduction]
** xref:observation/handler.adoc[Observation Handlers]
** xref:observation/components.adoc[Components]
** xref:observation/instrumenting.adoc[Instrumenting]
** xref:observation/testing.adoc[Testing]
** xref:observation/projects.adoc[Instrumented Projects]
3 changes: 2 additions & 1 deletion docs/modules/ROOT/pages/concepts/distribution-summaries.adoc
Expand Up @@ -29,7 +29,8 @@ DistributionSummary summary = DistributionSummary
NOTE: The maximum (which is named `max`) for basic `DistributionSummary` implementations, such as `CumulativeDistributionSummary` and `StepDistributionSummary`, is a time window maximum (`TimeWindowMax`).
It means that its value is the maximum value during a time window.
If no new values are recorded for the time window length, the maximum is reset to 0 as a new time window starts.
Time window size is the step size of the meter registry, unless expiry in `DistributionStatisticConfig` is explicitly set to another value.
The time window size until values are fully expired is the `expiry` multiplied by the `bufferLength` in `DistributionStatisticConfig`.
`expiry` defaults to the step size of the meter registry unless is explicitly set to a different value, and `bufferLength` defaults to `3`.
A time window max is used to capture the maximum latency in a subsequent interval after heavy resource pressure triggers the latency and prevents metrics from being published.
Percentiles are also time window percentiles (`TimeWindowPercentileHistogram`).

Expand Down
3 changes: 2 additions & 1 deletion docs/modules/ROOT/pages/concepts/timers.adoc
Expand Up @@ -31,7 +31,8 @@ Timer timer = Timer
NOTE: The maximum statistical value for basic `Timer` implementations, such as `CumulativeTimer` and `StepTimer`, is a time window maximum (`TimeWindowMax`).
It means that its value is the maximum value during a time window.
If no new values are recorded for the time window length, the max is reset to 0 as a new time window starts.
Time window size is the step size of the meter registry unless expiry in `DistributionStatisticConfig` is explicitly set to a different value.
The time window size until values are fully expired is the `expiry` multiplied by the `bufferLength` in `DistributionStatisticConfig`.
`expiry` defaults to the step size of the meter registry unless is explicitly set to a different value, and `bufferLength` defaults to `3`.
A time window maximum is used to capture maximum latency in a subsequent interval after heavy resource pressure triggers the latency and prevents metrics from being published.
Percentiles are also time window percentiles (`TimeWindowPercentileHistogram`). Histogram buckets usually behave like counters so depending on the backend, they can be reported as cumulative values (for example in the case of Prometheus) or as a rate at which a counter increments over the push interval.

Expand Down
9 changes: 5 additions & 4 deletions docs/modules/ROOT/pages/implementations/otlp.adoc
Expand Up @@ -35,15 +35,16 @@ management:
aggregationTemporality: "cumulative"
headers:
header1: value1
step: 30s
resourceAttributes:
key1: value1
----

1. `url` - The URL to which data is reported. Defaults to `http://localhost:4318/v1/metrics`
2. `aggregationTemporality` - https://opentelemetry.io/docs/specs/otel/metrics/data-model/#temporality[Aggregation temporality, window=_blank] determines how the additive quantities are expressed, in relation to time. The supported values are `cumulative` or `delta`. Defaults to `cumulative`. +
*Note*: This config was introduced in version 1.11.0.
1. `url` - The URL to which data is reported. Environment variables `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` and `OTEL_EXPORTER_OTLP_ENDPOINT` are also supported in the default implementation. If a value is not provided, it defaults to `http://localhost:4318/v1/metrics`
2. `aggregationTemporality` - https://opentelemetry.io/docs/specs/otel/metrics/data-model/#temporality[Aggregation temporality, window=_blank] determines how the additive quantities are expressed, in relation to time. The environment variable `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` is supported by the default implementation. The supported values are `cumulative` or `delta`. Defaults to `cumulative`.
3. `headers` - Additional headers to send with exported metrics. This can be used for authorization headers. By default, headers are loaded from the config. If that is not set, they can be taken from the environment variables `OTEL_EXPORTER_OTLP_HEADERS` and `OTEL_EXPORTER_OTLP_METRICS_HEADERS`. If a header is set in both the environmental variables, the header in the latter overrides the former.
4. `resourceAttributes` - https://opentelemetry.io/docs/specs/otel/resource/semantic_conventions/#service[Resource attributes, window=_blank] are used for all metrics published. By default, Micrometer adds the following resource attributes:
4. `step` - the interval at which metrics will be published. The environment variable `OTEL_METRIC_EXPORT_INTERVAL` is supported by the default implementation. If a value is not provided, defaults to 1 minute.
5. `resourceAttributes` - https://opentelemetry.io/docs/specs/otel/resource/semantic_conventions/#service[Resource attributes, window=_blank] are used for all metrics published. By default, Micrometer adds the following resource attributes:

[%autowidth]
|===
Expand Down
4 changes: 3 additions & 1 deletion docs/modules/ROOT/pages/observation.adoc
Expand Up @@ -3,4 +3,6 @@

Micrometer Observation is part of the https://github.com/micrometer-metrics/micrometer[Micrometer] project and contains the Observation API. The main idea behind it is that you

> Instrument code once, and get multiple benefits out of it.
****
_"Instrument code once, and get multiple benefits out of it."_
****
@@ -1,5 +1,73 @@
[[micrometer-observation-components]]
= Observation Components

In this section we will describe main components related to Micrometer Observation.

* <<micrometer-observation-context, Observation Context>>
* <<micrometer-observation-handler, Observation Handler>>
* <<micrometer-observation-events, Signaling Errors and Arbitrary Events>>
* <<micrometer-observation-convention-example, Observation Convention>>
* <<micrometer-observation-predicates-filters, Observation Predicates and Filters>>

*Micrometer Observation basic flow*

`Observation` through `ObservationRegistry` gets created with a mutable `Observation.Context`. On each Micrometer Observation lifecycle action (e.g. `start()`) a corresponding `ObservationHandler` method is called (e.g. `onStart`) with the mutable `Observation.Context` as argument.

// https://arthursonzogni.com/Diagon/#GraphDAG
// ObservationRegistry->Observation
// Context->Observation
// Observation->Handler
[source,subs=+attributes]
-----
┌───────────────────┐┌───────┐
│ObservationRegistry││Context│
└┬──────────────────┘└┬──────┘
┌▽────────────────────▽┐
│Observation │
└┬─────────────────────┘
┌▽──────┐
│Handler│
└───────┘
-----

*Micrometer Observation detailed flow*

// https://arthursonzogni.com/Diagon/#GraphDAG
// ObservationRegistry->Observation
// Context->Observation
// ObservationConvention->Observation
// ObservationPredicate->Observation
// Observation->Handler
// Handler->ObservationFilter
[source,subs=+attributes]
-----
┌───────────────────┐┌───────┐┌─────────────────────┐┌────────────────────┐
│ObservationRegistry││Context││ObservationConvention││ObservationPredicate│
└┬──────────────────┘└┬──────┘└┬────────────────────┘└┬───────────────────┘
┌▽────────────────────▽────────▽──────────────────────▽┐
│Observation │
└┬─────────────────────────────────────────────────────┘
┌▽──────┐
│Handler│
└┬──────┘
┌▽────────────────┐
│ObservationFilter│
└─────────────────┘
-----

`Observation` through `ObservationRegistry` gets created with a mutable `Observation.Context`. To allow name and key-value customization, an `ObservationConvention` can be used instead of direct name setting. List of `ObservationPredicate` is run to verify if an `Observation` should be created instead of a no-op version. On each xref:observation/introduction.adoc[Micrometer Observation lifecycle] action (e.g. `start()`) a corresponding `ObservationHandler` method is called (e.g. `onStart`) with the mutable `Observation.Context` as argument. On `Observation` stop, before calling the `ObservationHandler` `onStop` methods, list of `ObservationFilter` is called to optionally further modify the `Observation.Context`.

[[micrometer-observation-context]]
== Observation.Context

To pass information between the instrumented code and the handler (or between handler methods, such as `onStart` and `onStop`), you can use an `Observation.Context`. An `Observation.Context` is a `Map`-like container that can store values for you while your handler can access the data inside the context.

[[micrometer-observation-handler]]
= Observation Handler
== Observation Handler

Observation Handler allows adding capabilities to existing instrumentations (i.e. you instrument code once and depending on the Observation Handler setup, different actions, such as create spans, metrics, logs will happen). In other words, if you have instrumented code and want to add metrics around it, it's enough for you to register an Observation Handler in the Observation Registry to add that behaviour.

Let's look at the following example of adding a timer behaviour to an existing instrumentation.

A popular way to record Observations is storing the start state in a `Timer.Sample` instance and stopping it when the event has ended.
Recording such measurements could look like this:
Expand All @@ -16,16 +84,11 @@ If you want to have more observation options (such as metrics and tracing -- alr
include::{include-java}/observation/ObservationHandlerTests.java[tags=observation,indent=0]
-----

Starting with Micrometer 1.10, you can register "handlers" (`ObservationHandler` instances) that are notified about the lifecycle event of an observation (for example, you can run custom code when an observation is started or stopped).
Starting with Micrometer 1.10, you can register "handlers" (`ObservationHandler` instances) that are notified about the xref:observation/introduction.adoc[lifecycle event] of an observation (for example, you can run custom code when an observation is started or stopped).
Using this feature lets you add tracing capabilities to your existing metrics instrumentation (see: `DefaultTracingObservationHandler`). The implementation of these handlers does not need to be tracing related. It is completely up to you how you are going to implement them (for example, you can add logging capabilities).

[[micrometer-observation-context]]
== Observation.Context

To pass information between the instrumented code and the handler (or between handler methods, such as `onStart` and `onStop`), you can use an `Observation.Context`. An `Observation.Context` is a `Map`-like container that can store values for you while your handler can access the data inside the context.

[[micrometer-observation-handler-example]]
== ObservationHandler Example
=== ObservationHandler Example

Based on this, we can implement a simple handler that lets the users know about its invocations by printing them out to `stdout`:

Expand Down

0 comments on commit ef0869d

Please sign in to comment.