From f142f4594e0b083bc8a6e87350ce8ee0d931ea1c Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Mon, 22 Jan 2024 18:09:29 +0900 Subject: [PATCH 01/73] Enable whenConnectionCheckedInAfterPoolClose_thenNoExceptionThrown() (#4603) --- .../binder/mongodb/MongoMetricsConnectionPoolListenerTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/mongodb/MongoMetricsConnectionPoolListenerTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/mongodb/MongoMetricsConnectionPoolListenerTest.java index 7e0757dd27..719ca80981 100644 --- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/mongodb/MongoMetricsConnectionPoolListenerTest.java +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/mongodb/MongoMetricsConnectionPoolListenerTest.java @@ -114,6 +114,7 @@ public void clusterOpening(ClusterOpeningEvent event) { } @Issue("#2384") + @Test void whenConnectionCheckedInAfterPoolClose_thenNoExceptionThrown() { ServerId serverId = new ServerId(new ClusterId(), new ServerAddress(host, port)); ConnectionId connectionId = new ConnectionId(serverId); From b6e1aa30cf8cfa8fbd2289b002901b3f8a40cbd7 Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Mon, 22 Jan 2024 18:09:51 +0900 Subject: [PATCH 02/73] Polish (#4600) --- .../core/instrument/dropwizard/DropwizardMeterRegistry.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/dropwizard/DropwizardMeterRegistry.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/dropwizard/DropwizardMeterRegistry.java index cc5871f658..c002445589 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/dropwizard/DropwizardMeterRegistry.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/dropwizard/DropwizardMeterRegistry.java @@ -31,7 +31,6 @@ import java.lang.ref.WeakReference; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.ToDoubleFunction; import java.util.function.ToLongFunction; @@ -53,8 +52,6 @@ public abstract class DropwizardMeterRegistry extends MeterRegistry { private final DropwizardConfig dropwizardConfig; - private final AtomicBoolean warnLogged = new AtomicBoolean(); - public DropwizardMeterRegistry(DropwizardConfig config, MetricRegistry registry, HierarchicalNameMapper nameMapper, Clock clock) { super(clock); From ffd320f40d0cae289f730886662c2b255e1eed54 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Fri, 26 Jan 2024 03:38:01 -0800 Subject: [PATCH 03/73] Add sample for MultiGauge (#4618) --- .../core/samples/MultiGaugeSample.java | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 samples/micrometer-samples-core/src/main/java/io/micrometer/core/samples/MultiGaugeSample.java diff --git a/samples/micrometer-samples-core/src/main/java/io/micrometer/core/samples/MultiGaugeSample.java b/samples/micrometer-samples-core/src/main/java/io/micrometer/core/samples/MultiGaugeSample.java new file mode 100644 index 0000000000..40a640ae48 --- /dev/null +++ b/samples/micrometer-samples-core/src/main/java/io/micrometer/core/samples/MultiGaugeSample.java @@ -0,0 +1,87 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.core.samples; + +import io.micrometer.core.instrument.MultiGauge; +import io.micrometer.core.instrument.MultiGauge.Row; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class MultiGaugeSample { + + public static void main(String[] args) { + // MeterRegistry registry = SampleConfig.myMonitoringSystem(); + SimpleMeterRegistry registry = new SimpleMeterRegistry(); + + MultiGauge temperatures = MultiGauge.builder("temperatures") + .tag("home", "little-house") + .description("The temperature by room") + .baseUnit("celsius") + .register(registry); + + // @formatter:off + for (int i = 0; i < 3; i++) { + temperatures.register( + fetchTemperatures().stream() + .map(record -> Row.of(Tags.of("room", record.getRoom().name()), record.getTemperature())) + .collect(Collectors.toList()), + true // whether to overwrite the previous value or only record it once + ); + + System.out.println("---"); + System.out.println(registry.getMetersAsString()); + } + // @formatter:on + } + + private static List fetchTemperatures() { + return Arrays.stream(Room.values()) + .map(room -> new TemperatureRecord(room, Math.random() * 3 + 20)) + .collect(Collectors.toList()); + } + + private enum Room { + + LIVING_ROOM, BEDROOM, KITCHEN + + } + + private static class TemperatureRecord { + + private final Room room; + + private final double temperature; + + private TemperatureRecord(Room room, double temperature) { + this.room = room; + this.temperature = temperature; + } + + public Room getRoom() { + return room; + } + + public double getTemperature() { + return temperature; + } + + } + +} From 271c7c302eb5f7bea32ac82b11867855cb014cf5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 15:53:11 +0900 Subject: [PATCH 04/73] Bump gradle/wrapper-validation-action from 1 to 2 (#4619) Bumps [gradle/wrapper-validation-action](https://github.com/gradle/wrapper-validation-action) from 1 to 2. - [Release notes](https://github.com/gradle/wrapper-validation-action/releases) - [Commits](https://github.com/gradle/wrapper-validation-action/compare/v1...v2) --- updated-dependencies: - dependency-name: gradle/wrapper-validation-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/gradle-wrapper-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index c87c892efb..cf2c086a06 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -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 From b77135915134d4d5c750d2e3e2db5de6996e7b07 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Tue, 30 Jan 2024 18:22:16 +0900 Subject: [PATCH 05/73] Clarify time window length in docs Users would have had to read the JavaDocs or look at the implementation to understand that the window length is the `expiry` * `bufferLength`. Updated the docs to explicitly call that out. Closes gh-4625 --- docs/modules/ROOT/pages/concepts/distribution-summaries.adoc | 3 ++- docs/modules/ROOT/pages/concepts/timers.adoc | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/concepts/distribution-summaries.adoc b/docs/modules/ROOT/pages/concepts/distribution-summaries.adoc index fc7e3dea3e..f1061285ff 100644 --- a/docs/modules/ROOT/pages/concepts/distribution-summaries.adoc +++ b/docs/modules/ROOT/pages/concepts/distribution-summaries.adoc @@ -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`). diff --git a/docs/modules/ROOT/pages/concepts/timers.adoc b/docs/modules/ROOT/pages/concepts/timers.adoc index 980f30cf35..1499581e58 100644 --- a/docs/modules/ROOT/pages/concepts/timers.adoc +++ b/docs/modules/ROOT/pages/concepts/timers.adoc @@ -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. From 864f58a9af34df4c106c893cf002c1a1ba598a86 Mon Sep 17 00:00:00 2001 From: David Molina Estrada Date: Wed, 31 Jan 2024 04:34:03 +0100 Subject: [PATCH 06/73] Avoid getting convention name multiple times for same input (#4608) Unify the collector name passing the first calculated name (in PrometheusMeterRegistry.getConventionName(id)) to MicrometerCollector constructor. Closes gh-4607 --- .../prometheus/MicrometerCollector.java | 7 +++ .../prometheus/PrometheusMeterRegistry.java | 2 +- .../PrometheusMeterRegistryCustomizeTest.java | 50 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java diff --git a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java index 521a8ca875..9e2086b591 100644 --- a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java +++ b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java @@ -51,6 +51,13 @@ public MicrometerCollector(Meter.Id id, NamingConvention convention, PrometheusC this.help = config.descriptions() ? Optional.ofNullable(id.getDescription()).orElse(" ") : " "; } + public MicrometerCollector(String name, Meter.Id id, NamingConvention convention, PrometheusConfig config) { + this.id = id; + this.conventionName = name; + this.tagKeys = id.getConventionTags(convention).stream().map(Tag::getKey).collect(toList()); + this.help = config.descriptions() ? Optional.ofNullable(id.getDescription()).orElse(" ") : " "; + } + public void add(List tagValues, Child child) { children.put(tagValues, child); } diff --git a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusMeterRegistry.java b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusMeterRegistry.java index dba52a2c9d..b69032c7ac 100644 --- a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusMeterRegistry.java +++ b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusMeterRegistry.java @@ -575,7 +575,7 @@ private void onMeterRemoved(Meter meter) { private void applyToCollector(Meter.Id id, Consumer consumer) { collectorMap.compute(getConventionName(id), (name, existingCollector) -> { if (existingCollector == null) { - MicrometerCollector micrometerCollector = new MicrometerCollector(id, config().namingConvention(), + MicrometerCollector micrometerCollector = new MicrometerCollector(name, id, config().namingConvention(), prometheusConfig); consumer.accept(micrometerCollector); return micrometerCollector.register(registry); diff --git a/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java b/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java new file mode 100644 index 0000000000..916062aa47 --- /dev/null +++ b/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.prometheus; + +import io.micrometer.core.instrument.Counter; +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.MockClock; +import io.prometheus.client.CollectorRegistry; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class PrometheusMeterRegistryCustomizeTest { + + private final CollectorRegistry prometheusRegistry = new CollectorRegistry(true); + + private final MockClock clock = new MockClock(); + + private final PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT, + prometheusRegistry, clock) { + + @Override + protected String getConventionName(Meter.Id id) { + return "custom_prefix_" + super.getConventionName(id); + } + }; + + @DisplayName("registered counter collector name is the same that calculated by PrometheusMeterRegistry") + @Test + void customNamedCollectorName() { + Counter.builder("counter").description("my counter").register(registry); + assertThat(this.registry.getPrometheusRegistry().metricFamilySamples().nextElement().name) + .isEqualTo("custom_prefix_counter"); + } + +} From f2fa7a3f5422c40fc02d4bfa4decfc9e1b77fdfb Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:46:19 +0900 Subject: [PATCH 07/73] Polish Polish gh-4608 The test was not testing the changes made (it would have passed before the changes to main code), so I removed it. Removed the unused constructor in MicrometerCollector because it is a package private class we know all the callsites. --- .../prometheus/MicrometerCollector.java | 11 ++-- .../prometheus/MicrometerCollectorTest.java | 8 ++- .../PrometheusMeterRegistryCustomizeTest.java | 50 ------------------- 3 files changed, 9 insertions(+), 60 deletions(-) delete mode 100644 implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java diff --git a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java index 9e2086b591..92d76d97a2 100644 --- a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java +++ b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/MicrometerCollector.java @@ -44,14 +44,9 @@ class MicrometerCollector extends Collector implements Collector.Describable { private final String help; - public MicrometerCollector(Meter.Id id, NamingConvention convention, PrometheusConfig config) { - this.id = id; - this.conventionName = id.getConventionName(convention); - this.tagKeys = id.getConventionTags(convention).stream().map(Tag::getKey).collect(toList()); - this.help = config.descriptions() ? Optional.ofNullable(id.getDescription()).orElse(" ") : " "; - } - - public MicrometerCollector(String name, Meter.Id id, NamingConvention convention, PrometheusConfig config) { + // take name to avoid calling NamingConvention#name after the callsite has already + // done it + MicrometerCollector(String name, Meter.Id id, NamingConvention convention, PrometheusConfig config) { this.id = id; this.conventionName = name; this.tagKeys = id.getConventionTags(convention).stream().map(Tag::getKey).collect(toList()); diff --git a/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/MicrometerCollectorTest.java b/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/MicrometerCollectorTest.java index 8e0cbe2a07..233d8d9d4c 100644 --- a/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/MicrometerCollectorTest.java +++ b/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/MicrometerCollectorTest.java @@ -31,11 +31,14 @@ class MicrometerCollectorTest { + NamingConvention convention = NamingConvention.snakeCase; + @Issue("#769") @Test void manyTags() { Meter.Id id = Metrics.counter("my.counter").getId(); - MicrometerCollector collector = new MicrometerCollector(id, NamingConvention.dot, PrometheusConfig.DEFAULT); + MicrometerCollector collector = new MicrometerCollector(id.getConventionName(convention), id, convention, + PrometheusConfig.DEFAULT); for (Integer i = 0; i < 20_000; i++) { Collector.MetricFamilySamples.Sample sample = new Collector.MetricFamilySamples.Sample("my_counter", @@ -52,7 +55,8 @@ void manyTags() { @Test void sameValuesDifferentOrder() { Meter.Id id = Metrics.counter("my.counter").getId(); - MicrometerCollector collector = new MicrometerCollector(id, NamingConvention.dot, PrometheusConfig.DEFAULT); + MicrometerCollector collector = new MicrometerCollector(id.getConventionName(convention), id, convention, + PrometheusConfig.DEFAULT); Collector.MetricFamilySamples.Sample sample = new Collector.MetricFamilySamples.Sample("my_counter", asList("k", "k2"), asList("v1", "v2"), 1.0); diff --git a/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java b/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java deleted file mode 100644 index 916062aa47..0000000000 --- a/implementations/micrometer-registry-prometheus/src/test/java/io/micrometer/prometheus/PrometheusMeterRegistryCustomizeTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2024 VMware, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.micrometer.prometheus; - -import io.micrometer.core.instrument.Counter; -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MockClock; -import io.prometheus.client.CollectorRegistry; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -class PrometheusMeterRegistryCustomizeTest { - - private final CollectorRegistry prometheusRegistry = new CollectorRegistry(true); - - private final MockClock clock = new MockClock(); - - private final PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT, - prometheusRegistry, clock) { - - @Override - protected String getConventionName(Meter.Id id) { - return "custom_prefix_" + super.getConventionName(id); - } - }; - - @DisplayName("registered counter collector name is the same that calculated by PrometheusMeterRegistry") - @Test - void customNamedCollectorName() { - Counter.builder("counter").description("my counter").register(registry); - assertThat(this.registry.getPrometheusRegistry().metricFamilySamples().nextElement().name) - .isEqualTo("custom_prefix_counter"); - } - -} From 7260e1389bdf4bbebce0853fcd491c68956db58b Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Wed, 31 Jan 2024 12:51:01 +0900 Subject: [PATCH 08/73] Polish (#4627) --- .../io/micrometer/prometheus/PrometheusTimer.java | 2 +- .../instrument/binder/logging/Log4j2Metrics.java | 13 ++++++------- .../http/HttpJakartaServletRequestTagsTest.java | 6 +++--- .../jms/DefaultJmsPublishObservationConvention.java | 10 ++++------ ...DefaultJmsPublishObservationConventionTests.java | 6 +++--- 5 files changed, 17 insertions(+), 20 deletions(-) diff --git a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusTimer.java b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusTimer.java index d5f058a124..5f952197fa 100644 --- a/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusTimer.java +++ b/implementations/micrometer-registry-prometheus/src/main/java/io/micrometer/prometheus/PrometheusTimer.java @@ -115,7 +115,7 @@ protected void recordNonNegative(long amount, TimeUnit unit) { } if (!histogramExemplarsEnabled && exemplarSampler != null) { - updateLastExemplar(TimeUtils.nanosToUnit(amount, this.baseTimeUnit()), exemplarSampler); + updateLastExemplar(TimeUtils.nanosToUnit(amount, baseTimeUnit()), exemplarSampler); } } diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/logging/Log4j2Metrics.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/logging/Log4j2Metrics.java index e7b7d73b12..2d19fd8ff1 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/logging/Log4j2Metrics.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/logging/Log4j2Metrics.java @@ -40,11 +40,11 @@ /** * {@link MeterBinder} for Apache Log4j 2. Please use at least 2.21.0 since there was a * bug in earlier versions that prevented Micrometer to increment its counters correctly. - * See: - * logging-log4j2#1550 - * See: micrometer#2176 * + * @see logging-log4j2#1550 + * @see micrometer#2176 * @author Steven Sheehy * @author Johnny Lim * @since 1.1.0 @@ -76,7 +76,6 @@ public Log4j2Metrics(Iterable tags, LoggerContext loggerContext) { @Override public void bindTo(MeterRegistry registry) { - Configuration configuration = loggerContext.getConfiguration(); LoggerConfig rootLoggerConfig = configuration.getRootLogger(); rootLoggerConfig.addFilter(createMetricsFilterAndStart(registry)); @@ -92,9 +91,9 @@ public void bindTo(MeterRegistry registry) { } Filter logFilter = loggerConfig.getFilter(); - if ((logFilter instanceof CompositeFilter + if (logFilter instanceof CompositeFilter && Arrays.stream(((CompositeFilter) logFilter).getFiltersArray()) - .anyMatch(innerFilter -> innerFilter instanceof MetricsFilter))) { + .anyMatch(innerFilter -> innerFilter instanceof MetricsFilter)) { return; } diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/http/HttpJakartaServletRequestTagsTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/http/HttpJakartaServletRequestTagsTest.java index 072ea2c2ab..543f75ea64 100644 --- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/http/HttpJakartaServletRequestTagsTest.java +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/http/HttpJakartaServletRequestTagsTest.java @@ -107,14 +107,14 @@ void nullResponseShouldContributeUnknownOutcomeTag() { @Test void responseShouldContributeOutcomeTag() { - Tag unknownOutcome = Tag.of("outcome", "SUCCESS"); + Tag successOutcome = Tag.of("outcome", "SUCCESS"); HttpServletResponse jakartaResponse = mockJakartaResponse(200); Tag result = HttpJakartaServletRequestTags.outcome(jakartaResponse); - assertThat(result).isEqualTo(unknownOutcome); + assertThat(result).isEqualTo(successOutcome); javax.servlet.http.HttpServletResponse javaxResponse = mockJavaxResponse(200); result = HttpRequestTags.outcome(javaxResponse); - assertThat(result).isEqualTo(unknownOutcome); + assertThat(result).isEqualTo(successOutcome); } private HttpServletRequest mockJakartaRequest(String method) { diff --git a/micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConvention.java b/micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConvention.java index 8a6ed5c22f..bb672b09b0 100644 --- a/micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConvention.java +++ b/micrometer-jakarta9/src/main/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConvention.java @@ -117,10 +117,9 @@ protected KeyValue destinationName(JmsPublishObservationContext context) { if (jmsDestination instanceof Queue) { Queue queue = (Queue) jmsDestination; String queueName = queue.getQueueName(); - if (queueName == null) { - return getKeyValueTopic(jmsDestination); + if (queueName != null) { + return KeyValue.of(HighCardinalityKeyNames.DESTINATION_NAME, queueName); } - return KeyValue.of(HighCardinalityKeyNames.DESTINATION_NAME, queueName); } return getKeyValueTopic(jmsDestination); } @@ -133,10 +132,9 @@ private static KeyValue getKeyValueTopic(Destination jmsDestination) throws JMSE if (jmsDestination instanceof Topic) { Topic topic = (Topic) jmsDestination; String topicName = topic.getTopicName(); - if (topicName == null) { - return DESTINATION_NAME_UNKNOWN; + if (topicName != null) { + return KeyValue.of(HighCardinalityKeyNames.DESTINATION_NAME, topicName); } - return KeyValue.of(HighCardinalityKeyNames.DESTINATION_NAME, topicName); } return DESTINATION_NAME_UNKNOWN; } diff --git a/micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConventionTests.java b/micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConventionTests.java index 54346d8bb6..dfba9acba8 100644 --- a/micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConventionTests.java +++ b/micrometer-jakarta9/src/test/java/io/micrometer/jakarta9/instrument/jms/DefaultJmsPublishObservationConventionTests.java @@ -96,8 +96,8 @@ void shouldHaveTopicDestinationName() throws Exception { } @Test - void shouldHaveTopicNullDestinationName() throws Exception { - JmsPublishObservationContext context = new JmsPublishObservationContext(createMessageWithNullTopic()); + void shouldHaveUnknownDestinationNameWhenTopicNameIsNull() throws Exception { + JmsPublishObservationContext context = new JmsPublishObservationContext(createMessageWithNullTopicName()); assertThat(convention.getHighCardinalityKeyValues(context)) .contains(KeyValue.of("messaging.destination.name", "unknown")); } @@ -210,7 +210,7 @@ private Message createMessageWithTopic() throws Exception { return message; } - private Message createMessageWithNullTopic() throws Exception { + private Message createMessageWithNullTopicName() throws Exception { Topic topic = mock(Topic.class); when(topic.getTopicName()).thenReturn(null); Message message = mock(Message.class); From 33bb26754d6f4821abbfda0c9aa0f1fd9215128a Mon Sep 17 00:00:00 2001 From: Gregor Zeitlinger Date: Wed, 31 Jan 2024 05:23:53 +0100 Subject: [PATCH 09/73] URL decode headers from environment variables in OtlpConfig (#4595) The headers from environment variables are expected to be URL encoded according to the spec. This change tries to URL decode them. See https://github.com/open-telemetry/opentelemetry-specification/issues/3832 See https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables --- .../io/micrometer/registry/otlp/OtlpConfig.java | 9 +++++++++ .../micrometer/registry/otlp/OtlpConfigTest.java | 16 ++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java index bbb260f806..d6910e5a53 100644 --- a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java +++ b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java @@ -18,6 +18,7 @@ import io.micrometer.core.instrument.config.validate.Validated; import io.micrometer.core.instrument.push.PushRegistryConfig; +import java.net.URLDecoder; import java.util.Arrays; import java.util.Map; import java.util.Objects; @@ -131,6 +132,14 @@ default Map headers() { headersString = env.getOrDefault("OTEL_EXPORTER_OTLP_HEADERS", "").trim(); String metricsHeaders = env.getOrDefault("OTEL_EXPORTER_OTLP_METRICS_HEADERS", "").trim(); headersString = Objects.equals(headersString, "") ? metricsHeaders : headersString + "," + metricsHeaders; + try { + // headers are encoded as URL - see + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md#specifying-headers-via-environment-variables + headersString = URLDecoder.decode(headersString, "UTF-8"); + } + catch (Exception e) { + throw new IllegalArgumentException("Cannot decode header value: " + headersString, e); + } } String[] keyValues = Objects.equals(headersString, "") ? new String[] {} : headersString.split(","); diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java index b0ebb4a203..5ec6d688e7 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java @@ -23,6 +23,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariable; import static uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariables; @@ -62,8 +63,19 @@ void headersConfigTakesPrecedenceOverEnvVars() throws Exception { @Test void headersUseEnvVarWhenConfigNotSet() throws Exception { OtlpConfig config = k -> null; - withEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS", "header2=value") - .execute(() -> assertThat(config.headers()).containsEntry("header2", "value").hasSize(1)); + withEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS", "header2=va%20lue,header3=f oo") + .execute(() -> assertThat(config.headers()).containsEntry("header2", "va lue") + .containsEntry("header3", "f oo") + .hasSize(2)); + } + + @Test + void headersDecodingError() throws Exception { + OtlpConfig config = k -> null; + withEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS", "header2=%-1").execute(() -> { + assertThatThrownBy(config::headers).isInstanceOf(IllegalArgumentException.class) + .hasMessage("Cannot decode header value: header2=%-1,"); + }); } @Test From 3a6923d980d543af045a7a9fa9bbfce9cd398980 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 13:44:11 +0900 Subject: [PATCH 10/73] Polish Polish gh-4595 --- .../io/micrometer/registry/otlp/OtlpConfig.java | 3 ++- .../micrometer/registry/otlp/OtlpConfigTest.java | 5 +++-- .../config/InvalidConfigurationException.java | 14 ++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java index d6910e5a53..a735d097e9 100644 --- a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java +++ b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java @@ -15,6 +15,7 @@ */ package io.micrometer.registry.otlp; +import io.micrometer.core.instrument.config.InvalidConfigurationException; import io.micrometer.core.instrument.config.validate.Validated; import io.micrometer.core.instrument.push.PushRegistryConfig; @@ -138,7 +139,7 @@ default Map headers() { headersString = URLDecoder.decode(headersString, "UTF-8"); } catch (Exception e) { - throw new IllegalArgumentException("Cannot decode header value: " + headersString, e); + throw new InvalidConfigurationException("Cannot URL decode header value: " + headersString, e); } } diff --git a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java index 5ec6d688e7..b45ae85391 100644 --- a/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java +++ b/implementations/micrometer-registry-otlp/src/test/java/io/micrometer/registry/otlp/OtlpConfigTest.java @@ -15,6 +15,7 @@ */ package io.micrometer.registry.otlp; +import io.micrometer.core.instrument.config.InvalidConfigurationException; import org.junit.jupiter.api.Test; import java.util.Collections; @@ -73,8 +74,8 @@ void headersUseEnvVarWhenConfigNotSet() throws Exception { void headersDecodingError() throws Exception { OtlpConfig config = k -> null; withEnvironmentVariable("OTEL_EXPORTER_OTLP_HEADERS", "header2=%-1").execute(() -> { - assertThatThrownBy(config::headers).isInstanceOf(IllegalArgumentException.class) - .hasMessage("Cannot decode header value: header2=%-1,"); + assertThatThrownBy(config::headers).isInstanceOf(InvalidConfigurationException.class) + .hasMessage("Cannot URL decode header value: header2=%-1,"); }); } diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/config/InvalidConfigurationException.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/config/InvalidConfigurationException.java index 3369193b43..69e4d7700b 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/config/InvalidConfigurationException.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/config/InvalidConfigurationException.java @@ -21,6 +21,20 @@ */ public class InvalidConfigurationException extends IllegalStateException { + /** + * Construct an exception indication invalid configuration with the specified detail + * message and cause. + * @param message the detail message (which is saved for later retrieval by the + * {@link Throwable#getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link Throwable#getCause()} method). (A {@code null} value is permitted, and + * indicates that the cause is nonexistent or unknown.) + * @since 1.11.9 + */ + public InvalidConfigurationException(String message, Throwable cause) { + super(message, cause); + } + public InvalidConfigurationException(String s) { super(s); } From 640ec2fb1d8f0a77d76f78b854f36df12d271d74 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 18:28:56 +0900 Subject: [PATCH 11/73] Upgrade CI image JDK to 8.0.402, 11.0.22, 17.0.10, 21.0.2 Closes gh-4630 --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 036f362a9c..78216c7b1a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -12,19 +12,19 @@ executors: environment: GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' docker: - - image: cimg/openjdk:17.0.9 + - image: cimg/openjdk:17.0.10 circle-jdk8-executor: working_directory: ~/micrometer environment: GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' docker: - - image: cimg/openjdk:8.0.392 + - image: cimg/openjdk:8.0.402 circle-jdk11-executor: working_directory: ~/micrometer environment: GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' docker: - - image: cimg/openjdk:11.0.21 + - image: cimg/openjdk:11.0.22 machine-executor: working_directory: ~/micrometer machine: From 22b48c2aa3a02853597f28e691761b04904f5aa6 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 18:40:40 +0900 Subject: [PATCH 12/73] Upgrade CI machine image to ubuntu-2204:2024.01.1 Closes gh-4631 --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 78216c7b1a..f900280b9f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,7 +28,7 @@ executors: machine-executor: working_directory: ~/micrometer machine: - image: ubuntu-2204:2023.10.1 + image: ubuntu-2204:2024.01.1 commands: gradlew-build: From f53d61adfa348c2bf52c272d2292bcdcab8f687b Mon Sep 17 00:00:00 2001 From: Dimo Velev Date: Wed, 31 Jan 2024 12:30:23 +0100 Subject: [PATCH 13/73] Close Stackdriver client after closing registry (#4358) Do not close the client before `close` has finished as `close` publishes the metrics one last time. Close the client upon start if necessary so that multiple stop/start cycles would not leak clients. Fixes gh-4353 --------- Co-authored-by: Dimo Velev --- .../stackdriver/StackdriverMeterRegistry.java | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java index 4110da914e..909a4b371c 100644 --- a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java +++ b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java @@ -125,6 +125,7 @@ public void start(ThreadFactory threadFactory) { logger.error("unable to start stackdriver, service settings are not available"); } else { + shutdownClientIfNecessary(true); try { this.client = MetricServiceClient.create(metricServiceSettings); super.start(threadFactory); @@ -138,11 +139,57 @@ public void start(ThreadFactory threadFactory) { @Override public void stop() { - if (client != null) - client.shutdownNow(); super.stop(); } + @Override + public void close() { + try { + super.close(); + } + finally { + shutdownClientIfNecessary(false); + } + } + + protected void shutdownClientIfNecessary(final boolean quietly) { + if (client != null) { + if (!client.isShutdown()) { + try { + client.shutdownNow(); + final boolean terminated = client.awaitTermination(10, TimeUnit.SECONDS); + if (!terminated) { + logger.warn("The metric service client failed to terminate within the timeout"); + } + } + catch (final RuntimeException e) { + if (quietly) { + logger.warn("Failed to shutdown the metric service client", e); + } + else { + throw e; + } + } + catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + } + try { + client.close(); + } + catch (final RuntimeException e) { + if (quietly) { + logger.warn("Failed to close metric service client", e); + } + else { + throw e; + } + } + client = null; + } + } + @Override protected void publish() { if (client == null) { From 3326c107d5e854399f334e6485ce9cb8ce7d40c4 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 20:50:39 +0900 Subject: [PATCH 14/73] Polish gh-4358 No need to override the `stop` method and reduces the indentation on shutdownClientIfNecessary. --- .../stackdriver/StackdriverMeterRegistry.java | 57 +++++++++---------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java index 909a4b371c..5eccdf95d2 100644 --- a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java +++ b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java @@ -137,11 +137,6 @@ public void start(ThreadFactory threadFactory) { } } - @Override - public void stop() { - super.stop(); - } - @Override public void close() { try { @@ -152,42 +147,42 @@ public void close() { } } - protected void shutdownClientIfNecessary(final boolean quietly) { - if (client != null) { - if (!client.isShutdown()) { - try { - client.shutdownNow(); - final boolean terminated = client.awaitTermination(10, TimeUnit.SECONDS); - if (!terminated) { - logger.warn("The metric service client failed to terminate within the timeout"); - } - } - catch (final RuntimeException e) { - if (quietly) { - logger.warn("Failed to shutdown the metric service client", e); - } - else { - throw e; - } - } - catch (final InterruptedException e) { - Thread.currentThread().interrupt(); - return; - } - } + private void shutdownClientIfNecessary(final boolean quietly) { + if (client == null) + return; + if (!client.isShutdown()) { try { - client.close(); + client.shutdownNow(); + final boolean terminated = client.awaitTermination(10, TimeUnit.SECONDS); + if (!terminated) { + logger.warn("The metric service client failed to terminate within the timeout"); + } } catch (final RuntimeException e) { if (quietly) { - logger.warn("Failed to close metric service client", e); + logger.warn("Failed to shutdown the metric service client", e); } else { throw e; } } - client = null; + catch (final InterruptedException e) { + Thread.currentThread().interrupt(); + return; + } + } + try { + client.close(); + } + catch (final RuntimeException e) { + if (quietly) { + logger.warn("Failed to close metric service client", e); + } + else { + throw e; + } } + client = null; } @Override From 400c7e25625b35824e5f2256d9d584db1b507711 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Wed, 31 Jan 2024 21:05:36 +0900 Subject: [PATCH 15/73] Add back override stop for binary compatibility Binary compatibility breaks when removing the otherwise unnecessary override. --- .../io/micrometer/stackdriver/StackdriverMeterRegistry.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java index 5eccdf95d2..556ae6137f 100644 --- a/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java +++ b/implementations/micrometer-registry-stackdriver/src/main/java/io/micrometer/stackdriver/StackdriverMeterRegistry.java @@ -147,6 +147,11 @@ public void close() { } } + @Override + public void stop() { + super.stop(); + } + private void shutdownClientIfNecessary(final boolean quietly) { if (client == null) return; From 1b0e423546818e2bb59c655ccbb886ea0469fada Mon Sep 17 00:00:00 2001 From: Georg Pirklbauer Date: Wed, 31 Jan 2024 13:23:25 +0100 Subject: [PATCH 16/73] [Dynatrace] Logging verbosity: Move metadata discrepancy logging to WarnThenDebug (#4583) Move Metadata discrepancy logging to WarnThenDebug because this is an instrumentation mismatch with the Dynatrace model that end users cannot fix, so flooding them with warn logs is not productive. --- .../dynatrace/v2/DynatraceExporterV2.java | 32 ++-- .../dynatrace/v2/WarnThenDebugLoggers.java | 54 +++++++ .../dynatrace/v2/DynatraceExporterV2Test.java | 144 ++++++++++++++++-- 3 files changed, 204 insertions(+), 26 deletions(-) create mode 100644 implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/WarnThenDebugLoggers.java diff --git a/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/DynatraceExporterV2.java b/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/DynatraceExporterV2.java index a014e63235..b32cb11220 100644 --- a/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/DynatraceExporterV2.java +++ b/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/DynatraceExporterV2.java @@ -60,18 +60,18 @@ public final class DynatraceExporterV2 extends AbstractDynatraceExporter { private static final Pattern IS_NULL_ERROR_RESPONSE = Pattern.compile("\"error\":\\s?null"); - private static final WarnThenDebugLogger stackTraceWarnThenDebugLogger = new WarnThenDebugLogger( - DynatraceExporterV2.class); - - private static final WarnThenDebugLogger nanGaugeWarnThenDebugLogger = new WarnThenDebugLogger( - DynatraceExporterV2.class); - private static final Map staticDimensions = Collections.singletonMap("dt.metrics.source", "micrometer"); - // This should be non-static for MockLoggerFactory.injectLogger() in tests. + // Loggers must be non-static for MockLoggerFactory.injectLogger() in tests. private final InternalLogger logger = InternalLoggerFactory.getInstance(DynatraceExporterV2.class); + private final WarnThenDebugLogger stackTraceLogger = new WarnThenDebugLoggers.StackTraceLogger(); + + private final WarnThenDebugLogger nanGaugeLogger = new WarnThenDebugLoggers.NanGaugeLogger(); + + private final WarnThenDebugLogger metadataDiscrepancyLogger = new WarnThenDebugLoggers.MetadataDiscrepancyLogger(); + private MetricLinePreConfiguration preConfiguration; private boolean skipExport = false; @@ -219,7 +219,7 @@ private String createGaugeLine(Meter meter, Map seenMetadata, Me // NaN's are currently dropped on the Dynatrace side, so dropping them // on the client side here will not change the metrics in Dynatrace. - nanGaugeWarnThenDebugLogger.log(() -> String.format( + nanGaugeLogger.log(() -> String.format( "Meter '%s' returned a value of NaN, which will not be exported. This can be a deliberate value or because the weak reference to the backing object expired.", meter.getId().getName())); return null; @@ -418,9 +418,11 @@ private void send(List metricLines) { response.code(), getTruncatedBody(response))); } catch (Throwable throwable) { - logger.warn("Failed metric ingestion: " + throwable); - stackTraceWarnThenDebugLogger.log("Stack trace for previous 'Failed metric ingestion' warning log: ", - throwable); + // the "general" logger logs the message, the WarnThenDebugLogger logs the + // stack trace. + logger.warn("Failed metric ingestion: {}", throwable.toString()); + stackTraceLogger.log(String.format("Stack trace for previous 'Failed metric ingestion' warning log: %s", + throwable.getMessage()), throwable); } } @@ -501,10 +503,10 @@ private void storeMetadata(MetricLineBuilder.MetadataStep metadataStep, Map String.format( + "Metadata discrepancy detected:\n" + "original metadata:\t%s\n" + "tried to set new:\t%s\n" + + "Metadata for metric key %s will not be sent.", + previousMetadataLine, metadataLine, key)); } } // else: diff --git a/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/WarnThenDebugLoggers.java b/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/WarnThenDebugLoggers.java new file mode 100644 index 0000000000..bef7df8311 --- /dev/null +++ b/implementations/micrometer-registry-dynatrace/src/main/java/io/micrometer/dynatrace/v2/WarnThenDebugLoggers.java @@ -0,0 +1,54 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.dynatrace.v2; + +import io.micrometer.common.util.internal.logging.WarnThenDebugLogger; + +/** + * This internal class holds loggers that are used in {@link DynatraceExporterV2}. They + * are all just extending the default {@link WarnThenDebugLogger}. It is necessary to + * extend them, because the {@link WarnThenDebugLogger} does not allow creating a new + * logger with just a name (a class object has to be passed). Creating the + * WarnThenDebugLogger with the same class multiple times makes it impossible to test, as + * the MockLoggerFactory will ignore multiple loggers with the same name. + */ +class WarnThenDebugLoggers { + + static class StackTraceLogger extends WarnThenDebugLogger { + + public StackTraceLogger() { + super(StackTraceLogger.class); + } + + } + + static class NanGaugeLogger extends WarnThenDebugLogger { + + public NanGaugeLogger() { + super(NanGaugeLogger.class); + } + + } + + static class MetadataDiscrepancyLogger extends WarnThenDebugLogger { + + public MetadataDiscrepancyLogger() { + super(MetadataDiscrepancyLogger.class); + } + + } + +} diff --git a/implementations/micrometer-registry-dynatrace/src/test/java/io/micrometer/dynatrace/v2/DynatraceExporterV2Test.java b/implementations/micrometer-registry-dynatrace/src/test/java/io/micrometer/dynatrace/v2/DynatraceExporterV2Test.java index 33069fb6ec..47dc8691cf 100644 --- a/implementations/micrometer-registry-dynatrace/src/test/java/io/micrometer/dynatrace/v2/DynatraceExporterV2Test.java +++ b/implementations/micrometer-registry-dynatrace/src/test/java/io/micrometer/dynatrace/v2/DynatraceExporterV2Test.java @@ -27,7 +27,6 @@ import io.micrometer.dynatrace.DynatraceApiVersion; import io.micrometer.dynatrace.DynatraceConfig; import io.micrometer.dynatrace.DynatraceMeterRegistry; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -45,7 +44,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; -import static io.micrometer.common.util.internal.logging.InternalLogLevel.ERROR; +import static io.micrometer.common.util.internal.logging.InternalLogLevel.*; import static io.micrometer.core.instrument.MockClock.clock; import static java.lang.Double.*; import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -64,9 +63,9 @@ */ class DynatraceExporterV2Test { - private static final MockLoggerFactory FACTORY = new MockLoggerFactory(); + private MockLoggerFactory loggerFactory; - private static final MockLogger LOGGER = FACTORY.getLogger(DynatraceExporterV2.class); + private MockLogger logger; private static final Map SEEN_METADATA = new HashMap<>(); @@ -80,6 +79,8 @@ class DynatraceExporterV2Test { private DynatraceExporterV2 exporter; + private static final String subsequentLogsAsDebug = "Note that subsequent logs will be logged at debug level."; + @BeforeEach void setUp() { this.config = createDefaultDynatraceConfig(); @@ -90,18 +91,19 @@ void setUp() { // library will not // complain. this.httpClient = mock(HttpSender.class); - this.exporter = FACTORY.injectLogger(() -> createExporter(httpClient)); + + // ensures new MockLoggers are created for each test. + // Since there are some asserts on log lines, different test runs do not reuse the + // same loggers and thus do not interfere. + this.loggerFactory = new MockLoggerFactory(); + this.exporter = loggerFactory.injectLogger(() -> createExporter(httpClient)); + this.logger = loggerFactory.getLogger(DynatraceExporterV2.class); this.meterRegistry = DynatraceMeterRegistry.builder(config).clock(clock).httpClient(httpClient).build(); SEEN_METADATA.clear(); } - @AfterEach - void tearDown() { - LOGGER.clear(); - } - @Test void toGaugeLine() { meterRegistry.gauge("my.gauge", 1.23); @@ -118,6 +120,27 @@ void toGaugeLineShouldDropNanValue() { assertThat(exporter.toGaugeLine(gauge, SEEN_METADATA)).isEmpty(); } + @Test + void toGaugeLineShouldDropNanValue_testLogWarnThenDebug() { + MockLogger nanGaugeLogger = loggerFactory.getLogger(WarnThenDebugLoggers.NanGaugeLogger.class); + + String expectedMessage = "Meter 'my.gauge' returned a value of NaN, which will not be exported. This can be a deliberate value or because the weak reference to the backing object expired."; + + LogEvent warnEvent = new LogEvent(WARN, String.join(" ", expectedMessage, subsequentLogsAsDebug), null); + LogEvent debugEvent = new LogEvent(DEBUG, expectedMessage, null); + + meterRegistry.gauge("my.gauge", NaN); + Gauge gauge = meterRegistry.find("my.gauge").gauge(); + + // first export; log at warn + assertThat(exporter.toGaugeLine(gauge, SEEN_METADATA)).isEmpty(); + assertThat(nanGaugeLogger.getLogEvents()).hasSize(1).containsExactly(warnEvent); + + // second export; log at debug + assertThat(exporter.toGaugeLine(gauge, SEEN_METADATA)).isEmpty(); + assertThat(nanGaugeLogger.getLogEvents()).hasSize(2).containsExactly(warnEvent, debugEvent); + } + @Test void toGaugeLineShouldDropInfiniteValues() { meterRegistry.gauge("my.gauge", POSITIVE_INFINITY); @@ -652,10 +675,67 @@ void failOnSendShouldHaveProperLogging() throws Throwable { Gauge gauge = meterRegistry.find("my.gauge").gauge(); exporter.export(Collections.singletonList(gauge)); - assertThat(LOGGER.getLogEvents()) + assertThat(logger.getLogEvents()) .contains(new LogEvent(ERROR, "Failed metric ingestion: Error Code=500, Response Body=simulated", null)); } + @Test + void failOnSendWithExceptionShouldHaveProperLogging_warnThenDebug() { + MockLogger stackTraceLogger = loggerFactory.getLogger(WarnThenDebugLoggers.StackTraceLogger.class); + + Throwable expectedException = new RuntimeException("test exception", new Throwable("root cause exception")); + when(httpClient.post(config.uri())).thenThrow(expectedException); + + // the "general" logger just logs the message, the WarnThenDebugLogger contains + // the exception & stack trace. + String expectedWarnThenDebugMessage = "Stack trace for previous 'Failed metric ingestion' warning log:"; + // these two will be logged by the WarnThenDebugLogger: + // the warning message is suffixed with "Note that subsequent logs will be logged + // at debug level.". + LogEvent warnThenDebugWarningLog = new LogEvent(WARN, + String.join(" ", expectedWarnThenDebugMessage, expectedException.getMessage(), subsequentLogsAsDebug), + expectedException); + LogEvent warnThenDebugDebugLog = new LogEvent(DEBUG, + String.join(" ", expectedWarnThenDebugMessage, expectedException.getMessage()), expectedException); + + // this will be logged by the "general" logger in a single line (once per export) + LogEvent expectedExceptionLogMessage = new LogEvent(WARN, + "Failed metric ingestion: java.lang.RuntimeException: " + expectedException.getMessage(), null); + + meterRegistry.gauge("my.gauge", 1d); + Gauge gauge = meterRegistry.find("my.gauge").gauge(); + + // first export + exporter.export(Collections.singletonList(gauge)); + + // after the first export, the general logger only has the WARN event, but not the + // debug event. + assertThat(logger.getLogEvents()).containsOnlyOnce(expectedExceptionLogMessage); + + long countExceptionLogsFirstExport = logger.getLogEvents() + .stream() + .filter(event -> event.equals(expectedExceptionLogMessage)) + .count(); + assertThat(countExceptionLogsFirstExport).isEqualTo(1); + + // the WarnThenDebugLogger only has one event so far. + assertThat(stackTraceLogger.getLogEvents()).hasSize(1).containsExactly(warnThenDebugWarningLog); + + // second export + exporter.export(Collections.singletonList(gauge)); + + // after the second export, the general logger contains the warning log twice + long countExceptionLogsSecondExport = logger.getLogEvents() + .stream() + .filter(event -> event.equals(expectedExceptionLogMessage)) + .count(); + assertThat(countExceptionLogsSecondExport).isEqualTo(2); + + // the WarnThenDebugLogger now has two logs. + assertThat(stackTraceLogger.getLogEvents()).hasSize(2) + .containsExactly(warnThenDebugWarningLog, warnThenDebugDebugLog); + } + @Test void endpointPickedUpBetweenExportsAndChangedPropertiesFile() throws Throwable { String randomUuid = UUID.randomUUID().toString(); @@ -942,6 +1022,48 @@ void conflictingMetadataIsIgnored() { }); } + @Test + void conflictingMetadataIsIgnored_testLogWarnThenDebug() { + MockLogger metadataDiscrepancyLogger = loggerFactory + .getLogger(WarnThenDebugLoggers.MetadataDiscrepancyLogger.class); + + String expectedLogMessage = "Metadata discrepancy detected:\n" + + "original metadata:\t#my.count count dt.meta.description=count\\ 1\\ description,dt.meta.unit=Bytes\n" + + "tried to set new:\t#my.count count dt.meta.description=count\\ description\n" + + "Metadata for metric key my.count will not be sent."; + LogEvent warnEvent = new LogEvent(WARN, String.join(" ", expectedLogMessage, subsequentLogsAsDebug), null); + LogEvent debugEvent = new LogEvent(DEBUG, expectedLogMessage, null); + + HttpSender.Request.Builder builder = mock(HttpSender.Request.Builder.class); + when(httpClient.post(anyString())).thenReturn(builder); + + // the unit and description are different between counters, while the name stays + // the same. + Counter counter1 = Counter.builder("my.count") + .description("count 1 description") + .baseUnit("Bytes") + .tag("counter-number", "counter1") + .register(meterRegistry); + Counter counter2 = Counter.builder("my.count") + .description("count description") + .baseUnit("not Bytes") + .tag("counter-number", "counter2") + .register(meterRegistry); + + counter1.increment(5.234); + counter2.increment(2.345); + + // first export + exporter.export(meterRegistry.getMeters()); + + assertThat(metadataDiscrepancyLogger.getLogEvents()).hasSize(1).containsExactly(warnEvent); + + // second export + exporter.export(meterRegistry.getMeters()); + assertThat(metadataDiscrepancyLogger.getLogEvents()).hasSize(2).containsExactly(warnEvent, debugEvent); + + } + @Test void metadataIsNotExportedWhenTurnedOff() { HttpSender.Request.Builder builder = spy(HttpSender.Request.build(config.uri(), httpClient)); From 11536e76ffd24314cb09de6a8f99d0f316e13823 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:14:09 -0800 Subject: [PATCH 17/73] Bump io.spring.ge.conventions from 0.0.14 to 0.0.15 (#4680) Bumps [io.spring.ge.conventions](https://github.com/spring-io/gradle-enterprise-conventions) from 0.0.14 to 0.0.15. - [Release notes](https://github.com/spring-io/gradle-enterprise-conventions/releases) - [Commits](https://github.com/spring-io/gradle-enterprise-conventions/compare/v0.0.14...v0.0.15) --- updated-dependencies: - dependency-name: io.spring.ge.conventions dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index d17bf90abd..50b4d4b1d7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -6,7 +6,7 @@ pluginManagement { plugins { id 'com.gradle.enterprise' version '3.16.1' - id 'io.spring.ge.conventions' version '0.0.14' + id 'io.spring.ge.conventions' version '0.0.15' id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' } From 7a85827dcc141237d8f2c61443e2f814674c52fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:14:18 -0800 Subject: [PATCH 18/73] Bump spring-javaformat from 0.0.40 to 0.0.41 (#4679) Bumps `spring-javaformat` from 0.0.40 to 0.0.41. Updates `io.spring.javaformat:spring-javaformat-checkstyle` from 0.0.40 to 0.0.41 - [Release notes](https://github.com/spring-io/spring-javaformat/releases) - [Commits](https://github.com/spring-io/spring-javaformat/compare/v0.0.40...v0.0.41) Updates `io.spring.javaformat:spring-javaformat-gradle-plugin` from 0.0.40 to 0.0.41 - [Release notes](https://github.com/spring-io/spring-javaformat/releases) - [Commits](https://github.com/spring-io/spring-javaformat/compare/v0.0.40...v0.0.41) --- updated-dependencies: - dependency-name: io.spring.javaformat:spring-javaformat-checkstyle dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.spring.javaformat:spring-javaformat-gradle-plugin dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9444c93a9a..9c0f933efc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -67,7 +67,7 @@ signalfx = "1.0.38" slf4j = "1.7.36" spectator-atlas = "1.3.10" spring = "5.3.31" -spring-javaformat = "0.0.40" +spring-javaformat = "0.0.41" testcontainers = "1.19.3" tomcat = "8.5.97" wavefront = "3.0.4" From 800ea0a863f15eb509c8177802356338cd0674c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:14:33 -0800 Subject: [PATCH 19/73] Bump com.amazonaws:aws-java-sdk-cloudwatch from 1.12.629 to 1.12.649 (#4682) Bumps [com.amazonaws:aws-java-sdk-cloudwatch](https://github.com/aws/aws-sdk-java) from 1.12.629 to 1.12.649. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.629...1.12.649) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9c0f933efc..41c92245e3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ aspectjweaver = "1.8.14" assertj = "3.24.2" awaitility = "4.2.0" # legacy SDK -aws-cloudwatch = "1.12.629" +aws-cloudwatch = "1.12.649" caffeine = "2.9.3" cloudwatch2 = "2.18.41" colt = "1.2.0" From bcc955a3cb6d567b3442a9fb8e53ebe5006f833c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:14:43 -0800 Subject: [PATCH 20/73] Bump dropwizard-metrics from 4.2.23 to 4.2.25 (#4678) Bumps `dropwizard-metrics` from 4.2.23 to 4.2.25. Updates `io.dropwizard.metrics:metrics-core` from 4.2.23 to 4.2.25 - [Release notes](https://github.com/dropwizard/metrics/releases) - [Commits](https://github.com/dropwizard/metrics/compare/v4.2.23...v4.2.25) Updates `io.dropwizard.metrics:metrics-graphite` from 4.2.23 to 4.2.25 - [Release notes](https://github.com/dropwizard/metrics/releases) - [Commits](https://github.com/dropwizard/metrics/compare/v4.2.23...v4.2.25) Updates `io.dropwizard.metrics:metrics-jmx` from 4.2.23 to 4.2.25 - [Release notes](https://github.com/dropwizard/metrics/releases) - [Commits](https://github.com/dropwizard/metrics/compare/v4.2.23...v4.2.25) --- updated-dependencies: - dependency-name: io.dropwizard.metrics:metrics-core dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.dropwizard.metrics:metrics-graphite dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: io.dropwizard.metrics:metrics-jmx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 41c92245e3..44223da43f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -11,7 +11,7 @@ caffeine = "2.9.3" cloudwatch2 = "2.18.41" colt = "1.2.0" dagger = "2.11" -dropwizard-metrics = "4.2.23" +dropwizard-metrics = "4.2.25" dropwizard-metrics5 = "5.0.0" dynatrace-utils = "1.5.0" ehcache2 = "2.10.9.2" From 504fd5a023507adda250b3dbadc896967a71fcb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:14:51 -0800 Subject: [PATCH 21/73] Bump org.apache.tomcat.embed:tomcat-embed-core from 8.5.97 to 8.5.98 (#4676) Bumps org.apache.tomcat.embed:tomcat-embed-core from 8.5.97 to 8.5.98. --- updated-dependencies: - dependency-name: org.apache.tomcat.embed:tomcat-embed-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 44223da43f..09a7f904d0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -69,7 +69,7 @@ spectator-atlas = "1.3.10" spring = "5.3.31" spring-javaformat = "0.0.41" testcontainers = "1.19.3" -tomcat = "8.5.97" +tomcat = "8.5.98" wavefront = "3.0.4" # pinned to avoid issues with shaded slf4j version - see gh-3414 wiremock = "2.33.2" From 8ee104bfe184d5f29466a3ea3a15607ea87add67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:15:07 -0800 Subject: [PATCH 22/73] Bump io.netty:netty-bom from 4.1.104.Final to 4.1.106.Final (#4674) Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.1.104.Final to 4.1.106.Final. - [Commits](https://github.com/netty/netty/compare/netty-4.1.104.Final...netty-4.1.106.Final) --- updated-dependencies: - dependency-name: io.netty:netty-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 09a7f904d0..856b75475b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -56,7 +56,7 @@ maven-resolver = "1.8.2" # 5.x requires JDK 11. mockito = "4.11.0" mongo = "4.6.1" -netty = "4.1.104.Final" +netty = "4.1.106.Final" newrelic-api = "5.14.0" okhttp = "4.11.0" postgre = "42.3.8" From 23a37924a84bf0be8b558f6e2264de77891654af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:15:16 -0800 Subject: [PATCH 23/73] Bump io.projectreactor:reactor-bom from 2020.0.39 to 2020.0.40 (#4681) Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2020.0.39 to 2020.0.40. - [Release notes](https://github.com/reactor/reactor/releases) - [Commits](https://github.com/reactor/reactor/compare/2020.0.39...2020.0.40) --- updated-dependencies: - dependency-name: io.projectreactor:reactor-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 856b75475b..62d4756eed 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -61,7 +61,7 @@ newrelic-api = "5.14.0" okhttp = "4.11.0" postgre = "42.3.8" prometheus = "0.15.0" -reactor = "2020.0.39" +reactor = "2020.0.40" rest-assured = "5.3.2" signalfx = "1.0.38" slf4j = "1.7.36" From 83c8c5aeeb9a9566a4554ec888736e215130a217 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:15:53 -0800 Subject: [PATCH 24/73] Bump testcontainers from 1.19.3 to 1.19.4 (#4675) Bumps `testcontainers` from 1.19.3 to 1.19.4. Updates `org.testcontainers:junit-jupiter` from 1.19.3 to 1.19.4 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.3...1.19.4) Updates `org.testcontainers:kafka` from 1.19.3 to 1.19.4 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.3...1.19.4) Updates `org.testcontainers:postgresql` from 1.19.3 to 1.19.4 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.3...1.19.4) Updates `org.testcontainers:mongodb` from 1.19.3 to 1.19.4 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.3...1.19.4) Updates `org.testcontainers:testcontainers` from 1.19.3 to 1.19.4 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.3...1.19.4) --- updated-dependencies: - dependency-name: org.testcontainers:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:kafka dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:postgresql dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:mongodb dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:testcontainers dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 62d4756eed..c577c24b12 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,7 +68,7 @@ slf4j = "1.7.36" spectator-atlas = "1.3.10" spring = "5.3.31" spring-javaformat = "0.0.41" -testcontainers = "1.19.3" +testcontainers = "1.19.4" tomcat = "8.5.98" wavefront = "3.0.4" # pinned to avoid issues with shaded slf4j version - see gh-3414 From 2a0d06da6fc1b27312dba808296799d217aeff13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 14:16:07 -0800 Subject: [PATCH 25/73] Bump com.gradle.enterprise from 3.16.1 to 3.16.2 (#4677) Bumps com.gradle.enterprise from 3.16.1 to 3.16.2. --- updated-dependencies: - dependency-name: com.gradle.enterprise dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index 50b4d4b1d7..db1bc57b0e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,7 +5,7 @@ pluginManagement { } plugins { - id 'com.gradle.enterprise' version '3.16.1' + id 'com.gradle.enterprise' version '3.16.2' id 'io.spring.ge.conventions' version '0.0.15' id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' } From 4b647382c018d92a18eab623216906e673554e72 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Thu, 1 Feb 2024 14:18:24 -0800 Subject: [PATCH 26/73] Bump org.gradle.toolchains.foojay-resolver-convention from 0.7.0 to 0.8.0 Closes gh-4683 --- settings.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle b/settings.gradle index db1bc57b0e..4bb1975edb 100644 --- a/settings.gradle +++ b/settings.gradle @@ -7,7 +7,7 @@ pluginManagement { plugins { id 'com.gradle.enterprise' version '3.16.2' id 'io.spring.ge.conventions' version '0.0.15' - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } rootProject.name = 'micrometer' From b7fb212d29aeec248a747f3c132e874e7cc225b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:05:43 -0800 Subject: [PATCH 27/73] Bump uk.org.webcompere:system-stubs-jupiter from 2.1.5 to 2.1.6 (#4647) Bumps [uk.org.webcompere:system-stubs-jupiter](https://github.com/webcompere/system-stubs) from 2.1.5 to 2.1.6. - [Release notes](https://github.com/webcompere/system-stubs/releases) - [Changelog](https://github.com/webcompere/system-stubs/blob/main/History.md) - [Commits](https://github.com/webcompere/system-stubs/compare/system-stubs-parent-2.1.5...system-stubs-parent-2.1.6) --- updated-dependencies: - dependency-name: uk.org.webcompere:system-stubs-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3490eb65be..e326785ad3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -175,7 +175,7 @@ spring-context = { module = "org.springframework:spring-context", version.ref = spring-core = { module = "org.springframework:spring-core", version.ref = "spring" } spring-cloud = { module = "org.springframework.cloud:spring-cloud-dependencies", version = "2021.0.9" } spring-javaformatCheckstyle = { module = "io.spring.javaformat:spring-javaformat-checkstyle", version.ref = "spring-javaformat" } -systemStubsJupiter = { module = "uk.org.webcompere:system-stubs-jupiter", version = "2.1.5" } +systemStubsJupiter = { module = "uk.org.webcompere:system-stubs-jupiter", version = "2.1.6" } testcontainers-junitJupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" } testcontainers-kafka = { module = "org.testcontainers:kafka", version.ref = "testcontainers" } testcontainers-postgresql = { module = "org.testcontainers:postgresql", version.ref = "testcontainers" } From 03fc81d18f19c1153036ab9cd92a083b6fc54e9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:32:00 -0800 Subject: [PATCH 28/73] Bump org.apache.felix:org.apache.felix.scr from 2.2.6 to 2.2.10 (#4646) Bumps org.apache.felix:org.apache.felix.scr from 2.2.6 to 2.2.10. --- updated-dependencies: - dependency-name: org.apache.felix:org.apache.felix.scr dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0bf2bed616..74be940cd6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -99,7 +99,7 @@ dynatraceUtils = { module = "com.dynatrace.metric.util:dynatrace-metric-utils-ja ehcache2 = { module = "net.sf.ehcache:ehcache", version.ref = "ehcache2" } ehcache3 = { module = "org.ehcache:ehcache", version.ref = "ehcache3" } felixFramework = "org.apache.felix:org.apache.felix.framework:7.0.5" -felixScr = "org.apache.felix:org.apache.felix.scr:2.2.6" +felixScr = "org.apache.felix:org.apache.felix.scr:2.2.10" gmetric4j = { module = "info.ganglia.gmetric4j:gmetric4j", version.ref = "gmetric4j" } googleCloudMonitoring = { module = "com.google.cloud:google-cloud-monitoring", version.ref = "google-cloud-monitoring" } googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.16.1"} From cda33b34384424cc559d8e4920bc54a367829d16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:42:40 -0800 Subject: [PATCH 29/73] Bump io.projectreactor:reactor-bom from 2022.0.14 to 2022.0.15 (#4662) Bumps [io.projectreactor:reactor-bom](https://github.com/reactor/reactor) from 2022.0.14 to 2022.0.15. - [Release notes](https://github.com/reactor/reactor/releases) - [Commits](https://github.com/reactor/reactor/compare/2022.0.14...2022.0.15) --- updated-dependencies: - dependency-name: io.projectreactor:reactor-bom dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 148f427f98..98a0bda805 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -64,7 +64,7 @@ newrelic-api = "5.14.0" okhttp = "4.11.0" postgre = "42.6.0" prometheus = "0.16.0" -reactor = "2022.0.14" +reactor = "2022.0.15" rest-assured = "5.3.2" signalfx = "1.0.38" slf4j = "1.7.36" From 23c89a5f1ebd29d5eb58d8487bf783059601ba51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:20:49 -0800 Subject: [PATCH 30/73] Bump io.opentelemetry.proto:opentelemetry-proto (#4660) Bumps [io.opentelemetry.proto:opentelemetry-proto](https://github.com/open-telemetry/opentelemetry-proto-java) from 1.0.0-alpha to 1.1.0-alpha. - [Release notes](https://github.com/open-telemetry/opentelemetry-proto-java/releases) - [Commits](https://github.com/open-telemetry/opentelemetry-proto-java/commits) --- updated-dependencies: - dependency-name: io.opentelemetry.proto:opentelemetry-proto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cc900cfb08..0213560a10 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -175,7 +175,7 @@ nettyBom = { module = "io.netty:netty-bom", version.ref = "netty" } newrelicApi = { module = "com.newrelic.agent.java:newrelic-api", version.ref = "newrelic-api" } okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "okhttp" } # some proto are marked alpha, hence the alpha version. metrics proto is what we use and it is marked stable -openTelemetry-proto = { module = "io.opentelemetry.proto:opentelemetry-proto", version = "1.0.0-alpha" } +openTelemetry-proto = { module = "io.opentelemetry.proto:opentelemetry-proto", version = "1.1.0-alpha" } osgiJunit5 = "org.osgi:org.osgi.test.junit5:1.2.1" postgre = { module = "org.postgresql:postgresql", version.ref = "postgre" } prometheusClient = { module = "io.prometheus:simpleclient_common", version.ref = "prometheus" } From 7b971b0ecd0a96d8341ef5ba1850cc401dc8ff6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:21:05 -0800 Subject: [PATCH 31/73] Bump com.fasterxml.jackson.core:jackson-databind from 2.16.0 to 2.16.1 (#4670) Bumps [com.fasterxml.jackson.core:jackson-databind](https://github.com/FasterXML/jackson) from 2.16.0 to 2.16.1. - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0213560a10..0eb9e90997 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ httpcomponents-client5 = "5.3" # 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. hystrix = "1.5.12" -jackson-databind = "2.16.0" +jackson-databind = "2.16.1" javax-cache = "1.1.1" javax-inject = "1" jaxb = "2.3.1" From a6363a84c77ef8cf329762b2858760900f3b9267 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:21:14 -0800 Subject: [PATCH 32/73] Bump com.google.auth:google-auth-library-oauth2-http (#4671) Bumps com.google.auth:google-auth-library-oauth2-http from 1.20.0 to 1.22.0. --- updated-dependencies: - dependency-name: com.google.auth:google-auth-library-oauth2-http dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0eb9e90997..d7be161e36 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -107,7 +107,7 @@ felixFramework = "org.apache.felix:org.apache.felix.framework:7.0.5" felixScr = "org.apache.felix:org.apache.felix.scr:2.2.10" gmetric4j = { module = "info.ganglia.gmetric4j:gmetric4j", version.ref = "gmetric4j" } googleCloudMonitoring = { module = "com.google.cloud:google-cloud-monitoring", version.ref = "google-cloud-monitoring" } -googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.20.0"} +googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.22.0"} grpcApi = { module = "io.grpc:grpc-api", version.ref = "grpc" } grpcCore = { module = "io.grpc:grpc-core", version.ref = "grpc" } grpcInprocess = { module = "io.grpc:grpc-inprocess", version.ref = "grpc" } From ab55b58a94b3ab95299a5fb9520da9930f887ac8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:12:22 -0800 Subject: [PATCH 33/73] Bump software.amazon.awssdk:cloudwatch from 2.22.9 to 2.23.16 (#4698) Bumps software.amazon.awssdk:cloudwatch from 2.22.9 to 2.23.16. --- updated-dependencies: - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d7be161e36..d2a7c868d7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" # legacy SDK aws-cloudwatch = "1.12.649" caffeine = "2.9.3" -cloudwatch2 = "2.22.9" +cloudwatch2 = "2.23.16" colt = "1.2.0" dagger = "2.50" dropwizard-metrics = "4.2.25" From f047aa1acfb4ef693f0351e8df897d276fcd3e3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:12:31 -0800 Subject: [PATCH 34/73] Bump org.aspectj:aspectjweaver from 1.9.20.1 to 1.9.21 (#4702) Bumps [org.aspectj:aspectjweaver](https://github.com/eclipse/org.aspectj) from 1.9.20.1 to 1.9.21. - [Release notes](https://github.com/eclipse/org.aspectj/releases) - [Commits](https://github.com/eclipse/org.aspectj/commits) --- updated-dependencies: - dependency-name: org.aspectj:aspectjweaver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d2a7c868d7..90a78cee9a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ activemq-artemis = "2.31.2" application-insights = "2.6.4" archunit = "1.2.1" asmForPlugins = "7.3.1" -aspectjweaver = "1.9.20.1" +aspectjweaver = "1.9.21" assertj = "3.25.0" awaitility = "4.2.0" # legacy SDK From 8c1490559f4e3f72705c3c4ae9c3d503812d4dc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:12:42 -0800 Subject: [PATCH 35/73] Bump com.jayway.jsonpath:json-path from 2.8.0 to 2.9.0 (#4701) Bumps [com.jayway.jsonpath:json-path](https://github.com/jayway/JsonPath) from 2.8.0 to 2.9.0. - [Release notes](https://github.com/jayway/JsonPath/releases) - [Changelog](https://github.com/json-path/JsonPath/blob/master/changelog.md) - [Commits](https://github.com/jayway/JsonPath/compare/json-path-2.8.0...json-path-2.9.0) --- updated-dependencies: - dependency-name: com.jayway.jsonpath:json-path dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90a78cee9a..247a26ebe1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -151,7 +151,7 @@ jersey3TestFrameworkJdkHttp = { module = "org.glassfish.jersey.test-framework.pr jmhCore = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } jmhAnnotationProcessor = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" } jooq = { module = "org.jooq:jooq", version.ref = "jooq" } -jsonPath = { module = "com.jayway.jsonpath:json-path", version = "2.8.0" } +jsonPath = { module = "com.jayway.jsonpath:json-path", version = "2.9.0" } jsr107 = { module = "org.jsr107.ri:cache-ri-impl", version.ref = "jsr107" } jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" } junitBom = { module = "org.junit:junit-bom", version.ref = "junit" } From 165ead6ea6b0410a5f6d6efaa55d11df696fed20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:12:51 -0800 Subject: [PATCH 36/73] Bump org.apache.httpcomponents.client5:httpclient5 from 5.3 to 5.3.1 (#4697) Bumps [org.apache.httpcomponents.client5:httpclient5](https://github.com/apache/httpcomponents-client) from 5.3 to 5.3.1. - [Changelog](https://github.com/apache/httpcomponents-client/blob/rel/v5.3.1/RELEASE_NOTES.txt) - [Commits](https://github.com/apache/httpcomponents-client/compare/rel/v5.3...rel/v5.3.1) --- updated-dependencies: - dependency-name: org.apache.httpcomponents.client5:httpclient5 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 247a26ebe1..8aca0bb423 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,7 +31,7 @@ hibernate = "5.6.15.Final" hsqldb = "2.7.2" httpcomponents-async = "4.1.5" httpcomponents-client = "4.5.14" -httpcomponents-client5 = "5.3" +httpcomponents-client5 = "5.3.1" # 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. From 6ee61fca1ce526f9c695e340742b6a19a701e3c3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:13:01 -0800 Subject: [PATCH 37/73] Bump org.apache.logging.log4j:log4j-core from 2.22.0 to 2.22.1 (#4695) Bumps org.apache.logging.log4j:log4j-core from 2.22.0 to 2.22.1. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8aca0bb423..7f042f126f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -55,7 +55,7 @@ kafka = "2.8.2" kafka-junit = "4.2.10" latency-utils = "2.0.3" logback = "1.2.13" -log4j = "2.22.0" +log4j = "2.22.1" maven-resolver = "1.9.18" mockito = "5.8.0" mongo = "4.11.1" From 184595f520d72f896760b42327bd63d36afbb05a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:21:41 -0800 Subject: [PATCH 38/73] Bump com.amazonaws:aws-java-sdk-cloudwatch from 1.12.649 to 1.12.650 (#4696) Bumps [com.amazonaws:aws-java-sdk-cloudwatch](https://github.com/aws/aws-sdk-java) from 1.12.649 to 1.12.650. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.649...1.12.650) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c577c24b12..860c494150 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ aspectjweaver = "1.8.14" assertj = "3.24.2" awaitility = "4.2.0" # legacy SDK -aws-cloudwatch = "1.12.649" +aws-cloudwatch = "1.12.650" caffeine = "2.9.3" cloudwatch2 = "2.18.41" colt = "1.2.0" From fc228c713785c62afe88972ff625db10a03e4378 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Thu, 1 Feb 2024 17:23:21 -0800 Subject: [PATCH 39/73] Bump com.diffplug.spotless:spotless-plugin-gradle to 6.25.0 Closes gh-4703 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2ea3387045..548a978695 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -197,7 +197,7 @@ plugin-nexusPublish = { module = "io.github.gradle-nexus:publish-plugin", versio plugin-javaformat = { module = "io.spring.javaformat:spring-javaformat-gradle-plugin", version.ref = "spring-javaformat" } plugin-japicmp = { module = "me.champeau.gradle:japicmp-gradle-plugin", version = "0.4.2" } plugin-downloadTask = { module = "de.undercouch:gradle-download-task", version = "5.5.0" } -plugin-spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version = "6.22.0" } +plugin-spotless = { module = "com.diffplug.spotless:spotless-plugin-gradle", version = "6.25.0" } [plugins] kotlin19 = { id = "org.jetbrains.kotlin.jvm", version = "1.9.22" } From 42c01e2b9b74b7c41cb22616f814a91911ef9936 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:55:01 -0800 Subject: [PATCH 40/73] Bump org.assertj:assertj-core from 3.25.0 to 3.25.2 (#4708) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.25.0 to 3.25.2. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.25.0...assertj-build-3.25.2) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 71673dd82d..da3bbd2943 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ application-insights = "2.6.4" archunit = "1.2.1" asmForPlugins = "7.3.1" aspectjweaver = "1.9.21" -assertj = "3.25.0" +assertj = "3.25.2" awaitility = "4.2.0" # legacy SDK aws-cloudwatch = "1.12.650" From 96b5fc9aa724e0a02264dafabd7bee85fea8ce5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:55:12 -0800 Subject: [PATCH 41/73] Bump activemq-artemis from 2.31.2 to 2.32.0 (#4705) Bumps `activemq-artemis` from 2.31.2 to 2.32.0. Updates `org.apache.activemq:artemis-jakarta-client` from 2.31.2 to 2.32.0 - [Commits](https://github.com/apache/activemq-artemis/compare/2.31.2...2.32.0) Updates `org.apache.activemq:artemis-junit-5` from 2.31.2 to 2.32.0 --- updated-dependencies: - dependency-name: org.apache.activemq:artemis-jakarta-client dependency-type: direct:production update-type: version-update:semver-minor - dependency-name: org.apache.activemq:artemis-junit-5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index da3bbd2943..c7a8e6ed3f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -activemq-artemis = "2.31.2" +activemq-artemis = "2.32.0" application-insights = "2.6.4" archunit = "1.2.1" asmForPlugins = "7.3.1" From 9bed446eaf906cf0a12f6ab987026a802cb083be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:55:23 -0800 Subject: [PATCH 42/73] Bump com.google.cloud:google-cloud-monitoring from 3.32.0 to 3.35.0 (#4709) Bumps [com.google.cloud:google-cloud-monitoring](https://github.com/googleapis/google-cloud-java) from 3.32.0 to 3.35.0. - [Release notes](https://github.com/googleapis/google-cloud-java/releases) - [Changelog](https://github.com/googleapis/google-cloud-java/blob/main/changelog.json) - [Commits](https://github.com/googleapis/google-cloud-java/commits) --- updated-dependencies: - dependency-name: com.google.cloud:google-cloud-monitoring dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7a8e6ed3f..67dd3f8dd8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ dynatrace-utils = "2.1.0" ehcache2 = "2.10.9.2" ehcache3 = "3.10.8" gmetric4j = "1.0.10" -google-cloud-monitoring = "3.32.0" +google-cloud-monitoring = "3.35.0" grpc = "1.58.0" guava = "32.1.2-jre" guice = "5.1.0" From bafd38af1f0312618a337b60ac71fe7d5d251c4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 17:55:33 -0800 Subject: [PATCH 43/73] Bump org.mockito:mockito-core from 5.8.0 to 5.10.0 (#4707) Bumps [org.mockito:mockito-core](https://github.com/mockito/mockito) from 5.8.0 to 5.10.0. - [Release notes](https://github.com/mockito/mockito/releases) - [Commits](https://github.com/mockito/mockito/compare/v5.8.0...v5.10.0) --- updated-dependencies: - dependency-name: org.mockito:mockito-core dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 67dd3f8dd8..ed6ba12437 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -57,7 +57,7 @@ latency-utils = "2.0.3" logback = "1.2.13" log4j = "2.22.1" maven-resolver = "1.9.18" -mockito = "5.8.0" +mockito = "5.10.0" mongo = "4.11.1" netty = "4.1.106.Final" newrelic-api = "5.14.0" From 49d79d49dd6876c50c5ce2d5788286067941f314 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:11:42 +0900 Subject: [PATCH 44/73] Pin version of com.google.cloud:libraries-bom in stackdriver registry This was using `latest.version` by mistake. Fixes gh-4711 --- gradle/libs.versions.toml | 1 + implementations/micrometer-registry-stackdriver/build.gradle | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa8d119bb2..531977ea29 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -105,6 +105,7 @@ ehcache3 = { module = "org.ehcache:ehcache", version.ref = "ehcache3" } felixFramework = "org.apache.felix:org.apache.felix.framework:7.0.5" felixScr = "org.apache.felix:org.apache.felix.scr:2.2.10" gmetric4j = { module = "info.ganglia.gmetric4j:gmetric4j", version.ref = "gmetric4j" } +googleCloudLibrariesBom = { module = "com.google.cloud:libraries-bom", version = "26.31.0" } googleCloudMonitoring = { module = "com.google.cloud:google-cloud-monitoring", version.ref = "google-cloud-monitoring" } googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.20.0"} grpcApi = { module = "io.grpc:grpc-api", version.ref = "grpc" } diff --git a/implementations/micrometer-registry-stackdriver/build.gradle b/implementations/micrometer-registry-stackdriver/build.gradle index 1b3e1987ea..860aef8968 100644 --- a/implementations/micrometer-registry-stackdriver/build.gradle +++ b/implementations/micrometer-registry-stackdriver/build.gradle @@ -1,7 +1,7 @@ dependencies { api project(':micrometer-core') - api platform('com.google.cloud:libraries-bom:latest.release') + api platform(libs.googleCloudLibrariesBom) api('com.google.cloud:google-cloud-monitoring') { // see gh-4010 From 1e1cf64488c84fd564c83479e2f77059676c358e Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:15:40 +0900 Subject: [PATCH 45/73] Remove stackdriver-specific dependencies from global dependencies.gradle There's no need to manage these dependencies globally when they will only be used in the stackdriver module. Switch to referencing the type-safe version catalog for these dependencies in the stackdriver build file. --- dependencies.gradle | 2 -- implementations/micrometer-registry-stackdriver/build.gradle | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index fa7bc068d9..b4271c8357 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -7,8 +7,6 @@ def VERSIONS = [ libs.caffeine, libs.kafkaJunit, libs.wiremock, - libs.googleOauth2Http, - libs.googleCloudMonitoring, libs.dagger, libs.daggerCompiler, libs.guava, diff --git a/implementations/micrometer-registry-stackdriver/build.gradle b/implementations/micrometer-registry-stackdriver/build.gradle index 860aef8968..9a4eea25b0 100644 --- a/implementations/micrometer-registry-stackdriver/build.gradle +++ b/implementations/micrometer-registry-stackdriver/build.gradle @@ -3,11 +3,11 @@ dependencies { api platform(libs.googleCloudLibrariesBom) - api('com.google.cloud:google-cloud-monitoring') { + api(libs.googleCloudMonitoring) { // see gh-4010 exclude group: 'com.google.guava', module: 'listenablefuture' } - api 'com.google.auth:google-auth-library-oauth2-http' + api libs.googleOauth2Http implementation 'org.slf4j:slf4j-api' compileOnly 'ch.qos.logback:logback-classic' From dce0018f18a8808c77b9b776360b19bc4fe1e5a4 Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:30:24 +0900 Subject: [PATCH 46/73] Upgrade to logback 1.4.14 Closes gh-4712 --- dependencies.gradle | 2 +- gradle/libs.versions.toml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index b717a517a2..858ec09a3b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,5 +1,5 @@ def VERSIONS = [ - libs.logback, + libs.logback12, libs.colt, libs.aws.javaSdkCloudwatch, libs.dynatraceUtils, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 548a978695..5678cc744e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -51,7 +51,7 @@ junit-platform = "1.9.3" kafka = "2.8.2" kafka-junit = "4.2.10" latency-utils = "2.0.3" -logback = "1.2.13" +logback12 = "1.2.13" log4j = "2.19.0" maven-resolver = "1.8.2" mockito = "5.5.0" @@ -150,8 +150,8 @@ kafkaJunit = { module = "com.github.charithe:kafka-junit", version.ref = "kafka- kotlinxCoroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.6.4" } latencyUtils = { module = "org.latencyutils:LatencyUtils", version.ref = "latency-utils" } lmaxDisruptor = "com.lmax:disruptor:3.4.4" -logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } -logback14 = {module = "ch.qos.logback:logback-classic", version = "1.4.11" } +logback12 = { module = "ch.qos.logback:logback-classic", version.ref = "logback12" } +logback14 = {module = "ch.qos.logback:logback-classic", version = "1.4.14" } log4j = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } mavenResolverConnectorBasic = { module = "org.apache.maven.resolver:maven-resolver-connector-basic", version.ref = "maven-resolver" } mavenResolverTransportHttp = { module = "org.apache.maven.resolver:maven-resolver-transport-http", version.ref = "maven-resolver" } From 1b0604db491eed6bf087f9074596bbc241b806e2 Mon Sep 17 00:00:00 2001 From: Aleksander Brzozowski Date: Fri, 2 Feb 2024 12:14:27 +0100 Subject: [PATCH 47/73] add support for Observation propagation in kotlin gRPC coroutine server (#4284) * add support for Observation propagation in kotlin gRPC coroutine server This commit contains changes that allow to capture current observation when using kotlin gRPC coroutine server. In order to properly propagate current Observation to a coroutine server method, we need to propagate Observation as a context element by extending `CoroutineContextServerInterceptor`. Moreover, current Observation needs to be somehow allowed to capture by `CoroutineContextServerInterceptor`. To do this, we need to open current Observation scope inside `ObservationGrpcServerInterceptor`. It is important to keep these two interceptors in a proper order - first, we need to open current Observation scope, and later create a context element based on it. Fixes: #4218 * set license & set 'since' property for a public class --------- Co-authored-by: Aleksander Brzozowski --- dependencies.gradle | 1 + gradle/libs.versions.toml | 2 + micrometer-core/build.gradle | 1 + .../ObservationGrpcServerInterceptor.java | 2 +- ...vationCoroutineContextServerInterceptor.kt | 47 ++++++++ .../binder/grpc/GrpcObservationTest.java | 58 ++++++++- .../kotlin/binder/grpc/GrpcCoroutinesTest.kt | 114 ++++++++++++++++++ 7 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 micrometer-core/src/main/kotlin/io/micrometer/core/instrument/kotlin/ObservationCoroutineContextServerInterceptor.kt create mode 100644 micrometer-core/src/test/kotlin/io/micrometer/core/instrument/kotlin/binder/grpc/GrpcCoroutinesTest.kt diff --git a/dependencies.gradle b/dependencies.gradle index 611405e88f..d1d1a1df8f 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -31,6 +31,7 @@ def VERSIONS = [ libs.grpcStubs, libs.grpcAlts, libs.grpcTestingProto, + libs.grpcKotlinStub, libs.gmetric4j, libs.prometheusClient, libs.prometheusPushgateway, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3f649507df..c5c5b8016f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,6 +20,7 @@ ehcache3 = "3.10.8" gmetric4j = "1.0.10" google-cloud-monitoring = "3.35.0" grpc = "1.58.0" +grpcKotlin = "1.4.0" guava = "32.1.2-jre" guice = "5.1.0" h2 = "2.2.224" @@ -116,6 +117,7 @@ grpcServices = { module = "io.grpc:grpc-services", version.ref = "grpc" } grpcStubs = { module = "io.grpc:grpc-stubs", version.ref = "grpc" } grpcAlts = { module = "io.grpc:grpc-alts", version.ref = "grpc" } grpcTestingProto = { module = "io.grpc:grpc-testing-proto", version.ref = "grpc" } +grpcKotlinStub = { module = "io.grpc:grpc-kotlin-stub", version.ref = "grpcKotlin" } guava = { module = "com.google.guava:guava", version.ref = "guava" } guice = { module = "com.google.inject:guice", version.ref = "guice" } h2 = { module = "com.h2database:h2", version.ref = "h2" } diff --git a/micrometer-core/build.gradle b/micrometer-core/build.gradle index 033cfd7d15..f0a5d471ae 100644 --- a/micrometer-core/build.gradle +++ b/micrometer-core/build.gradle @@ -101,6 +101,7 @@ dependencies { optionalApi 'org.apache.tomcat.embed:tomcat-embed-core' optionalApi 'org.glassfish.jersey.core:jersey-server' optionalApi 'io.grpc:grpc-api' + optionalApi 'io.grpc:grpc-kotlin-stub' optionalApi 'io.netty:netty-transport' // apache httpcomponents monitoring diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/grpc/ObservationGrpcServerInterceptor.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/grpc/ObservationGrpcServerInterceptor.java index 535e29e0eb..e9a62d4e79 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/grpc/ObservationGrpcServerInterceptor.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/grpc/ObservationGrpcServerInterceptor.java @@ -98,7 +98,7 @@ public Listener interceptCall(ServerCall call, ObservationGrpcServerCall serverCall = new ObservationGrpcServerCall<>(call, observation); - try { + try (Observation.Scope scope = observation.openScope()) { Listener result = next.startCall(serverCall, headers); return new ObservationGrpcServerCallListener<>(result, observation); } diff --git a/micrometer-core/src/main/kotlin/io/micrometer/core/instrument/kotlin/ObservationCoroutineContextServerInterceptor.kt b/micrometer-core/src/main/kotlin/io/micrometer/core/instrument/kotlin/ObservationCoroutineContextServerInterceptor.kt new file mode 100644 index 0000000000..eac99a6ade --- /dev/null +++ b/micrometer-core/src/main/kotlin/io/micrometer/core/instrument/kotlin/ObservationCoroutineContextServerInterceptor.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.core.instrument.kotlin + +import io.grpc.Metadata +import io.grpc.ServerCall +import io.grpc.kotlin.CoroutineContextServerInterceptor +import io.micrometer.observation.ObservationRegistry +import kotlin.coroutines.CoroutineContext + +/** + * This interceptor is meant to propagate observation context to a kotlin coroutine gRPC server method. + * + * Usage: + * + * ``` + * val server = ServerBuilder.forPort(8080) + * .intercept(ObservationCoroutineContextServerInterceptor(observationRegistry)) + * .intercept(ObservationGrpcServerInterceptor(observationRegistry)) + * .build(); + * server.start() + * ``` + * + * Please remember that order of interceptors matters, and it has to be the same as it is in the example above. + * + * @since 1.13.0 + */ +class ObservationCoroutineContextServerInterceptor( + private val observationRegistry: ObservationRegistry, +) : CoroutineContextServerInterceptor() { + override fun coroutineContext(call: ServerCall<*, *>, headers: Metadata): CoroutineContext { + return observationRegistry.asContextElement() + } +} diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java index cf05c91359..75e2d79aac 100644 --- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/grpc/GrpcObservationTest.java @@ -63,6 +63,7 @@ import io.micrometer.observation.Observation.Context; import io.micrometer.observation.Observation.Event; import io.micrometer.observation.ObservationHandler; +import io.micrometer.observation.ObservationRegistry; import io.micrometer.observation.ObservationTextPublisher; import io.micrometer.observation.tck.TestObservationRegistry; import io.micrometer.observation.tck.TestObservationRegistryAssert; @@ -104,8 +105,8 @@ class GrpcObservationTest { void setUp() { serverHandler = new ContextAndEventHoldingObservationHandler<>(GrpcServerObservationContext.class); clientHandler = new ContextAndEventHoldingObservationHandler<>(GrpcClientObservationContext.class); - MeterRegistry meterRegistry = new SimpleMeterRegistry(); + MeterRegistry meterRegistry = new SimpleMeterRegistry(); observationRegistry.observationConfig() .observationHandler(new ObservationTextPublisher()) .observationHandler(new DefaultMeterObservationHandler(meterRegistry)) @@ -508,6 +509,41 @@ public void onCompleted() { } + @Nested + class WithObservationAwareInterceptor { + + ObservationAwareServerInterceptor scopeAwareServerInterceptor; + + @BeforeEach + void setCustomInterceptor() throws Exception { + scopeAwareServerInterceptor = new ObservationAwareServerInterceptor(observationRegistry); + + EchoService echoService = new EchoService(); + server = InProcessServerBuilder.forName("sample") + .addService(echoService) + .intercept(scopeAwareServerInterceptor) + .intercept(serverInterceptor) + .build(); + server.start(); + + channel = InProcessChannelBuilder.forName("sample").intercept(clientInterceptor).build(); + } + + @Test + void observationShouldBeCapturedByInterceptor() { + SimpleServiceBlockingStub stub = SimpleServiceGrpc.newBlockingStub(channel); + + SimpleRequest request = SimpleRequest.newBuilder().setRequestMessage("Hello").build(); + stub.unaryRpc(request); + + assertThat(scopeAwareServerInterceptor.lastObservation).isNotNull().satisfies((observation -> { + assertThat(observation.getContext().getContextualName()) + .isEqualTo("grpc.testing.SimpleService/UnaryRpc"); + })); + } + + } + // perform server context verification on basic information void verifyServerContext(String serviceName, String methodName, String contextualName, MethodType methodType) { assertThat(serverHandler.getContext()).isNotNull().satisfies((serverContext) -> { @@ -716,4 +752,24 @@ public void sendHeaders(Metadata headers) { } + // Hold reference to last intercepted Observation + static class ObservationAwareServerInterceptor implements ServerInterceptor { + + Observation lastObservation; + + private final ObservationRegistry observationRegistry; + + private ObservationAwareServerInterceptor(ObservationRegistry observationRegistry) { + this.observationRegistry = observationRegistry; + } + + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, + ServerCallHandler next) { + this.lastObservation = observationRegistry.getCurrentObservation(); + return next.startCall(call, headers); + } + + } + } diff --git a/micrometer-core/src/test/kotlin/io/micrometer/core/instrument/kotlin/binder/grpc/GrpcCoroutinesTest.kt b/micrometer-core/src/test/kotlin/io/micrometer/core/instrument/kotlin/binder/grpc/GrpcCoroutinesTest.kt new file mode 100644 index 0000000000..8b6566afe1 --- /dev/null +++ b/micrometer-core/src/test/kotlin/io/micrometer/core/instrument/kotlin/binder/grpc/GrpcCoroutinesTest.kt @@ -0,0 +1,114 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.core.instrument.kotlin.binder.grpc + +import io.grpc.ManagedChannel +import io.grpc.MethodDescriptor +import io.grpc.Server +import io.grpc.ServerServiceDefinition +import io.grpc.inprocess.InProcessChannelBuilder +import io.grpc.inprocess.InProcessServerBuilder +import io.grpc.kotlin.AbstractCoroutineServerImpl +import io.grpc.kotlin.ServerCalls +import io.grpc.stub.annotations.RpcMethod +import io.grpc.testing.protobuf.SimpleRequest +import io.grpc.testing.protobuf.SimpleResponse +import io.grpc.testing.protobuf.SimpleServiceGrpc +import io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerInterceptor +import io.micrometer.core.instrument.kotlin.ObservationCoroutineContextServerInterceptor +import io.micrometer.observation.Observation +import io.micrometer.observation.ObservationRegistry +import io.micrometer.observation.ObservationTextPublisher +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.ThrowingConsumer +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class GrpcCoroutinesTest { + + val observationRegistry: ObservationRegistry = ObservationRegistry.create() + val echoServiceCoroutine: EchoServiceCoroutine = EchoServiceCoroutine(observationRegistry) + lateinit var server: Server + lateinit var channel: ManagedChannel + + @BeforeEach + fun setUp() { + server = InProcessServerBuilder.forName("sample") + .intercept(ObservationCoroutineContextServerInterceptor(observationRegistry)) + .intercept(ObservationGrpcServerInterceptor(observationRegistry)) + .addService(echoServiceCoroutine) + .build() + server.start() + channel = InProcessChannelBuilder.forName("sample").build() + } + + @AfterEach + fun cleanUp() { + channel.shutdownNow() + server.shutdownNow() + } + + @Test + fun `unary rpc should propagate observation`() { + val stub = SimpleServiceGrpc.newBlockingStub(channel) + val request = SimpleRequest.newBuilder() + .setRequestMessage("hello") + .build() + observationRegistry.observationConfig() + .observationHandler(ObservationTextPublisher()) + + stub.unaryRpc(request) + + assertThat(echoServiceCoroutine.lastObservation).isNotNull() + .satisfies( + ThrowingConsumer { observation: Observation -> + assertThat(observation.getContext().contextualName) + .isEqualTo("grpc.testing.SimpleService/UnaryRpc") + }, + ) + } + + // This service has the same rpc method that the one defined in SimpleServiceGrpc + class EchoServiceCoroutine(private val observationRegistry: ObservationRegistry) : AbstractCoroutineServerImpl() { + + var lastObservation: Observation? = null + + @RpcMethod( + fullMethodName = "${SimpleServiceGrpc.SERVICE_NAME}/UnaryRpc", + requestType = SimpleRequest::class, + responseType = SimpleResponse::class, + methodType = MethodDescriptor.MethodType.UNARY, + ) + fun unaryRpc(request: SimpleRequest): SimpleResponse { + lastObservation = observationRegistry.currentObservation + return SimpleResponse.newBuilder() + .setResponseMessage(request.getRequestMessage()) + .build() + } + + override fun bindService(): ServerServiceDefinition { + return ServerServiceDefinition.builder(SimpleServiceGrpc.SERVICE_NAME) + .addMethod( + ServerCalls.unaryServerMethodDefinition( + context = context, + descriptor = SimpleServiceGrpc.getUnaryRpcMethod(), + implementation = ::unaryRpc, + ), + ).build() + } + } +} From ebb004c760440908a7ca39d7d19303088e7ddff4 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Fri, 2 Feb 2024 14:01:43 -0800 Subject: [PATCH 48/73] Replace full urls to xref wherever it is possible Closes gh-4714 --- docs/modules/ROOT/pages/observation/projects.adoc | 2 +- docs/modules/ROOT/pages/reference/db.adoc | 2 +- docs/modules/ROOT/pages/reference/grpc.adoc | 2 +- docs/modules/ROOT/pages/reference/httpcomponents.adoc | 2 +- docs/modules/ROOT/pages/reference/jetty.adoc | 2 +- docs/modules/ROOT/pages/reference/mongodb.adoc | 2 +- docs/modules/ROOT/pages/reference/okhttpclient.adoc | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/modules/ROOT/pages/observation/projects.adoc b/docs/modules/ROOT/pages/observation/projects.adoc index 12a02ba5ff..9dde9420f1 100644 --- a/docs/modules/ROOT/pages/observation/projects.adoc +++ b/docs/modules/ROOT/pages/observation/projects.adoc @@ -32,7 +32,7 @@ Micrometer Observation is used to instrument various projects. Below you can fin | RabbitMQ Stream | https://github.com/rabbitmq/rabbitmq-stream-java-client/pull/384[PR] | Resilience4j | https://github.com/resilience4j/resilience4j/pull/1698[PR] | R2DBC | https://github.com/r2dbc/r2dbc-proxy/issues/122[Issue] -| Reactor | https://docs.micrometer.io/micrometer/reference/observation/instrumenting.html#instrumentation_of_reactive_libraries[Docs] +| Reactor | xref:observation/instrumenting.adoc#instrumentation_of_reactive_libraries[Docs] | Reactor Netty | https://projectreactor.io/docs/netty/release/reference/index.html#_tracing_3[Docs] | Redisson | https://github.com/redisson/redisson/issues/4976[Issue], https://github.com/redisson/redisson/wiki/16.-Observability#162-tracing[Docs] diff --git a/docs/modules/ROOT/pages/reference/db.adoc b/docs/modules/ROOT/pages/reference/db.adoc index d9c8bf37a2..79c7b2f2d5 100644 --- a/docs/modules/ROOT/pages/reference/db.adoc +++ b/docs/modules/ROOT/pages/reference/db.adoc @@ -11,7 +11,7 @@ Micrometer can instrument various libraries that interact with databases [[db-datasource-observation]] == DataSource Observation Instrumentation -Through the https://github.com/jdbc-observations/datasource-micrometer[Datasource Micrometer] project you can instrument your `Datasource` to start producing https://docs.micrometer.io/micrometer/reference/observation.html[Observations] while interacting with the database. That means that depending on your Observation Handler setup you can plug in producing of metrics or distributed tracing. +Through the https://github.com/jdbc-observations/datasource-micrometer[Datasource Micrometer] project you can instrument your `Datasource` to start producing xref:observation.adoc[Observations] while interacting with the database. That means that depending on your Observation Handler setup you can plug in producing of metrics or distributed tracing. You can read more about Datasource Micrometer https://jdbc-observations.github.io/datasource-micrometer/docs/current/docs/html/[reference documentation] here. diff --git a/docs/modules/ROOT/pages/reference/grpc.adoc b/docs/modules/ROOT/pages/reference/grpc.adoc index c320a951c9..8a09345d5b 100644 --- a/docs/modules/ROOT/pages/reference/grpc.adoc +++ b/docs/modules/ROOT/pages/reference/grpc.adoc @@ -3,7 +3,7 @@ https://grpc.io/[gRPC] is a modern open source high performance Remote Procedure Call (RPC) framework that can run in any environment. -Below you can find an example of how to instrument gRPC with https://docs.micrometer.io/micrometer/reference/observation.html[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). +Below you can find an example of how to instrument gRPC with xref:observation.adoc[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). First, client and server side interceptors need to be setup. diff --git a/docs/modules/ROOT/pages/reference/httpcomponents.adoc b/docs/modules/ROOT/pages/reference/httpcomponents.adoc index f794c2e5e0..954a74a56f 100644 --- a/docs/modules/ROOT/pages/reference/httpcomponents.adoc +++ b/docs/modules/ROOT/pages/reference/httpcomponents.adoc @@ -5,7 +5,7 @@ IMPORTANT: This section requires usage of Apache HttpComponents Client at least https://hc.apache.org/index.html/[Apache HttpComponents Client] is an HTTP/1.1 compliant HTTP agent implementation. -Below you can find an example of how to instrument Apache HttpComponents Client with https://docs.micrometer.io/micrometer/reference/observation.html[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). +Below you can find an example of how to instrument Apache HttpComponents Client xref:observation.adoc[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). Example of classic, blocking HTTP client. diff --git a/docs/modules/ROOT/pages/reference/jetty.adoc b/docs/modules/ROOT/pages/reference/jetty.adoc index abc209dd1b..bc624c22d4 100644 --- a/docs/modules/ROOT/pages/reference/jetty.adoc +++ b/docs/modules/ROOT/pages/reference/jetty.adoc @@ -31,7 +31,7 @@ ServletContainer servletContainer = new ServletContainer(resourceConfig); [[overview-observation]] == Eclipse Observation Jersey Instrumentation -Below you can find an example of how to instrument Jersey with https://docs.micrometer.io/micrometer/reference/observation.html[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). +Below you can find an example of how to instrument Jersey with xref:observation.adoc[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). [source,java,subs=+attributes] ----- diff --git a/docs/modules/ROOT/pages/reference/mongodb.adoc b/docs/modules/ROOT/pages/reference/mongodb.adoc index 057ba01d46..ba9e754def 100644 --- a/docs/modules/ROOT/pages/reference/mongodb.adoc +++ b/docs/modules/ROOT/pages/reference/mongodb.adoc @@ -5,7 +5,7 @@ https://www.mongodb.com/[MongoDB] is a modern database that supports transaction Below you can find an example of how to instrument MongoDb with Micrometer. -TIP: To add more capabilities such as distributed tracing, please consider using https://docs.spring.io/spring-data/mongodb/reference/observability/observability.html[Spring Data MongoDb] which uses https://docs.micrometer.io/micrometer/reference/observation.html[Micrometer Observation] under the hood. +TIP: To add more capabilities such as distributed tracing, please consider using https://docs.spring.io/spring-data/mongodb/reference/observability/observability.html[Spring Data MongoDb] which uses xref:observation.adoc[Micrometer Observation] under the hood. Below you can find an example of metrics for command execution. diff --git a/docs/modules/ROOT/pages/reference/okhttpclient.adoc b/docs/modules/ROOT/pages/reference/okhttpclient.adoc index 49e17f4383..547cec0c26 100644 --- a/docs/modules/ROOT/pages/reference/okhttpclient.adoc +++ b/docs/modules/ROOT/pages/reference/okhttpclient.adoc @@ -6,7 +6,7 @@ Micrometer supports https://square.github.io/okhttp/[OkHttp Client] instrumentat [[okhttpclient-observation]] == OkHttpClient Observation -Below you can find an example of how to instrument OkHttp Client with https://docs.micrometer.io/micrometer/reference/observation.html[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). +Below you can find an example of how to instrument OkHttp Client with xref:observation.adoc[Micrometer Observation]. That means that depending on your Observation Handler configuration you instrument once, and can have multiple benefits out of it (e.g. metrics, distributed tracing). [source,java,subs=+attributes] ----- From a07ada7e719e48a07e08d4db61d74803aa65d6fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:07:53 +0900 Subject: [PATCH 49/73] Bump com.netflix.spectator:spectator-reg-atlas from 1.7.4 to 1.7.7 (#4721) Bumps [com.netflix.spectator:spectator-reg-atlas](https://github.com/Netflix/spectator) from 1.7.4 to 1.7.7. - [Release notes](https://github.com/Netflix/spectator/releases) - [Changelog](https://github.com/Netflix/spectator/blob/main/CHANGELOG.md) - [Commits](https://github.com/Netflix/spectator/compare/v1.7.4...v1.7.7) --- updated-dependencies: - dependency-name: com.netflix.spectator:spectator-reg-atlas dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index efe4239082..921288ff8e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,7 +68,7 @@ reactor = "2022.0.15" rest-assured = "5.3.2" signalfx = "1.0.38" slf4j = "1.7.36" -spectator-atlas = "1.7.4" +spectator-atlas = "1.7.7" spring = "5.3.31" spring-javaformat = "0.0.41" testcontainers = "1.19.4" From 7202b6d3ed1d0a0d427d45f75fd6da16fe87598d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:08:32 +0900 Subject: [PATCH 50/73] Bump com.amazonaws:aws-java-sdk-cloudwatch from 1.12.650 to 1.12.651 (#4722) Bumps [com.amazonaws:aws-java-sdk-cloudwatch](https://github.com/aws/aws-sdk-java) from 1.12.650 to 1.12.651. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.650...1.12.651) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 921288ff8e..42c33074ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ aspectjweaver = "1.9.21" assertj = "3.24.2" awaitility = "4.2.0" # legacy SDK -aws-cloudwatch = "1.12.650" +aws-cloudwatch = "1.12.651" caffeine = "2.9.3" cloudwatch2 = "2.21.46" colt = "1.2.0" From 628f9b7f0417775931380ec6b53dbb466b7aa166 Mon Sep 17 00:00:00 2001 From: Georg Pirklbauer Date: Mon, 5 Feb 2024 04:20:50 +0100 Subject: [PATCH 51/73] Bump dynatrace-metric-utils-java to 2.2.0 (#4713) To be more compatible with the Unified Code for Units of Measure (UCUM), Dynatrace now allows curly braces in metric units. The utility library used to serialize metrics to the Dynatrace format currently rejects curly braces. --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 42c33074ac..cb46a07dee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,7 +14,7 @@ colt = "1.2.0" dagger = "2.48.1" dropwizard-metrics = "4.2.25" dropwizard-metrics5 = "5.0.0" -dynatrace-utils = "2.1.0" +dynatrace-utils = "2.2.0" ehcache2 = "2.10.9.2" ehcache3 = "3.10.8" gmetric4j = "1.0.10" From 2fb73a9f86622b20a4cea8a70a86785e0fe4ec11 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:21:28 +0900 Subject: [PATCH 52/73] Bump io.grpc:grpc-kotlin-stub from 1.4.0 to 1.4.1 (#4717) Bumps [io.grpc:grpc-kotlin-stub](https://github.com/grpc/grpc-kotlin) from 1.4.0 to 1.4.1. - [Release notes](https://github.com/grpc/grpc-kotlin/releases) - [Changelog](https://github.com/grpc/grpc-kotlin/blob/master/CHANGELOG.md) - [Commits](https://github.com/grpc/grpc-kotlin/compare/v1.4.0...v1.4.1) --- updated-dependencies: - dependency-name: io.grpc:grpc-kotlin-stub dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a1dfc6e1e3..ca6053c356 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ ehcache3 = "3.10.8" gmetric4j = "1.0.10" google-cloud-monitoring = "3.35.0" grpc = "1.58.0" -grpcKotlin = "1.4.0" +grpcKotlin = "1.4.1" guava = "32.1.2-jre" guice = "5.1.0" h2 = "2.2.224" From 78c9cd4cd9d885fd5d40cc694f47d0c7a830330f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 12:22:58 +0900 Subject: [PATCH 53/73] Bump software.amazon.awssdk:cloudwatch from 2.23.16 to 2.23.17 (#4720) Bumps software.amazon.awssdk:cloudwatch from 2.23.16 to 2.23.17. --- updated-dependencies: - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ca6053c356..7e22e09df6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" # legacy SDK aws-cloudwatch = "1.12.651" caffeine = "2.9.3" -cloudwatch2 = "2.23.16" +cloudwatch2 = "2.23.17" colt = "1.2.0" dagger = "2.50" dropwizard-metrics = "4.2.25" From 63266bccd34c6387be6f22f3df40a16e585740df Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Mon, 5 Feb 2024 12:35:29 +0900 Subject: [PATCH 54/73] Upgrade to Gradle Wrapper 8.6 (#4716) --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew.bat | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 136eb86a0c..565695aa42 100644 --- a/build.gradle +++ b/build.gradle @@ -364,7 +364,7 @@ nexusPublishing { } wrapper { - gradleVersion = '8.5' + gradleVersion = '8.6' } defaultTasks 'build' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1af9e0930b..a80b22ce5c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 6689b85bee..7101f8e467 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail From b43a8aa9f32c1377c9a62a05bc1855afc46b93fe Mon Sep 17 00:00:00 2001 From: Johnny Lim Date: Mon, 5 Feb 2024 22:22:13 +0900 Subject: [PATCH 55/73] Polish Apache HttpComponents instrumentation changes (#4037) See gh-3800 See gh-3941 --- .../hc5/ApacheHttpClientContext.java | 15 ++- ...ApacheHttpClientObservationConvention.java | 2 +- ...cheHttpClientObservationDocumentation.java | 2 +- ...ApacheHttpClientObservationConvention.java | 99 ++++++++++++---- .../hc5/ObservationExecChainHandler.java | 21 ++-- ...heHttpClientObservationConventionTest.java | 37 +++--- ...vationExecChainHandlerIntegrationTest.java | 109 +++++++++--------- .../hc5/ObservationExecChainHandlerTest.java | 26 +++-- 8 files changed, 183 insertions(+), 128 deletions(-) diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientContext.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientContext.java index 14e5e9c14a..353ee6534e 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientContext.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientContext.java @@ -32,6 +32,9 @@ */ public class ApacheHttpClientContext extends RequestReplySenderContext { + @SuppressWarnings("deprecation") + private static final DefaultUriMapper DEFAULT_URI_MAPPER = new DefaultUriMapper(); + private final HttpClientContext clientContext; private final Function uriMapper; @@ -45,7 +48,7 @@ public class ApacheHttpClientContext extends RequestReplySenderContext getUriMapper() { /** * Whether the route information should be contributed as tags with metrics. + * @return whether the route information should be contributed as tags with metrics * @deprecated as of 1.12.0 with no replacement. */ @Deprecated diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationConvention.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationConvention.java index dd0c1f5aa6..e6823c6411 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationConvention.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationConvention.java @@ -31,7 +31,7 @@ public interface ApacheHttpClientObservationConvention extends ObservationConven * that should hold the String representation of the URI template used for creating * the client URL. *

- * This value can be contributed as a {@link io.micrometer.common.KeyValue} to the + * This value can be contributed as an {@link io.micrometer.common.KeyValue} to the * recorded observations.

      * String uriTemplate = "/users/{id}";
      * HttpClientContext clientContext = ...
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationDocumentation.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationDocumentation.java
index 1bf1ff4121..61c90fc6e6 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationDocumentation.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ApacheHttpClientObservationDocumentation.java
@@ -73,7 +73,7 @@ public String asString() {
         },
         /**
          * Key name for exception.
-         * @since 1.11.0
+         * @since 1.12.0
          */
         EXCEPTION {
             @Override
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConvention.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConvention.java
index 01f87ba10a..b415968a0c 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConvention.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConvention.java
@@ -42,15 +42,25 @@ public class DefaultApacheHttpClientObservationConvention implements ApacheHttpC
      */
     public static final DefaultApacheHttpClientObservationConvention INSTANCE = new DefaultApacheHttpClientObservationConvention();
 
-    private static final KeyValue METHOD_UNKNOWN = KeyValue.of(ApacheHttpClientKeyNames.METHOD, "UNKNOWN");
+    private static final String CONTEXTUAL_NAME_UNKNOWN = "HTTP UNKNOWN";
 
-    private static final KeyValue URI_UNKNOWN = KeyValue.of(ApacheHttpClientKeyNames.URI, "UNKNOWN");
+    private static final KeyValue METHOD_UNKNOWN = ApacheHttpClientKeyNames.METHOD.withValue("UNKNOWN");
 
-    private static final KeyValue STATUS_IO_ERROR = KeyValue.of(ApacheHttpClientKeyNames.STATUS, "IO_ERROR");
+    private static final KeyValue URI_UNKNOWN = ApacheHttpClientKeyNames.URI.withValue("UNKNOWN");
 
-    private static final KeyValue STATUS_CLIENT_ERROR = KeyValue.of(ApacheHttpClientKeyNames.STATUS, "CLIENT_ERROR");
+    private static final KeyValue STATUS_IO_ERROR = ApacheHttpClientKeyNames.STATUS.withValue("IO_ERROR");
 
-    private static final KeyValue EXCEPTION_NONE = KeyValue.of(ApacheHttpClientKeyNames.EXCEPTION, KeyValue.NONE_VALUE);
+    private static final KeyValue STATUS_CLIENT_ERROR = ApacheHttpClientKeyNames.STATUS.withValue("CLIENT_ERROR");
+
+    private static final KeyValue EXCEPTION_NONE = ApacheHttpClientKeyNames.EXCEPTION.withValue(KeyValue.NONE_VALUE);
+
+    private static final KeyValue OUTCOME_UNKNOWN = ApacheHttpClientKeyNames.OUTCOME.withValue(Outcome.UNKNOWN.name());
+
+    private static final KeyValue TARGET_HOST_UNKNOWN = ApacheHttpClientKeyNames.TARGET_HOST.withValue("UNKNOWN");
+
+    private static final KeyValue TARGET_PORT_UNKNOWN = ApacheHttpClientKeyNames.TARGET_PORT.withValue("UNKNOWN");
+
+    private static final KeyValue TARGET_SCHEME_UNKNOWN = ApacheHttpClientKeyNames.TARGET_SCHEME.withValue("UNKNOWN");
 
     // There is no need to instantiate this class multiple times, but it may be extended,
     // hence protected visibility.
@@ -65,11 +75,10 @@ public String getName() {
     @Override
     public String getContextualName(ApacheHttpClientContext context) {
         HttpRequest request = context.getCarrier();
-        String methodName = "UNKNOWN";
         if (request != null && request.getMethod() != null) {
-            methodName = request.getMethod();
+            return "HTTP " + request.getMethod();
         }
-        return "HTTP " + methodName;
+        return CONTEXTUAL_NAME_UNKNOWN;
     }
 
     @Override
@@ -78,14 +87,26 @@ public KeyValues getLowCardinalityKeyValues(ApacheHttpClientContext context) {
                 targetPort(context), targetScheme(context), uri(context));
     }
 
+    /**
+     * Extract {@code exception} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code exception} key value
+     * @since 1.12.0
+     */
     protected KeyValue exception(ApacheHttpClientContext context) {
         Throwable error = context.getError();
         if (error != null) {
-            return KeyValue.of(ApacheHttpClientKeyNames.EXCEPTION, error.getClass().getSimpleName());
+            return ApacheHttpClientKeyNames.EXCEPTION.withValue(error.getClass().getSimpleName());
         }
         return EXCEPTION_NONE;
     }
 
+    /**
+     * Extract {@code method} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code method} key value
+     * @since 1.12.0
+     */
     protected KeyValue method(ApacheHttpClientContext context) {
         HttpRequest request = context.getCarrier();
         if (request == null || request.getMethod() == null) {
@@ -94,52 +115,88 @@ protected KeyValue method(ApacheHttpClientContext context) {
         return ApacheHttpClientKeyNames.METHOD.withValue(request.getMethod());
     }
 
+    /**
+     * Extract {@code outcome} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code outcome} key value
+     * @since 1.12.0
+     */
     protected KeyValue outcome(ApacheHttpClientContext context) {
         HttpResponse response = context.getResponse();
         if (response == null) {
-            return KeyValue.of(ApacheHttpClientKeyNames.OUTCOME, Outcome.UNKNOWN.name());
+            return OUTCOME_UNKNOWN;
         }
-        return KeyValue.of(ApacheHttpClientKeyNames.OUTCOME, Outcome.forStatus(response.getCode()).name());
+        return ApacheHttpClientKeyNames.OUTCOME.withValue(Outcome.forStatus(response.getCode()).name());
     }
 
+    /**
+     * Extract {@code status} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code status} key value
+     * @since 1.12.0
+     */
     protected KeyValue status(ApacheHttpClientContext context) {
         Throwable error = context.getError();
-        HttpResponse response = context.getResponse();
         if (error instanceof IOException || error instanceof HttpException || error instanceof RuntimeException) {
             return STATUS_IO_ERROR;
         }
-        else if (response == null) {
+        HttpResponse response = context.getResponse();
+        if (response == null) {
             return STATUS_CLIENT_ERROR;
         }
-        return KeyValue.of(ApacheHttpClientKeyNames.STATUS, Integer.toString(response.getCode()));
+        return ApacheHttpClientKeyNames.STATUS.withValue(String.valueOf(response.getCode()));
     }
 
+    /**
+     * Extract {@code target.host} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code target.host} key value
+     * @since 1.12.0
+     */
     protected KeyValue targetHost(ApacheHttpClientContext context) {
         RouteInfo httpRoute = context.getHttpClientContext().getHttpRoute();
         if (httpRoute != null) {
-            return KeyValue.of(ApacheHttpClientKeyNames.TARGET_HOST, httpRoute.getTargetHost().getHostName());
+            return ApacheHttpClientKeyNames.TARGET_HOST.withValue(httpRoute.getTargetHost().getHostName());
         }
-        return KeyValue.of(ApacheHttpClientKeyNames.TARGET_HOST, "UNKNOWN");
+        return TARGET_HOST_UNKNOWN;
     }
 
+    /**
+     * Extract {@code target.port} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code target.port} key value
+     * @since 1.12.0
+     */
     protected KeyValue targetPort(ApacheHttpClientContext context) {
         Object routeAttribute = context.getHttpClientContext().getAttribute("http.route");
         if (routeAttribute instanceof HttpRoute) {
             int port = ((HttpRoute) routeAttribute).getTargetHost().getPort();
-            return KeyValue.of(ApacheHttpClientKeyNames.TARGET_PORT, String.valueOf(port));
+            return ApacheHttpClientKeyNames.TARGET_PORT.withValue(String.valueOf(port));
         }
-        return KeyValue.of(ApacheHttpClientKeyNames.TARGET_PORT, "UNKNOWN");
+        return TARGET_PORT_UNKNOWN;
     }
 
+    /**
+     * Extract {@code target.scheme} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code target.scheme} key value
+     * @since 1.12.0
+     */
     protected KeyValue targetScheme(ApacheHttpClientContext context) {
         Object routeAttribute = context.getHttpClientContext().getAttribute("http.route");
         if (routeAttribute instanceof HttpRoute) {
-            return KeyValue.of(ApacheHttpClientKeyNames.TARGET_SCHEME,
-                    ((HttpRoute) routeAttribute).getTargetHost().getSchemeName());
+            return ApacheHttpClientKeyNames.TARGET_SCHEME
+                .withValue(((HttpRoute) routeAttribute).getTargetHost().getSchemeName());
         }
-        return KeyValue.of(ApacheHttpClientKeyNames.TARGET_SCHEME, "UNKNOWN");
+        return TARGET_SCHEME_UNKNOWN;
     }
 
+    /**
+     * Extract {@code uri} key value from context.
+     * @param context HTTP client context
+     * @return extracted {@code uri} key value
+     * @since 1.12.0
+     */
     @SuppressWarnings("deprecation")
     protected KeyValue uri(ApacheHttpClientContext context) {
         HttpClientContext clientContext = context.getHttpClientContext();
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandler.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandler.java
index 46da19edea..a75045fe71 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandler.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandler.java
@@ -29,9 +29,9 @@
 import org.apache.hc.core5.http.*;
 import org.apache.hc.core5.http.nio.AsyncDataConsumer;
 import org.apache.hc.core5.http.nio.AsyncEntityProducer;
-import org.apache.hc.core5.util.Args;
 
 import java.io.IOException;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicMarkableReference;
 
 /**
@@ -84,7 +84,7 @@ public void execute(HttpRequest request, AsyncEntityProducer entityProducer, Asy
             .observation(observationConvention, DefaultApacheHttpClientObservationConvention.INSTANCE,
                     () -> observationContext, observationRegistry)
             .start();
-        ObervableCancellableDependency cancellable = new ObervableCancellableDependency(observation);
+        ObservableCancellableDependency cancellable = new ObservableCancellableDependency(observation);
         chain.proceed(request, entityProducer, cancellable.wrapScope(scope), new AsyncExecCallback() {
 
             @Override
@@ -123,10 +123,10 @@ public ClassicHttpResponse execute(ClassicHttpRequest request, ExecChain.Scope s
             .observation(observationConvention, DefaultApacheHttpClientObservationConvention.INSTANCE,
                     () -> observationContext, observationRegistry)
             .start();
-        ClassicHttpResponse response;
         try {
-            response = chain.proceed(request, scope);
+            ClassicHttpResponse response = chain.proceed(request, scope);
             observationContext.setResponse(response);
+            return response;
         }
         catch (Throwable exc) {
             observation.error(exc);
@@ -135,16 +135,15 @@ public ClassicHttpResponse execute(ClassicHttpRequest request, ExecChain.Scope s
         finally {
             observation.stop();
         }
-        return response;
     }
 
-    private static class ObervableCancellableDependency implements CancellableDependency {
+    private static class ObservableCancellableDependency implements CancellableDependency {
 
         private final Observation observation;
 
         private final AtomicMarkableReference dependencyRef;
 
-        public ObervableCancellableDependency(Observation observation) {
+        ObservableCancellableDependency(Observation observation) {
             this.observation = observation;
             this.dependencyRef = new AtomicMarkableReference<>(null, false);
         }
@@ -155,9 +154,9 @@ public boolean isCancelled() {
         }
 
         @Override
-        public void setDependency(final Cancellable dependency) {
-            Args.notNull(dependency, "dependency");
-            final Cancellable actualDependency = dependencyRef.getReference();
+        public void setDependency(Cancellable dependency) {
+            Objects.requireNonNull(dependency, "dependency");
+            Cancellable actualDependency = dependencyRef.getReference();
             if (!dependencyRef.compareAndSet(actualDependency, dependency, false, false)) {
                 dependency.cancel();
             }
@@ -166,7 +165,7 @@ public void setDependency(final Cancellable dependency) {
         @Override
         public boolean cancel() {
             while (!dependencyRef.isMarked()) {
-                final Cancellable actualDependency = dependencyRef.getReference();
+                Cancellable actualDependency = dependencyRef.getReference();
                 if (dependencyRef.compareAndSet(actualDependency, actualDependency, false, true)) {
                     if (actualDependency != null) {
                         actualDependency.cancel();
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConventionTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConventionTest.java
index 6e16beb656..6c5615eb29 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConventionTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/DefaultApacheHttpClientObservationConventionTest.java
@@ -31,6 +31,7 @@
 import java.io.IOException;
 import java.util.stream.Stream;
 
+import static io.micrometer.core.instrument.binder.httpcomponents.hc5.ApacheHttpClientObservationDocumentation.ApacheHttpClientKeyNames.*;
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
@@ -67,7 +68,7 @@ void shouldContributeExceptionNoneWhenSuccess() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(null, clientContext);
         assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("exception", KeyValue.NONE_VALUE));
+            .contains(EXCEPTION.withValue(KeyValue.NONE_VALUE));
     }
 
     @Test
@@ -76,7 +77,7 @@ void shouldContributeExceptionWhenFailure() {
         ApacheHttpClientContext context = new ApacheHttpClientContext(null, clientContext);
         context.setError(new IllegalStateException("error"));
         assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("exception", "IllegalStateException"));
+            .contains(EXCEPTION.withValue("IllegalStateException"));
     }
 
     @Test
@@ -84,15 +85,14 @@ void shouldContributeHttpMethodName() {
         SimpleHttpRequest request = SimpleRequestBuilder.get("https://example.org/resource").build();
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(KeyValue.of("method", "GET"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(METHOD.withValue("GET"));
     }
 
     @Test
     void shouldContributeDefaultHttpMethodName() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(null, clientContext);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("method", "UNKNOWN"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(METHOD.withValue("UNKNOWN"));
     }
 
     @Test
@@ -101,8 +101,7 @@ void shouldContributeOutcome() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         context.setResponse(SimpleHttpResponse.create(200));
-        assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("outcome", "SUCCESS"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(OUTCOME.withValue("SUCCESS"));
     }
 
     @Test
@@ -110,8 +109,7 @@ void shouldContributeDefaultOutcome() {
         SimpleHttpRequest request = SimpleRequestBuilder.get("https://example.org/resource").build();
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("outcome", "UNKNOWN"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(OUTCOME.withValue("UNKNOWN"));
     }
 
     @ParameterizedTest
@@ -121,8 +119,7 @@ void shouldContributeStatusForErrors(Throwable exception) {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         context.setError(exception);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("status", "IO_ERROR"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(STATUS.withValue("IO_ERROR"));
     }
 
     static Stream exceptionsSource() {
@@ -136,7 +133,7 @@ void shouldContributeStatusForMissingResponse() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("status", "CLIENT_ERROR"));
+            .contains(STATUS.withValue("CLIENT_ERROR"));
     }
 
     @Test
@@ -145,7 +142,7 @@ void shouldContributeStatusForResponse() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         context.setResponse(SimpleHttpResponse.create(200));
-        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(KeyValue.of("status", "200"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(STATUS.withValue("200"));
     }
 
     @Test
@@ -153,9 +150,8 @@ void shouldContributeTargetWhenUnknown() {
         SimpleHttpRequest request = SimpleRequestBuilder.get("https://example.org/resource").build();
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(
-                KeyValue.of("target.host", "UNKNOWN"), KeyValue.of("target.port", "UNKNOWN"),
-                KeyValue.of("target.scheme", "UNKNOWN"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(TARGET_HOST.withValue("UNKNOWN"),
+                TARGET_PORT.withValue("UNKNOWN"), TARGET_SCHEME.withValue("UNKNOWN"));
     }
 
     @Test
@@ -166,8 +162,7 @@ void shouldContributeTargetWhenAvailable() throws Exception {
         clientContext.setAttribute(HttpClientContext.HTTP_ROUTE,
                 new HttpRoute(HttpHost.create("https://example.org:80")));
         assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(
-                KeyValue.of("target.host", "example.org"), KeyValue.of("target.port", "80"),
-                KeyValue.of("target.scheme", "https"));
+                TARGET_HOST.withValue("example.org"), TARGET_PORT.withValue("80"), TARGET_SCHEME.withValue("https"));
     }
 
     @Test
@@ -175,7 +170,7 @@ void shouldContributeUriTemplateWhenUnknown() {
         SimpleHttpRequest request = SimpleRequestBuilder.get("https://example.org/resource").build();
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
-        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(KeyValue.of("uri", "UNKNOWN"));
+        assertThat(observationConvention.getLowCardinalityKeyValues(context)).contains(URI.withValue("UNKNOWN"));
     }
 
     @Test
@@ -186,7 +181,7 @@ void shouldContributeUriTemplateFromAttribute() {
                 "https://example.org/{id}");
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("uri", "https://example.org/{id}"));
+            .contains(URI.withValue("https://example.org/{id}"));
     }
 
     @Test
@@ -198,7 +193,7 @@ void shouldContributeUriTemplateFromHeader() {
         HttpClientContext clientContext = HttpClientContext.create();
         ApacheHttpClientContext context = new ApacheHttpClientContext(request, clientContext);
         assertThat(observationConvention.getLowCardinalityKeyValues(context))
-            .contains(KeyValue.of("uri", "https://example.org/{id}"));
+            .contains(URI.withValue("https://example.org/{id}"));
     }
 
 }
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java
index 86c6a3ab19..9434791f0b 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerIntegrationTest.java
@@ -18,7 +18,6 @@
 import com.github.tomakehurst.wiremock.WireMockServer;
 import io.micrometer.observation.tck.TestObservationRegistry;
 import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
-import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
 import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
 import org.apache.hc.client5.http.classic.methods.HttpGet;
 import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
@@ -49,18 +48,17 @@
 
 import java.io.IOException;
 import java.net.SocketTimeoutException;
-import java.net.URI;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
 import static com.github.tomakehurst.wiremock.client.WireMock.*;
 import static com.github.tomakehurst.wiremock.stubbing.Scenario.STARTED;
+import static io.micrometer.core.instrument.binder.httpcomponents.hc5.ApacheHttpClientObservationDocumentation.ApacheHttpClientKeyNames.*;
 import static io.micrometer.observation.tck.TestObservationRegistryAssert.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 /**
- * Wiremock based integration tests for {@link ObservationExecChainHandler}.
+ * Wiremock-based integration tests for {@link ObservationExecChainHandler}.
  *
  * @author Lars Uffmann
  * @author Brian Clozel
@@ -68,7 +66,7 @@
 @ExtendWith(WiremockResolver.class)
 class ObservationExecChainHandlerIntegrationTest {
 
-    public static final String DEFAULT_METER_NAME = "httpcomponents.httpclient.request";
+    private static final String DEFAULT_METER_NAME = "httpcomponents.httpclient.request";
 
     private static final HttpClientResponseHandler NOOP_RESPONSE_HANDLER = (response) -> response;
 
@@ -86,9 +84,9 @@ void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server)
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SUCCESS")
-                .hasLowCardinalityKeyValue("status", "200")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SUCCESS"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("200"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
             // end::example_classic[]
         }
 
@@ -100,9 +98,9 @@ void recordClientErrorExchanges(@WiremockResolver.Wiremock WireMockServer server
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "CLIENT_ERROR")
-                .hasLowCardinalityKeyValue("status", "404")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("CLIENT_ERROR"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("404"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -113,7 +111,7 @@ void recordUnknownUriPatternByDefault(@WiremockResolver.Wiremock WireMockServer
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "UNKNOWN");
+                .hasLowCardinalityKeyValue(URI.withValue("UNKNOWN"));
         }
 
         @Test
@@ -127,7 +125,7 @@ void recordUriPatternWhenHeader(@WiremockResolver.Wiremock WireMockServer server
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "/some/{name}");
+                .hasLowCardinalityKeyValue(URI.withValue("/some/{name}"));
         }
 
         @Test
@@ -141,7 +139,7 @@ void recordUriPatternWhenContext(@WiremockResolver.Wiremock WireMockServer serve
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "/some/{name}");
+                .hasLowCardinalityKeyValue(URI.withValue("/some/{name}"));
         }
 
         @ParameterizedTest
@@ -150,13 +148,13 @@ void contextualNameContainsMethod(String methodName, @WiremockResolver.Wiremock
                 throws Exception {
             server.stubFor(any(anyUrl()));
             try (CloseableHttpClient client = classicClient()) {
-                HttpUriRequestBase request = new HttpUriRequestBase(methodName, URI.create(server.baseUrl()));
+                HttpUriRequestBase request = new HttpUriRequestBase(methodName, java.net.URI.create(server.baseUrl()));
                 executeClassic(client, request);
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
                 .hasContextualNameEqualTo("HTTP " + methodName)
-                .hasLowCardinalityKeyValue("method", methodName);
+                .hasLowCardinalityKeyValue(METHOD.withValue(methodName));
         }
 
         @Test
@@ -168,10 +166,10 @@ void recordProtocolErrorsAsIoErrors(@WiremockResolver.Wiremock WireMockServer se
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("status", "IO_ERROR")
-                .hasLowCardinalityKeyValue("exception", "ProtocolException")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("IO_ERROR"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("ProtocolException"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -183,10 +181,10 @@ void recordSocketTimeoutAsIoErrors(@WiremockResolver.Wiremock WireMockServer ser
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("status", "IO_ERROR")
-                .hasLowCardinalityKeyValue("exception", "SocketTimeoutException")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("IO_ERROR"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("SocketTimeoutException"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -197,9 +195,9 @@ void recordRequestRetries(@WiremockResolver.Wiremock WireMockServer server) thro
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SERVER_ERROR")
-                .hasLowCardinalityKeyValue("status", "503")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SERVER_ERROR"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("503"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
             assertThat(observationRegistry).hasNumberOfObservationsWithNameEqualTo(DEFAULT_METER_NAME, 2);
         }
 
@@ -216,8 +214,8 @@ void recordRequestRetriesWithSuccess(@WiremockResolver.Wiremock WireMockServer s
             try (CloseableHttpClient client = classicClient()) {
                 executeClassic(client, new HttpGet(server.baseUrl() + "/retry"));
             }
-            assertThat(observationRegistry).hasAnObservationWithAKeyValue("outcome", "SUCCESS")
-                .hasAnObservationWithAKeyValue("outcome", "SERVER_ERROR");
+            assertThat(observationRegistry).hasAnObservationWithAKeyValue(OUTCOME.withValue("SUCCESS"))
+                .hasAnObservationWithAKeyValue(OUTCOME.withValue("SERVER_ERROR"));
             assertThat(observationRegistry).hasNumberOfObservationsWithNameEqualTo(DEFAULT_METER_NAME, 2);
         }
 
@@ -236,9 +234,9 @@ void recordSuccessfulExchanges(@WiremockResolver.Wiremock WireMockServer server)
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SUCCESS")
-                .hasLowCardinalityKeyValue("status", "200")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SUCCESS"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("200"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
             // end::example_async[]
         }
 
@@ -251,9 +249,9 @@ void recordClientErrorExchanges(@WiremockResolver.Wiremock WireMockServer server
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "CLIENT_ERROR")
-                .hasLowCardinalityKeyValue("status", "404")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("CLIENT_ERROR"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("404"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -265,7 +263,7 @@ void recordUnknownUriPatternByDefault(@WiremockResolver.Wiremock WireMockServer
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "UNKNOWN");
+                .hasLowCardinalityKeyValue(URI.withValue("UNKNOWN"));
         }
 
         @Test
@@ -280,7 +278,7 @@ void recordUriPatternWhenHeader(@WiremockResolver.Wiremock WireMockServer server
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "/some/{name}");
+                .hasLowCardinalityKeyValue(URI.withValue("/some/{name}"));
         }
 
         @Test
@@ -294,7 +292,7 @@ void recordUriPatternWhenContext(@WiremockResolver.Wiremock WireMockServer serve
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("uri", "/some/{name}");
+                .hasLowCardinalityKeyValue(URI.withValue("/some/{name}"));
         }
 
         @ParameterizedTest
@@ -310,7 +308,7 @@ void contextualNameContainsMethod(String methodName, @WiremockResolver.Wiremock
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
                 .hasContextualNameEqualTo("HTTP " + methodName)
-                .hasLowCardinalityKeyValue("method", methodName);
+                .hasLowCardinalityKeyValue(METHOD.withValue(methodName));
         }
 
         @Test
@@ -322,10 +320,10 @@ void recordProtocolErrorsAsIoErrors(@WiremockResolver.Wiremock WireMockServer se
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("status", "IO_ERROR")
-                .hasLowCardinalityKeyValue("exception", "ProtocolException")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("IO_ERROR"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("ProtocolException"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -338,10 +336,10 @@ void recordSocketTimeoutAsIoErrors(@WiremockResolver.Wiremock WireMockServer ser
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("status", "IO_ERROR")
-                .hasLowCardinalityKeyValue("exception", "SocketTimeoutException")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("IO_ERROR"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("SocketTimeoutException"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
         }
 
         @Test
@@ -353,9 +351,9 @@ void recordRequestRetries(@WiremockResolver.Wiremock WireMockServer server) thro
             }
             assertThat(observationRegistry).hasObservationWithNameEqualTo(DEFAULT_METER_NAME)
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SERVER_ERROR")
-                .hasLowCardinalityKeyValue("status", "503")
-                .hasLowCardinalityKeyValue("method", "GET");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SERVER_ERROR"))
+                .hasLowCardinalityKeyValue(STATUS.withValue("503"))
+                .hasLowCardinalityKeyValue(METHOD.withValue("GET"));
             assertThat(observationRegistry).hasNumberOfObservationsWithNameEqualTo(DEFAULT_METER_NAME, 2);
         }
 
@@ -372,8 +370,8 @@ void recordRequestRetriesWithSuccess(@WiremockResolver.Wiremock WireMockServer s
                 SimpleHttpRequest request = SimpleRequestBuilder.get(server.baseUrl() + "/retry").build();
                 executeAsync(client, request);
             }
-            assertThat(observationRegistry).hasAnObservationWithAKeyValue("outcome", "SUCCESS")
-                .hasAnObservationWithAKeyValue("outcome", "SERVER_ERROR");
+            assertThat(observationRegistry).hasAnObservationWithAKeyValue(OUTCOME.withValue("SUCCESS"))
+                .hasAnObservationWithAKeyValue(OUTCOME.withValue("SERVER_ERROR"));
             assertThat(observationRegistry).hasNumberOfObservationsWithNameEqualTo(DEFAULT_METER_NAME, 2);
         }
 
@@ -410,7 +408,6 @@ private void executeClassic(CloseableHttpClient client, HttpContext context, Cla
     }
 
     private CloseableHttpAsyncClient asyncClient() {
-
         DefaultHttpRequestRetryStrategy retryStrategy = new DefaultHttpRequestRetryStrategy(1,
                 TimeValue.ofMilliseconds(500L));
 
@@ -434,15 +431,13 @@ private CloseableHttpAsyncClient asyncClient() {
     private void executeAsync(CloseableHttpAsyncClient client, SimpleHttpRequest request)
             throws ExecutionException, InterruptedException {
         client.start();
-        Future responseFuture = client.execute(request, null);
-        responseFuture.get();
+        client.execute(request, null).get();
     }
 
     private void executeAsync(CloseableHttpAsyncClient client, HttpContext context, SimpleHttpRequest request)
             throws ExecutionException, InterruptedException {
         client.start();
-        Future responseFuture = client.execute(request, context, null);
-        responseFuture.get();
+        client.execute(request, context, null).get();
     }
 
 }
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerTest.java
index f88fb21fbf..0e633559ae 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/httpcomponents/hc5/ObservationExecChainHandlerTest.java
@@ -15,6 +15,7 @@
  */
 package io.micrometer.core.instrument.binder.httpcomponents.hc5;
 
+import io.micrometer.common.KeyValue;
 import io.micrometer.common.lang.Nullable;
 import io.micrometer.observation.tck.TestObservationRegistry;
 import org.apache.hc.client5.http.HttpRoute;
@@ -37,6 +38,7 @@
 import java.io.IOException;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import static io.micrometer.core.instrument.binder.httpcomponents.hc5.ApacheHttpClientObservationDocumentation.ApacheHttpClientKeyNames.*;
 import static io.micrometer.observation.tck.TestObservationRegistryAssert.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
@@ -78,10 +80,10 @@ void setup() throws Exception {
         void shouldInstrumentReceivedResponses() throws Exception {
             ExecChain chain = mock(ExecChain.class);
             given(chain.proceed(any(), any())).willReturn(new BasicClassicHttpResponse(200));
-            ClassicHttpResponse response = handler.execute(request, this.scope, chain);
+            handler.execute(request, this.scope, chain);
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SUCCESS");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SUCCESS"));
         }
 
         @Test
@@ -93,8 +95,8 @@ void shouldInstrumentExceptions() throws Exception {
                 .isInstanceOf(IllegalArgumentException.class);
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("exception", "IllegalArgumentException");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("IllegalArgumentException"));
         }
 
         @Test
@@ -106,8 +108,8 @@ void shouldInstrumentCancelledRequests() throws Exception {
                 .isInstanceOf(RequestFailedException.class);
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("exception", "RequestFailedException");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("RequestFailedException"));
         }
 
     }
@@ -117,7 +119,7 @@ class AsyncClientTests {
 
         private AsyncExecChain.Scope scope;
 
-        private TestAsyncExecChain testAsyncExecChain = new TestAsyncExecChain();
+        private final TestAsyncExecChain testAsyncExecChain = new TestAsyncExecChain();
 
         @BeforeEach
         void setup() throws Exception {
@@ -136,7 +138,7 @@ void shouldInstrumentReceivedResponses() throws Exception {
 
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "SUCCESS");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("SUCCESS"));
         }
 
         @Test
@@ -149,8 +151,8 @@ void shouldInstrumentExceptions() throws Exception {
 
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("exception", "IllegalArgumentException");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue("IllegalArgumentException"));
         }
 
         @Test
@@ -162,8 +164,8 @@ void shouldInstrumentCancelledRequests() throws Exception {
 
             assertThat(observationRegistry).hasObservationWithNameEqualTo("httpcomponents.httpclient.request")
                 .that()
-                .hasLowCardinalityKeyValue("outcome", "UNKNOWN")
-                .hasLowCardinalityKeyValue("exception", "none");
+                .hasLowCardinalityKeyValue(OUTCOME.withValue("UNKNOWN"))
+                .hasLowCardinalityKeyValue(EXCEPTION.withValue(KeyValue.NONE_VALUE));
         }
 
     }

From 71e2e5e8e47ea2b3504ac9039dc835e001778675 Mon Sep 17 00:00:00 2001
From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com>
Date: Tue, 6 Feb 2024 13:05:44 +0900
Subject: [PATCH 56/73]  Document newly supported OTLP env vars

 See gh-4500 that added support for more environment variables. Documents that support in our reference documentation.

 Resolves gh-4566
---
 .../ROOT/pages/implementations/otlp.adoc      |  8 ++++--
 .../micrometer/registry/otlp/OtlpConfig.java  | 28 ++++++++++++++++---
 2 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/docs/modules/ROOT/pages/implementations/otlp.adoc b/docs/modules/ROOT/pages/implementations/otlp.adoc
index cf71caa430..90a967e2f9 100644
--- a/docs/modules/ROOT/pages/implementations/otlp.adoc
+++ b/docs/modules/ROOT/pages/implementations/otlp.adoc
@@ -35,15 +35,17 @@ 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`. +
+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`. +
 *Note*: This config was introduced in version 1.11.0.
 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]
 |===
diff --git a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java
index 58a2fed6f4..3183a6add6 100644
--- a/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java
+++ b/implementations/micrometer-registry-otlp/src/main/java/io/micrometer/registry/otlp/OtlpConfig.java
@@ -50,8 +50,15 @@ default String prefix() {
     }
 
     /**
-     * Defaults to http://localhost:4318/v1/metrics
-     * @return address to where metrics will be published.
+     * If no value is returned by {@link #get(String)}, environment variables
+     * {@code OTEL_EXPORTER_OTLP_METRICS_ENDPOINT} and {@code OTEL_EXPORTER_OTLP_ENDPOINT}
+     * environment variables will be checked, in that order, by the default
+     * implementation.
+     * @return address to where metrics will be published. Default is
+     * {@code http://localhost:4318/v1/metrics}
+     * @see OTLP
+     * Exporter Configuration
      */
     default String url() {
         return getUrlString(this, "url").orElseGet(() -> {
@@ -70,6 +77,14 @@ else if (!endpoint.endsWith("/v1/metrics")) {
         });
     }
 
+    /**
+     * Default implementation supports the environment variable
+     * {@code OTEL_METRIC_EXPORT_INTERVAL} when the step value is not provided by the
+     * {@link #get(String)} implementation.
+     * @return step size (reporting frequency) to use. The default is 1 minute.
+     * @see OTEL_METRIC_EXPORT_INTERVAL
+     */
     @Override
     default Duration step() {
         Validated step = getDuration(this, "step");
@@ -120,11 +135,16 @@ default Map resourceAttributes() {
     /**
      * {@link AggregationTemporality} of the OtlpMeterRegistry. This determines whether
      * the meters should be cumulative(AGGREGATION_TEMPORALITY_CUMULATIVE) or
-     * step/delta(AGGREGATION_TEMPORALITY_DELTA).
-     * @return the aggregationTemporality for OtlpMeterRegistry
+     * step/delta(AGGREGATION_TEMPORALITY_DELTA). Default implementation supports the
+     * environment variable {@code OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE} when
+     * a value is not provided by {@link #get(String)}.
+     * @return the aggregationTemporality; default is Cumulative
      * @see OTLP
      * Temporality
+     * @see OpenTelemetry
+     * Metrics Exporter - OTLP
      * @since 1.11.0
      */
     default AggregationTemporality aggregationTemporality() {

From 0b321c81cf4d50934c27a1d673551c67f1c4becb Mon Sep 17 00:00:00 2001
From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com>
Date: Tue, 6 Feb 2024 13:07:01 +0900
Subject: [PATCH 57/73] Polish OTLP docs

Remove reference to version now that docs are versioned with the code.
---
 docs/modules/ROOT/pages/implementations/otlp.adoc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/docs/modules/ROOT/pages/implementations/otlp.adoc b/docs/modules/ROOT/pages/implementations/otlp.adoc
index cf71caa430..500db8c278 100644
--- a/docs/modules/ROOT/pages/implementations/otlp.adoc
+++ b/docs/modules/ROOT/pages/implementations/otlp.adoc
@@ -40,8 +40,7 @@ management:
 ----
 
 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.
+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`.
 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:
 

From 7e0fb8d59ee01e227e8c4d56c0c3de097fbad7ec Mon Sep 17 00:00:00 2001
From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com>
Date: Tue, 6 Feb 2024 13:46:26 +0900
Subject: [PATCH 58/73] Deprecate Jersey server instrumentation

Direct users to the jersey-micrometer module now released from the Jersey project.

Resolves gh-4100
---
 .../instrument/binder/jersey/server/AnnotationFinder.java     | 4 ++++
 .../jersey/server/DefaultJerseyObservationConvention.java     | 2 ++
 .../binder/jersey/server/DefaultJerseyTagsProvider.java       | 2 ++
 .../core/instrument/binder/jersey/server/JerseyContext.java   | 2 ++
 .../core/instrument/binder/jersey/server/JerseyKeyValues.java | 1 +
 .../binder/jersey/server/JerseyObservationConvention.java     | 2 ++
 .../binder/jersey/server/JerseyObservationDocumentation.java  | 2 ++
 .../core/instrument/binder/jersey/server/JerseyTags.java      | 2 ++
 .../instrument/binder/jersey/server/JerseyTagsProvider.java   | 2 ++
 .../binder/jersey/server/MetricsApplicationEventListener.java | 2 ++
 .../binder/jersey/server/MetricsRequestEventListener.java     | 2 ++
 .../jersey/server/ObservationApplicationEventListener.java    | 2 ++
 .../binder/jersey/server/ObservationRequestEventListener.java | 2 ++
 .../core/instrument/binder/jersey/server/TimedFinder.java     | 1 +
 .../core/instrument/binder/jersey/server/package-info.java    | 1 +
 .../binder/jersey/server/DefaultJerseyTagsProviderTest.java   | 1 +
 .../binder/jersey/server/MetricsRequestEventListenerTest.java | 1 +
 .../jersey/server/MetricsRequestEventListenerTimedTest.java   | 1 +
 .../JerseyServerTimingInstrumentationVerificationTests.java   | 1 +
 .../main/java/io/micrometer/samples/jersey3/Jersey3Main.java  | 1 +
 .../test/java/io/micrometer/samples/jersey3/Jersey3Test.java  | 1 +
 21 files changed, 35 insertions(+)

diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/AnnotationFinder.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/AnnotationFinder.java
index 15b34075ec..a8a59d9d4e 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/AnnotationFinder.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/AnnotationFinder.java
@@ -18,6 +18,10 @@
 import java.lang.annotation.Annotation;
 import java.lang.reflect.AnnotatedElement;
 
+/**
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
+ */
+@Deprecated
 public interface AnnotationFinder {
 
     AnnotationFinder DEFAULT = new AnnotationFinder() {
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyObservationConvention.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyObservationConvention.java
index 605491a2ab..ca20ded1c3 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyObservationConvention.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyObservationConvention.java
@@ -26,7 +26,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class DefaultJerseyObservationConvention implements JerseyObservationConvention {
 
     private final String metricsName;
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProvider.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProvider.java
index 398e24a98b..211e8f57aa 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProvider.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProvider.java
@@ -26,7 +26,9 @@
  * @author Michael Weirauch
  * @author Johnny Lim
  * @since 1.8.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public final class DefaultJerseyTagsProvider implements JerseyTagsProvider {
 
     @Override
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyContext.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyContext.java
index b4e6842a1a..cd5c4261dc 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyContext.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyContext.java
@@ -28,7 +28,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class JerseyContext extends RequestReplyReceiverContext {
 
     private RequestEvent requestEvent;
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyKeyValues.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyKeyValues.java
index faf73d1515..e6e44488da 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyKeyValues.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyKeyValues.java
@@ -27,6 +27,7 @@
  * Factory methods for {@link KeyValue KeyValues} associated with a request-response
  * exchange that is handled by Jersey server.
  */
+@SuppressWarnings("deprecation")
 class JerseyKeyValues {
 
     private static final KeyValue URI_NOT_FOUND = JerseyObservationDocumentation.JerseyLegacyLowCardinalityTags.URI
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationConvention.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationConvention.java
index 8a97977c1d..fef2085599 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationConvention.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationConvention.java
@@ -24,7 +24,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public interface JerseyObservationConvention extends ObservationConvention {
 
     @Override
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationDocumentation.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationDocumentation.java
index fcc29347c8..7b9996dd13 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationDocumentation.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyObservationDocumentation.java
@@ -26,7 +26,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 @NonNullApi
 public enum JerseyObservationDocumentation implements ObservationDocumentation {
 
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTags.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTags.java
index d66d7196c1..a7b175fccb 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTags.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTags.java
@@ -34,7 +34,9 @@
  * @author Michael Weirauch
  * @author Johnny Lim
  * @since 1.8.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public final class JerseyTags {
 
     private static final Tag URI_NOT_FOUND = Tag.of("uri", "NOT_FOUND");
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTagsProvider.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTagsProvider.java
index 4f49c5380f..c8497f2c80 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTagsProvider.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/JerseyTagsProvider.java
@@ -23,7 +23,9 @@
  *
  * @author Michael Weirauch
  * @since 1.8.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public interface JerseyTagsProvider {
 
     /**
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsApplicationEventListener.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsApplicationEventListener.java
index d591ad1b1d..f35daada4a 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsApplicationEventListener.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsApplicationEventListener.java
@@ -29,7 +29,9 @@
  *
  * @author Michael Weirauch
  * @since 1.8.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class MetricsApplicationEventListener implements ApplicationEventListener {
 
     private final MeterRegistry meterRegistry;
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListener.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListener.java
index 6652b8caa4..876fe2cf09 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListener.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListener.java
@@ -35,7 +35,9 @@
  * @author Michael Weirauch
  * @author Jon Schneider
  * @since 1.8.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class MetricsRequestEventListener implements RequestEventListener {
 
     private final Map shortTaskSample = Collections
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationApplicationEventListener.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationApplicationEventListener.java
index 2685228f20..e2edcd4f8f 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationApplicationEventListener.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationApplicationEventListener.java
@@ -30,7 +30,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class ObservationApplicationEventListener implements ApplicationEventListener {
 
     private final ObservationRegistry observationRegistry;
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationRequestEventListener.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationRequestEventListener.java
index 05f40e8e76..13c4cfafa3 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationRequestEventListener.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/ObservationRequestEventListener.java
@@ -33,7 +33,9 @@
  *
  * @author Marcin Grzejszczak
  * @since 1.10.0
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
+@Deprecated
 public class ObservationRequestEventListener implements RequestEventListener {
 
     private final Map observations = Collections
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/TimedFinder.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/TimedFinder.java
index ba2b1ee223..33dd469ba4 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/TimedFinder.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/TimedFinder.java
@@ -24,6 +24,7 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 
+@SuppressWarnings("deprecation")
 class TimedFinder {
 
     private final AnnotationFinder annotationFinder;
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/package-info.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/package-info.java
index 9c6777e4d5..fa95ea8374 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/package-info.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jersey/server/package-info.java
@@ -16,5 +16,6 @@
 
 /**
  * Meter binders for Jersey.
+ * @deprecated since 1.13.0 use the jersey-micrometer module in the Jersey project instead
  */
 package io.micrometer.core.instrument.binder.jersey.server;
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProviderTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProviderTest.java
index 5b6a4349eb..084997cf57 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProviderTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/DefaultJerseyTagsProviderTest.java
@@ -44,6 +44,7 @@
  * @author Michael Weirauch
  * @author Johnny Lim
  */
+@SuppressWarnings("deprecation")
 class DefaultJerseyTagsProviderTest {
 
     private final DefaultJerseyTagsProvider tagsProvider = new DefaultJerseyTagsProvider();
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTest.java
index 44243c6e8c..70166534b2 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTest.java
@@ -38,6 +38,7 @@
  * @author Michael Weirauch
  * @author Johnny Lim
  */
+@SuppressWarnings("deprecation")
 class MetricsRequestEventListenerTest extends JerseyTest {
 
     static {
diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTimedTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTimedTest.java
index 8348bee772..b9c3207c5a 100644
--- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTimedTest.java
+++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jersey/server/MetricsRequestEventListenerTimedTest.java
@@ -39,6 +39,7 @@
 /**
  * @author Michael Weirauch
  */
+@SuppressWarnings("deprecation")
 class MetricsRequestEventListenerTimedTest extends JerseyTest {
 
     static {
diff --git a/micrometer-test/src/test/java/io/micrometer/core/instrument/JerseyServerTimingInstrumentationVerificationTests.java b/micrometer-test/src/test/java/io/micrometer/core/instrument/JerseyServerTimingInstrumentationVerificationTests.java
index 7831633135..381c383d80 100644
--- a/micrometer-test/src/test/java/io/micrometer/core/instrument/JerseyServerTimingInstrumentationVerificationTests.java
+++ b/micrometer-test/src/test/java/io/micrometer/core/instrument/JerseyServerTimingInstrumentationVerificationTests.java
@@ -30,6 +30,7 @@
 import javax.ws.rs.core.Response;
 import java.net.URI;
 
+@SuppressWarnings("deprecation")
 class JerseyServerTimingInstrumentationVerificationTests extends HttpServerTimingInstrumentationVerificationTests {
 
     JerseyTest jerseyTest;
diff --git a/samples/micrometer-samples-jersey3/src/main/java/io/micrometer/samples/jersey3/Jersey3Main.java b/samples/micrometer-samples-jersey3/src/main/java/io/micrometer/samples/jersey3/Jersey3Main.java
index 23d55ec915..333c19bf14 100644
--- a/samples/micrometer-samples-jersey3/src/main/java/io/micrometer/samples/jersey3/Jersey3Main.java
+++ b/samples/micrometer-samples-jersey3/src/main/java/io/micrometer/samples/jersey3/Jersey3Main.java
@@ -32,6 +32,7 @@
 import java.net.InetSocketAddress;
 import java.time.Duration;
 
+@SuppressWarnings("deprecation")
 public class Jersey3Main {
 
     public static void main(String[] args) throws IOException {
diff --git a/samples/micrometer-samples-jersey3/src/test/java/io/micrometer/samples/jersey3/Jersey3Test.java b/samples/micrometer-samples-jersey3/src/test/java/io/micrometer/samples/jersey3/Jersey3Test.java
index 184d96cbcc..5ca300edfe 100644
--- a/samples/micrometer-samples-jersey3/src/test/java/io/micrometer/samples/jersey3/Jersey3Test.java
+++ b/samples/micrometer-samples-jersey3/src/test/java/io/micrometer/samples/jersey3/Jersey3Test.java
@@ -32,6 +32,7 @@
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+@SuppressWarnings("deprecation")
 class Jersey3Test extends JerseyTest {
 
     static final String TIMER_METRIC_NAME = "http.server.requests";

From 4743b3ce649579034a7006f432a5eafbacdac4a0 Mon Sep 17 00:00:00 2001
From: Marcin Grzejszczak 
Date: Tue, 6 Feb 2024 15:58:09 +0100
Subject: [PATCH 59/73] Added more high-overview docs with graphs; fixes
 gh-4726

---
 docs/modules/ROOT/nav.adoc                    |   2 +-
 .../{handler.adoc => components.adoc}         |  73 ++-
 .../ROOT/pages/observation/instrumenting.adoc | 502 ++++++++++++++++--
 .../ROOT/pages/observation/introduction.adoc  |  44 +-
 .../ObservationConfiguringTests.java          |   2 +-
 .../observation/ObservationHandlerTests.java  |   2 +-
 6 files changed, 555 insertions(+), 70 deletions(-)
 rename docs/modules/ROOT/pages/observation/{handler.adoc => components.adoc} (59%)

diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 6ec1f5246c..d1f1bdaf1f 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -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]
diff --git a/docs/modules/ROOT/pages/observation/handler.adoc b/docs/modules/ROOT/pages/observation/components.adoc
similarity index 59%
rename from docs/modules/ROOT/pages/observation/handler.adoc
rename to docs/modules/ROOT/pages/observation/components.adoc
index 3ee9f0b766..06185a1a71 100644
--- a/docs/modules/ROOT/pages/observation/handler.adoc
+++ b/docs/modules/ROOT/pages/observation/components.adoc
@@ -1,5 +1,69 @@
+[[micrometer-observation-components]]
+= Observation Components
+
+In this section we will describe main components related to Micrometer Observation.
+
+* <>
+* <>
+* <>
+* <>
+* <>
+
+*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 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
 
 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:
@@ -19,13 +83,8 @@ include::{include-java}/observation/ObservationHandlerTests.java[tags=observatio
 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).
 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`:
 
diff --git a/docs/modules/ROOT/pages/observation/instrumenting.adoc b/docs/modules/ROOT/pages/observation/instrumenting.adoc
index 83e919fe56..1ae78f8234 100644
--- a/docs/modules/ROOT/pages/observation/instrumenting.adoc
+++ b/docs/modules/ROOT/pages/observation/instrumenting.adoc
@@ -1,6 +1,8 @@
 [[micrometer-observation-handler]]
 = Instrumentation
 
+IMPORTANT: This section of the documentation is targeted to users who want to add instrumentation to their codebase.
+
 In this section, we see some common examples of reusing existing Micrometer and Micrometer Tracing handlers and context types to do instrumentation.
 
 IMPORTANT: Before you decide to instrument a project yourself, double-check whether that it has not already been instrumented!
@@ -14,68 +16,198 @@ To better convey how you can do instrumentation, we need to distinguish two conc
 
 *Creation of Observations* - We want to wrap an operation in an Observation to get measurements. We need to know if there previously has been a parent Observation to maintain the parent-child relationship of Observations.
 
-[[instrumentation_of_thread_switching_components]]
-== Instrumentation of Thread Switching Components
-
-We might want to create an Observation around a `Runnable` or `Callable` that we're submitting through an `Executor`. For that to work, we need to know if there was an Observation in the parent thread that the new thread should continue or for which a child Observation should be created.
-
-Consider the following example:
-
-[source,java]
------
-include::{include-java}/observation/ObservationInstrumentingTests.java[tags=executor,indent=0]
-
-include::{include-java}/observation/ObservationInstrumentingTests.java[tags=thread_switching,indent=0]
------
-
-[[instrumentation_of_reactive_libraries]]
-== Instrumentation of Reactive Libraries
-
-In this section, we discuss how to wrap Reactive libraries in Observations and how to use Reactor Context to safely propagate Observations between threads.
-
-[[instrumentation_of_reactive_libraries_after_reactor_3_5_3]]
-=== For Reactor 3.5.3 and After
-
-In the Reactor 3.5.3 release (through this https://github.com/reactor/reactor-core/pull/3335[PR]), an option to turn on automated context propagation was added. To use this, ensure that you use the following projects at minimum in the following versions:
-
-- Reactor https://github.com/reactor/reactor-core/releases/tag/v3.5.7[3.5.7]
-- Micrometer Context-Propagation https://github.com/micrometer-metrics/context-propagation/releases/tag/v1.0.3[1.0.3]
-- Micrometer https://github.com/micrometer-metrics/micrometer/releases/tag/v1.10.8[1.10.8]
-- Micrometer Tracing https://github.com/micrometer-metrics/tracing/releases/tag/v1.0.7[1.0.7]
-
-To use the feature, call the new Reactor's Hook method (for example, in your `public static void main` method), like this:
-
-[source,java]
------
-include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor_hook,indent=0]
------
-
-This automatically wraps Reactor's internal mechanisms to propagate context between operators, threads, and so on. Usage of `tap` and `handle` or the Context Propagation API is not required.
-
-Consider the following example:
-
-[source,java]
------
-include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor_with_hook,indent=0]
------
-
-If the performance of this approach is not satisfactory, check whether disabling the hook and explicitly using `handle` or `tap` operators improves the performance.
-
-[[instrumentation_of_reactive_libraries_before_reactor_3_5_3]]
-=== Before Reactor 3.5.3
-
-The preferred way of propagating elements through the Flux by using Reactor is not through `ThreadLocal` instances but through Reactor Context. Reactor, however, gives you two operators: `tap()` and `handle()`. With these two operators, if the https://docs.micrometer.io/context-propagation/reference/[Micrometer Context Propagation] library is on the classpath, it sets the thread local values for you.
-
-Consider the following example:
-
-[source,java]
------
-include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor,indent=0]
------
-
 [[instrumentation_of_http_communication]]
 == Instrumentation of HTTP Communication
 
+In this section you can find how to instrument libraries that do HTTP communication.
+
+[[instrumentation_of_http_communication_client]]
+=== Instrumentation of HTTP Client Communication
+
+*Basic explanation of HTTP client side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// RequestReplySenderContext -> Carrier: Wrap
+// ObservationRegistry -> Observation: Create
+// RequestReplySenderContext -> Observation: Create
+// ObservationConvention -> Observation: Create
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌─────────────────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
+│RequestReplySenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└────────────┬────────────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
+             │                 │              │                │                 │                    │
+             │      Wrap       │              │                │                 │                    │
+             │────────────────>│              │                │                 │                    │
+             │                 │              │                │                 │                    │
+             │                 │              │     Create     │                 │                    │
+             │                 │              │───────────────>│                 │                    │
+             │                 │              │                │                 │                    │
+             │                 │   Create     │                │                 │                    │
+             │────────────────────────────────────────────────>│                 │                    │
+             │                 │              │                │                 │                    │
+             │                 │              │                │     Create      │                    │
+             │                 │              │                │<────────────────│                    │
+             │                 │              │                │                 │                    │
+             │                 │              │                │            Wrap in Scope             │
+             │                 │              │                │─────────────────────────────────────>│
+┌────────────┴────────────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
+│RequestReplySenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└─────────────────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
+-----
+
+. Create a `RequestReplySenderContext` that wraps a carrier (e.g. `HttpRequest`)
+.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> httpRequest.header(key, value)`)
+.. Set the carrier on the `RequestReplySenderContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. carrier will be enriched with proper headers)
+. Wrap the code to instrument (e.g. sending of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+
+*More detailed explanation of HTTP client side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// RequestReplySenderContext -> Carrier: Wrap
+// ObservationConvention -> Observation: Create
+// RequestReplySenderContext -> Observation: Create
+// Observation -> ObservationHandler: Start
+// ObservationHandler -> Propagator: Instrument Carrier
+// Propagator -> Carrier: Instrument Carrier
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌─────────────────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐   ┌──────────┐┌──────────────────┐
+│RequestReplySenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
+└────────────┬────────────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘   └────┬─────┘└────────┬─────────┘
+             │                 │               │                 │               │                  │               │
+             │      Wrap       │               │                 │               │                  │               │
+             │────────────────>│               │                 │               │                  │               │
+             │                 │               │                 │               │                  │               │
+             │                 │               │     Create      │               │                  │               │
+             │                 │               │────────────────>│               │                  │               │
+             │                 │               │                 │               │                  │               │
+             │                 │    Create     │                 │               │                  │               │
+             │──────────────────────────────────────────────────>│               │                  │               │
+             │                 │               │                 │               │                  │               │
+             │                 │               │                 │     Start     │                  │               │
+             │                 │               │                 │──────────────>│                  │               │
+             │                 │               │                 │               │                  │               │
+             │                 │               │                 │               │Instrument Carrier│               │
+             │                 │               │                 │               │─────────────────>│               │
+             │                 │               │                 │               │                  │               │
+             │                 │               │         Instrument Carrier      │                  │               │
+             │                 │<───────────────────────────────────────────────────────────────────│               │
+             │                 │               │                 │               │                  │               │
+             │                 │               │                 │               │  Wrap in Scope   │               │
+             │                 │               │                 │─────────────────────────────────────────────────>│
+┌────────────┴────────────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐   ┌────┴─────┐┌────────┴─────────┐
+│RequestReplySenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
+└─────────────────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘   └──────────┘└──────────────────┘
+-----
+
+. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingSenderTracingObservationHandler` from Micrometer Tracing)
+. Create a `RequestReplySenderContext` that wraps a carrier (e.g. `HttpRequest`)
+.. In its constructor explain how to enrich the headers (e.g. `(carrier, key, value) -> carrier.header(key, value)`)
+.. Set the carrier on the `RequestReplySenderContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start the registered handler will instrument the carrier
+. Wrap the code to instrument (e.g. sending of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+
+[[instrumentation_of_http_communication_server]]
+=== Instrumentation of HTTP Server Communication
+
+*Basic explanation of HTTP server side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// RequestReplyReceiverContext -> Carrier: Wrap
+// ObservationRegistry -> Observation: Create
+// RequestReplyReceiverContext -> Observation: Create
+// ObservationConvention -> Observation: Create
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌───────────────────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
+│RequestReplyReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└─────────────┬─────────────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
+              │                  │              │                │                 │                    │
+              │       Wrap       │              │                │                 │                    │
+              │─────────────────>│              │                │                 │                    │
+              │                  │              │                │                 │                    │
+              │                  │              │     Create     │                 │                    │
+              │                  │              │───────────────>│                 │                    │
+              │                  │              │                │                 │                    │
+              │                  │   Create     │                │                 │                    │
+              │─────────────────────────────────────────────────>│                 │                    │
+              │                  │              │                │                 │                    │
+              │                  │              │                │     Create      │                    │
+              │                  │              │                │<────────────────│                    │
+              │                  │              │                │                 │                    │
+              │                  │              │                │            Wrap in Scope             │
+              │                  │              │                │─────────────────────────────────────>│
+┌─────────────┴─────────────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
+│RequestReplyReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└───────────────────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
+-----
+
+. Create a `RequestReplyReceiverContext` that wraps a carrier (e.g. `HttpRequest`)
+.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+.. Set the carrier on the `RequestReplyReceiverContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. tracing information will be retrieved from the headers)
+. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+
+*More detailed explanation of HTTP client side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// RequestReplyReceiverContext -> Carrier: Wrap
+// ObservationConvention -> Observation: Create
+// RequestReplyReceiverContext -> Observation: Create
+// Observation -> ObservationHandler: Start
+// ObservationHandler -> Propagator: Extract Carrier
+// Propagator -> Carrier: Extract Carrier
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌───────────────────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐┌──────────┐┌──────────────────┐
+│RequestReplyReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
+└─────────────┬─────────────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘└────┬─────┘└────────┬─────────┘
+              │                  │               │                 │               │               │               │
+              │       Wrap       │               │                 │               │               │               │
+              │─────────────────>│               │                 │               │               │               │
+              │                  │               │                 │               │               │               │
+              │                  │               │     Create      │               │               │               │
+              │                  │               │────────────────>│               │               │               │
+              │                  │               │                 │               │               │               │
+              │                  │    Create     │                 │               │               │               │
+              │───────────────────────────────────────────────────>│               │               │               │
+              │                  │               │                 │               │               │               │
+              │                  │               │                 │     Start     │               │               │
+              │                  │               │                 │──────────────>│               │               │
+              │                  │               │                 │               │               │               │
+              │                  │               │                 │               │Extract Carrier│               │
+              │                  │               │                 │               │──────────────>│               │
+              │                  │               │                 │               │               │               │
+              │                  │               │         Extract Carrier         │               │               │
+              │                  │<────────────────────────────────────────────────────────────────│               │
+              │                  │               │                 │               │               │               │
+              │                  │               │                 │               │ Wrap in Scope │               │
+              │                  │               │                 │──────────────────────────────────────────────>│
+┌─────────────┴─────────────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐┌────┴─────┐┌────────┴─────────┐
+│RequestReplyReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
+└───────────────────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘└──────────┘└──────────────────┘
+-----
+
+. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+. Create a `RequestReplyReceiverContext` that wraps a carrier (e.g. `HttpRequest`)
+.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+.. Set the carrier on the `RequestReplyReceiverContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, propagation will happen (e.g. tracing information will be retrieved from the headers)
+. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+
+[[instrumentation_of_http_communication_example]]
+=== Instrumentation of HTTP Communication Example
+
 To instrument an HTTP-based communication, we need to use the `RequestReplySenderContext` and `RequestReplyReceiverContext` for the client and server side, respectively.
 
 As an example for the client side, we use a handler that instruments the HTTP request by adding a `foo:bar` header (if you have Micrometer Tracing on the classpath, you could reuse the `PropagatingSenderTracingObservationHandler` and `PropagatingReceiverTracingObservationHandler` to propagate tracing context over the wire). Let's consider an example of such a handler:
@@ -106,8 +238,200 @@ Consider the following HTTP server side instrumentation that reuses the handler:
 include::{include-java}/observation/ObservationInstrumentingTests.java[tags=http_server,indent=0]
 -----
 
+[[instrumentation_of_messaging_communication]]
 == Instrumentation of Messaging Communication
 
+In this section you can find how to instrument libraries that do fire-and-forget like communication.
+
+[[instrumentation_of_messaging_communication_producer]]
+=== Instrumentation of Messaging Producer Side
+
+*Basic explanation of messaging producer side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// SenderContext -> Carrier: Wrap
+// ObservationRegistry -> Observation: Create
+// SenderContext -> Observation: Create
+// ObservationConvention -> Observation: Create
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌─────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
+│SenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└──────┬──────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
+       │           │              │                │                 │                    │
+       │   Wrap    │              │                │                 │                    │
+       │──────────>│              │                │                 │                    │
+       │           │              │                │                 │                    │
+       │           │              │     Create     │                 │                    │
+       │           │              │───────────────>│                 │                    │
+       │           │              │                │                 │                    │
+       │           │      Create  │                │                 │                    │
+       │──────────────────────────────────────────>│                 │                    │
+       │           │              │                │                 │                    │
+       │           │              │                │     Create      │                    │
+       │           │              │                │<────────────────│                    │
+       │           │              │                │                 │                    │
+       │           │              │                │            Wrap in Scope             │
+       │           │              │                │─────────────────────────────────────>│
+┌──────┴──────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
+│SenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└─────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
+-----
+
+. Create a `SenderContext` that wraps a carrier (e.g. `AmqpMessage`)
+.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> amqpMessage.header(key, value)`)
+.. Set the carrier on the `SenderContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. carrier will be enriched with proper headers)
+. Wrap the code to instrument (e.g. sending of an AMQP message) in scope (e.g. through the `observe` or `scoped` method)
+
+*More detailed explanation of messaging producer side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// SenderContext -> Carrier: Wrap
+// ObservationConvention -> Observation: Create
+// SenderContext -> Observation: Create
+// Observation -> ObservationHandler: Start
+// ObservationHandler -> Propagator: Instrument Carrier
+// Propagator -> Carrier: Instrument Carrier
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌─────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐   ┌──────────┐┌──────────────────┐
+│SenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
+└──────┬──────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘   └────┬─────┘└────────┬─────────┘
+       │           │               │                 │               │                  │               │
+       │   Wrap    │               │                 │               │                  │               │
+       │──────────>│               │                 │               │                  │               │
+       │           │               │                 │               │                  │               │
+       │           │               │     Create      │               │                  │               │
+       │           │               │────────────────>│               │                  │               │
+       │           │               │                 │               │                  │               │
+       │           │       Create  │                 │               │                  │               │
+       │────────────────────────────────────────────>│               │                  │               │
+       │           │               │                 │               │                  │               │
+       │           │               │                 │     Start     │                  │               │
+       │           │               │                 │──────────────>│                  │               │
+       │           │               │                 │               │                  │               │
+       │           │               │                 │               │Instrument Carrier│               │
+       │           │               │                 │               │─────────────────>│               │
+       │           │               │                 │               │                  │               │
+       │           │               │         Instrument Carrier      │                  │               │
+       │           │<───────────────────────────────────────────────────────────────────│               │
+       │           │               │                 │               │                  │               │
+       │           │               │                 │               │  Wrap in Scope   │               │
+       │           │               │                 │─────────────────────────────────────────────────>│
+┌──────┴──────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐   ┌────┴─────┐┌────────┴─────────┐
+│SenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
+└─────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘   └──────────┘└──────────────────┘
+-----
+
+. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+. Create a `SenderContext` that wraps a carrier (e.g. `AmqpMessage`)
+.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> amqpMessage.header(key, value)`)
+.. Set the carrier on the `SenderContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers)
+. Wrap the code to instrument (e.g. sending of an AMQP message) in scope (e.g. through the `observe` or `scoped` method)
+
+[[instrumentation_of_messaging_communication_consumer]]
+=== Instrumentation of Messaging Consumer Side Communication
+
+*Basic explanation of messaging consumer side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// ReceiverContext -> Carrier: Wrap
+// ObservationRegistry -> Observation: Create
+// ReceiverContext -> Observation: Create
+// ObservationConvention -> Observation: Create
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌───────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
+│ReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└───────┬───────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
+        │            │              │                │                 │                    │
+        │    Wrap    │              │                │                 │                    │
+        │───────────>│              │                │                 │                    │
+        │            │              │                │                 │                    │
+        │            │              │     Create     │                 │                    │
+        │            │              │───────────────>│                 │                    │
+        │            │              │                │                 │                    │
+        │            │      Create  │                │                 │                    │
+        │───────────────────────────────────────────>│                 │                    │
+        │            │              │                │                 │                    │
+        │            │              │                │     Create      │                    │
+        │            │              │                │<────────────────│                    │
+        │            │              │                │                 │                    │
+        │            │              │                │            Wrap in Scope             │
+        │            │              │                │─────────────────────────────────────>│
+┌───────┴───────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
+│ReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
+└───────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
+-----
+
+. Create a `ReceiverContext` that wraps a carrier (e.g. `AmqpMessage`)
+.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+.. Set the carrier on the `ReceiverContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. tracing information will be retrieved from the headers)
+. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+.. Some libraries (e.g. RabbitMQ) you might not have a handle on user's code, and you may require the user to allow starting a consumer side Observation and opening its scope by the framework (putting values in thread local) with the requirement of manually closing both the scope and stopping the Observation later by the user in their code!
+
+*More detailed explanation of messaging consumer side instrumentation*
+
+// https://arthursonzogni.com/Diagon/#Sequence
+// ReceiverContext -> Carrier: Wrap
+// ObservationConvention -> Observation: Create
+// ReceiverContext -> Observation: Create
+// Observation -> ObservationHandler: Start
+// ObservationHandler -> Propagator: Extract Carrier
+// Propagator -> Carrier: Extract Carrier
+// Observation -> Code to Instrument: Wrap in Scope
+[source,subs=+attributes]
+-----
+┌───────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐┌──────────┐┌──────────────────┐
+│ReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
+└───────┬───────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘└────┬─────┘└────────┬─────────┘
+        │            │               │                 │               │               │               │
+        │    Wrap    │               │                 │               │               │               │
+        │───────────>│               │                 │               │               │               │
+        │            │               │                 │               │               │               │
+        │            │               │     Create      │               │               │               │
+        │            │               │────────────────>│               │               │               │
+        │            │               │                 │               │               │               │
+        │            │       Create  │                 │               │               │               │
+        │─────────────────────────────────────────────>│               │               │               │
+        │            │               │                 │               │               │               │
+        │            │               │                 │     Start     │               │               │
+        │            │               │                 │──────────────>│               │               │
+        │            │               │                 │               │               │               │
+        │            │               │                 │               │Extract Carrier│               │
+        │            │               │                 │               │──────────────>│               │
+        │            │               │                 │               │               │               │
+        │            │               │         Extract Carrier         │               │               │
+        │            │<────────────────────────────────────────────────────────────────│               │
+        │            │               │                 │               │               │               │
+        │            │               │                 │               │ Wrap in Scope │               │
+        │            │               │                 │──────────────────────────────────────────────>│
+┌───────┴───────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐┌────┴─────┐┌────────┴─────────┐
+│ReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
+└───────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘└──────────┘└──────────────────┘
+-----
+
+. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+. Create a `ReceiverContext` that wraps a carrier (e.g. `AmqpMessage`)
+.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+.. Set the carrier on the `ReceiverContext`
+. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
+.. On `Observation` start, propagation will happen (e.g. tracing information will be retrieved from the headers)
+. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+.. Some libraries (e.g. RabbitMQ) you might not have a handle on user's code, and you may require the user to allow starting a consumer side Observation and opening its scope by the framework (putting values in thread local) with the requirement of manually closing both the scope and stopping the Observation later by the user in their code!
+
+[[instrumentation_of_messaging_communication_example]]
+=== Instrumentation of Messaging Communication Example
+
 To instrument messaging-based communication we need to use the `SenderContext` and `ReceiverContext` for the producer and consumer side respectively.
 
 In this section we will create a simple instrumentation for Apache Kafka.
@@ -180,3 +504,63 @@ Let's look at the assertions after having sent and received a message. We should
 -----
 include::{include-java}/observation/messaging/ObservationMessagingIntegrationTest.java[tags=test_assertions,indent=0]
 -----
+
+
+[[instrumentation_of_thread_switching_components]]
+== Instrumentation of Thread Switching Components
+
+We might want to create an Observation around a `Runnable` or `Callable` that we're submitting through an `Executor`. For that to work, we need to know if there was an Observation in the parent thread that the new thread should continue or for which a child Observation should be created.
+
+Consider the following example:
+
+[source,java]
+-----
+include::{include-java}/observation/ObservationInstrumentingTests.java[tags=executor,indent=0]
+
+include::{include-java}/observation/ObservationInstrumentingTests.java[tags=thread_switching,indent=0]
+-----
+
+[[instrumentation_of_reactive_libraries]]
+== Instrumentation of Reactive Libraries
+
+In this section, we discuss how to wrap Reactive libraries in Observations and how to use Reactor Context to safely propagate Observations between threads.
+
+[[instrumentation_of_reactive_libraries_after_reactor_3_5_3]]
+=== For Reactor 3.5.3 and After
+
+In the Reactor 3.5.3 release (through this https://github.com/reactor/reactor-core/pull/3335[PR]), an option to turn on automated context propagation was added. To use this, ensure that you use the following projects at minimum in the following versions:
+
+- Reactor https://github.com/reactor/reactor-core/releases/tag/v3.5.7[3.5.7]
+- Micrometer Context-Propagation https://github.com/micrometer-metrics/context-propagation/releases/tag/v1.0.3[1.0.3]
+- Micrometer https://github.com/micrometer-metrics/micrometer/releases/tag/v1.10.8[1.10.8]
+- Micrometer Tracing https://github.com/micrometer-metrics/tracing/releases/tag/v1.0.7[1.0.7]
+
+To use the feature, call the new Reactor's Hook method (for example, in your `public static void main` method), like this:
+
+[source,java]
+-----
+include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor_hook,indent=0]
+-----
+
+This automatically wraps Reactor's internal mechanisms to propagate context between operators, threads, and so on. Usage of `tap` and `handle` or the Context Propagation API is not required.
+
+Consider the following example:
+
+[source,java]
+-----
+include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor_with_hook,indent=0]
+-----
+
+If the performance of this approach is not satisfactory, check whether disabling the hook and explicitly using `handle` or `tap` operators improves the performance.
+
+[[instrumentation_of_reactive_libraries_before_reactor_3_5_3]]
+=== Before Reactor 3.5.3
+
+The preferred way of propagating elements through the Flux by using Reactor is not through `ThreadLocal` instances but through Reactor Context. Reactor, however, gives you two operators: `tap()` and `handle()`. With these two operators, if the https://docs.micrometer.io/context-propagation/reference/[Micrometer Context Propagation] library is on the classpath, it sets the thread local values for you.
+
+Consider the following example:
+
+[source,java]
+-----
+include::{include-java}/observation/ObservationInstrumentingTests.java[tags=reactor,indent=0]
+-----
diff --git a/docs/modules/ROOT/pages/observation/introduction.adoc b/docs/modules/ROOT/pages/observation/introduction.adoc
index 16cc451b17..c37ca16989 100644
--- a/docs/modules/ROOT/pages/observation/introduction.adoc
+++ b/docs/modules/ROOT/pages/observation/introduction.adoc
@@ -45,4 +45,46 @@ include::{include-java}/observation/ObservationTestingTests.java[tags=example,in
 
 TIP: Calling `observe(() -> ...)` leads to starting the Observation, putting it in scope, running the lambda, putting an error on the Observation if one took place, closing the scope and stopping the Observation.
 
-// TODO: Add a link to docs gen
+[[micrometer-observation-building-blocks]]
+== Building Blocks
+
+In this section we will describe a high overview of Micrometer Observation components. You can read more about those in xref:observation/components.adoc[this part of the documentation].
+
+Glossary
+
+- `ObservationRegistry` - registry containing `Observation` related configuration (e.g. handlers, predicates, filters)
+- `ObservationHandler` - handles lifecycle of an `Observation` (e.g. create a timer on observation start, stop it on observation stop)
+- `ObservationFilter` - mutates the `Context` before the `Observation` gets stopped (e.g. add a high cardinality key-value with the cloud server region)
+- `ObservationPredicate` - condition to disable creation of an `Observation` (e.g. don't create observations with given key-value)
+- `Context` (actually `Observation.Context`) - a mutable map attached to an `Observation`, passed between handlers (that way you can pass state without doing any thread locals)
+- `ObservationConvention` - mean to separate Observation lifecycle (starting, stopping, opening scopes) from adding meta-data (such as observation name, key-value pairs). That way the naming of observations and meta-data handling becomes a configuration problem (e.g. adding key-values do not require changing instrumentation code, but changing the convention)
+
+[[micrometer-observation-usage]]
+=== Usage Flow
+
+// https://arthursonzogni.com/Diagon/#GraphDAG
+// ObservationHandler->ObservationRegistry
+// ObservationFilter->ObservationRegistry
+// ObservationPredicate->ObservationRegistry
+// ObservationRegistry->Observation
+// Context->Observation
+// ObservationConvention->Observation
+[source,subs=+attributes]
+-----
+┌──────────────────┐┌─────────────────┐┌────────────────────┐┌───────┐┌─────────────────────┐
+│ObservationHandler││ObservationFilter││ObservationPredicate││Context││ObservationConvention│
+└┬─────────────────┘└┬────────────────┘└┬───────────────────┘└┬──────┘└┬────────────────────┘
+┌▽───────────────────▽──────────────────▽┐                    │        │
+│ObservationRegistry                     │                    │        │
+└┬───────────────────────────────────────┘                    │        │
+┌▽────────────────────────────────────────────────────────────▽────────▽┐
+│Observation                                                            │
+└───────────────────────────────────────────────────────────────────────┘
+-----
+
+* `ObservationHandler`, `ObservationFilter`, `ObservationPredicate` get registered on the `ObservationRegistry`
+** `ObservationHandler` can be composed together (e.g. via the `FirstMatchingCompositeObservationHandler` - that can be useful when you group multiple handlers of the same type, e.g. `TracingHandler` or `MeterHandler`)
+* `ObservationRegistry`, `Context` are mandatory to create an `Observation`
+** Either you create an `Observation` with name, `ObservationRegistry` and `Context`
+** Or with `ObservationRegistry`, `ObservationConvention`
+* When `Observation` calls its lifecycle methods, all `ObservationHandlers` that pass the `supportsContext` check with the corresponding `Context` will have their lifecycle methods executed (e.g. if a handler has an `instanceof SenderContext` check in `supportsContext` then it will be called only for such types of contexts)
diff --git a/docs/src/test/java/io/micrometer/docs/observation/ObservationConfiguringTests.java b/docs/src/test/java/io/micrometer/docs/observation/ObservationConfiguringTests.java
index 2c0e6ef266..90c06d0444 100644
--- a/docs/src/test/java/io/micrometer/docs/observation/ObservationConfiguringTests.java
+++ b/docs/src/test/java/io/micrometer/docs/observation/ObservationConfiguringTests.java
@@ -26,7 +26,7 @@
 import static org.assertj.core.api.BDDAssertions.then;
 
 /**
- * Sources for observation-handler.adoc
+ * Sources for observation-components.adoc
  */
 class ObservationConfiguringTests {
 
diff --git a/docs/src/test/java/io/micrometer/docs/observation/ObservationHandlerTests.java b/docs/src/test/java/io/micrometer/docs/observation/ObservationHandlerTests.java
index b03be0d4e6..fea4717707 100644
--- a/docs/src/test/java/io/micrometer/docs/observation/ObservationHandlerTests.java
+++ b/docs/src/test/java/io/micrometer/docs/observation/ObservationHandlerTests.java
@@ -36,7 +36,7 @@
 import static io.micrometer.docs.observation.ObservationHandlerTests.TaxObservationDocumentation.TaxLowCardinalityKeyNames.TAX_TYPE;
 
 /**
- * Sources for observation-handler.adoc
+ * Sources for observation-components.adoc
  */
 class ObservationHandlerTests {
 

From ecaa2593e8ce29d3e6435a51622e709197a5c471 Mon Sep 17 00:00:00 2001
From: Marcin Grzejszczak 
Date: Tue, 6 Feb 2024 16:11:14 +0100
Subject: [PATCH 60/73] Polish

---
 docs/modules/ROOT/pages/observation.adoc | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/docs/modules/ROOT/pages/observation.adoc b/docs/modules/ROOT/pages/observation.adoc
index 5623d8ff01..9d10963d46 100644
--- a/docs/modules/ROOT/pages/observation.adoc
+++ b/docs/modules/ROOT/pages/observation.adoc
@@ -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."_
+****

From 00717367aec558218eb355b8086a53dba9f7ac8d Mon Sep 17 00:00:00 2001
From: Marcin Grzejszczak 
Date: Wed, 7 Feb 2024 17:47:49 +0100
Subject: [PATCH 61/73] Changes following the review

---
 .../ROOT/pages/observation/components.adoc    |   8 +-
 .../ROOT/pages/observation/instrumenting.adoc | 499 ++++++------------
 2 files changed, 167 insertions(+), 340 deletions(-)

diff --git a/docs/modules/ROOT/pages/observation/components.adoc b/docs/modules/ROOT/pages/observation/components.adoc
index 06185a1a71..7caa2ea2d5 100644
--- a/docs/modules/ROOT/pages/observation/components.adoc
+++ b/docs/modules/ROOT/pages/observation/components.adoc
@@ -55,7 +55,7 @@ In this section we will describe main components related to Micrometer Observati
 └─────────────────┘
 -----
 
-`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 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`.
+`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
@@ -65,6 +65,10 @@ To pass information between the instrumented code and the handler (or between ha
 [[micrometer-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:
 
@@ -80,7 +84,7 @@ 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-handler-example]]
diff --git a/docs/modules/ROOT/pages/observation/instrumenting.adoc b/docs/modules/ROOT/pages/observation/instrumenting.adoc
index 1ae78f8234..6ba97769f7 100644
--- a/docs/modules/ROOT/pages/observation/instrumenting.adoc
+++ b/docs/modules/ROOT/pages/observation/instrumenting.adoc
@@ -24,186 +24,98 @@ In this section you can find how to instrument libraries that do HTTP communicat
 [[instrumentation_of_http_communication_client]]
 === Instrumentation of HTTP Client Communication
 
-*Basic explanation of HTTP client side instrumentation*
+*Explanation of HTTP client side instrumentation*
 
 // https://arthursonzogni.com/Diagon/#Sequence
-// RequestReplySenderContext -> Carrier: Wrap
-// ObservationRegistry -> Observation: Create
-// RequestReplySenderContext -> Observation: Create
-// ObservationConvention -> Observation: Create
-// Observation -> Code to Instrument: Wrap in Scope
+// [1] RequestReplySenderContext -> [2] Carrier: Wrap
+// [3] ObservationRegistry -> [4] Observation: Create
+// [1] RequestReplySenderContext -> [4] Observation: Create
+// [5] ObservationConvention -> [4] Observation: Create
+// [4] Observation -> [6] ObservationHandler: onStart
+// [4] Observation -> [7] Code to Instrument: Wrap in Scope
 [source,subs=+attributes]
 -----
-┌─────────────────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
-│RequestReplySenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└────────────┬────────────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
-             │                 │              │                │                 │                    │
-             │      Wrap       │              │                │                 │                    │
-             │────────────────>│              │                │                 │                    │
-             │                 │              │                │                 │                    │
-             │                 │              │     Create     │                 │                    │
-             │                 │              │───────────────>│                 │                    │
-             │                 │              │                │                 │                    │
-             │                 │   Create     │                │                 │                    │
-             │────────────────────────────────────────────────>│                 │                    │
-             │                 │              │                │                 │                    │
-             │                 │              │                │     Create      │                    │
-             │                 │              │                │<────────────────│                    │
-             │                 │              │                │                 │                    │
-             │                 │              │                │            Wrap in Scope             │
-             │                 │              │                │─────────────────────────────────────>│
-┌────────────┴────────────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
-│RequestReplySenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└─────────────────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
------
-
-. Create a `RequestReplySenderContext` that wraps a carrier (e.g. `HttpRequest`)
-.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> httpRequest.header(key, value)`)
-.. Set the carrier on the `RequestReplySenderContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. carrier will be enriched with proper headers)
-. Wrap the code to instrument (e.g. sending of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
-
-*More detailed explanation of HTTP client side instrumentation*
-
-// https://arthursonzogni.com/Diagon/#Sequence
-// RequestReplySenderContext -> Carrier: Wrap
-// ObservationConvention -> Observation: Create
-// RequestReplySenderContext -> Observation: Create
-// Observation -> ObservationHandler: Start
-// ObservationHandler -> Propagator: Instrument Carrier
-// Propagator -> Carrier: Instrument Carrier
-// Observation -> Code to Instrument: Wrap in Scope
-[source,subs=+attributes]
------
-┌─────────────────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐   ┌──────────┐┌──────────────────┐
-│RequestReplySenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
-└────────────┬────────────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘   └────┬─────┘└────────┬─────────┘
-             │                 │               │                 │               │                  │               │
-             │      Wrap       │               │                 │               │                  │               │
-             │────────────────>│               │                 │               │                  │               │
-             │                 │               │                 │               │                  │               │
-             │                 │               │     Create      │               │                  │               │
-             │                 │               │────────────────>│               │                  │               │
-             │                 │               │                 │               │                  │               │
-             │                 │    Create     │                 │               │                  │               │
-             │──────────────────────────────────────────────────>│               │                  │               │
-             │                 │               │                 │               │                  │               │
-             │                 │               │                 │     Start     │                  │               │
-             │                 │               │                 │──────────────>│                  │               │
-             │                 │               │                 │               │                  │               │
-             │                 │               │                 │               │Instrument Carrier│               │
-             │                 │               │                 │               │─────────────────>│               │
-             │                 │               │                 │               │                  │               │
-             │                 │               │         Instrument Carrier      │                  │               │
-             │                 │<───────────────────────────────────────────────────────────────────│               │
-             │                 │               │                 │               │                  │               │
-             │                 │               │                 │               │  Wrap in Scope   │               │
-             │                 │               │                 │─────────────────────────────────────────────────>│
-┌────────────┴────────────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐   ┌────┴─────┐┌────────┴─────────┐
-│RequestReplySenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
-└─────────────────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘   └──────────┘└──────────────────┘
------
-
-. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingSenderTracingObservationHandler` from Micrometer Tracing)
-. Create a `RequestReplySenderContext` that wraps a carrier (e.g. `HttpRequest`)
-.. In its constructor explain how to enrich the headers (e.g. `(carrier, key, value) -> carrier.header(key, value)`)
-.. Set the carrier on the `RequestReplySenderContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start the registered handler will instrument the carrier
-. Wrap the code to instrument (e.g. sending of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+┌─────────────────────────────┐┌───────────┐┌───────────────────────┐┌───────────────┐┌─────────────────────────┐┌──────────────────────┐┌──────────────────────┐
+│[1] RequestReplySenderContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└──────────────┬──────────────┘└─────┬─────┘└───────────┬───────────┘└───────┬───────┘└────────────┬────────────┘└──────────┬───────────┘└──────────┬───────────┘
+               │                     │                  │                    │                     │                        │                       │
+               │        Wrap         │                  │                    │                     │                        │                       │
+               │────────────────────>│                  │                    │                     │                        │                       │
+               │                     │                  │                    │                     │                        │                       │
+               │                     │                  │       Create       │                     │                        │                       │
+               │                     │                  │───────────────────>│                     │                        │                       │
+               │                     │                  │                    │                     │                        │                       │
+               │                     │     Create       │                    │                     │                        │                       │
+               │────────────────────────────────────────────────────────────>│                     │                        │                       │
+               │                     │                  │                    │                     │                        │                       │
+               │                     │                  │                    │       Create        │                        │                       │
+               │                     │                  │                    │<────────────────────│                        │                       │
+               │                     │                  │                    │                     │                        │                       │
+               │                     │                  │                    │                   onStart                    │                       │
+               │                     │                  │                    │─────────────────────────────────────────────>│                       │
+               │                     │                  │                    │                     │                        │                       │
+               │                     │                  │                    │                     │      Wrap in Scope     │                       │
+               │                     │                  │                    │─────────────────────────────────────────────────────────────────────>│
+┌──────────────┴──────────────┐┌─────┴─────┐┌───────────┴───────────┐┌───────┴───────┐┌────────────┴────────────┐┌──────────┴───────────┐┌──────────┴───────────┐
+│[1] RequestReplySenderContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└─────────────────────────────┘└───────────┘└───────────────────────┘└───────────────┘└─────────────────────────┘└──────────────────────┘└──────────────────────┘
+-----
+
+* In the <3> `ObservationRegistry` register a <6> handler that will propagate context (e.g. `PropagatingSenderTracingObservationHandler` from Micrometer Tracing)
+* Create a <1> `RequestReplySenderContext` that wraps a <2> carrier (e.g. `HttpRequest`)
+** In its constructor explain how to enrich the headers (e.g. `(key, value) -> httpRequest.header(key, value)`)
+** Set the <2> carrier on the <1> `RequestReplySenderContext`
+* Create an <4> `Observation`, optionally using the <5> `ObservationConvention` with the sender context
+** On <4> `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers) via an <6> `ObservationHandler`
+* Wrap the <7> code to instrument (e.g. sending of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
 
 [[instrumentation_of_http_communication_server]]
 === Instrumentation of HTTP Server Communication
 
-*Basic explanation of HTTP server side instrumentation*
-
-// https://arthursonzogni.com/Diagon/#Sequence
-// RequestReplyReceiverContext -> Carrier: Wrap
-// ObservationRegistry -> Observation: Create
-// RequestReplyReceiverContext -> Observation: Create
-// ObservationConvention -> Observation: Create
-// Observation -> Code to Instrument: Wrap in Scope
-[source,subs=+attributes]
------
-┌───────────────────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
-│RequestReplyReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└─────────────┬─────────────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
-              │                  │              │                │                 │                    │
-              │       Wrap       │              │                │                 │                    │
-              │─────────────────>│              │                │                 │                    │
-              │                  │              │                │                 │                    │
-              │                  │              │     Create     │                 │                    │
-              │                  │              │───────────────>│                 │                    │
-              │                  │              │                │                 │                    │
-              │                  │   Create     │                │                 │                    │
-              │─────────────────────────────────────────────────>│                 │                    │
-              │                  │              │                │                 │                    │
-              │                  │              │                │     Create      │                    │
-              │                  │              │                │<────────────────│                    │
-              │                  │              │                │                 │                    │
-              │                  │              │                │            Wrap in Scope             │
-              │                  │              │                │─────────────────────────────────────>│
-┌─────────────┴─────────────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
-│RequestReplyReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└───────────────────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
------
-
-. Create a `RequestReplyReceiverContext` that wraps a carrier (e.g. `HttpRequest`)
-.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
-.. Set the carrier on the `RequestReplyReceiverContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. tracing information will be retrieved from the headers)
-. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
-
-*More detailed explanation of HTTP client side instrumentation*
+*Explanation of HTTP server side instrumentation*
 
 // https://arthursonzogni.com/Diagon/#Sequence
-// RequestReplyReceiverContext -> Carrier: Wrap
-// ObservationConvention -> Observation: Create
-// RequestReplyReceiverContext -> Observation: Create
-// Observation -> ObservationHandler: Start
-// ObservationHandler -> Propagator: Extract Carrier
-// Propagator -> Carrier: Extract Carrier
-// Observation -> Code to Instrument: Wrap in Scope
+// [1] RequestReplyReceiverContext -> [2] Carrier: Wrap
+// [3] ObservationRegistry -> [4] Observation: Create
+// [1] RequestReplyReceiverContext -> [4] Observation: Create
+// [5] ObservationConvention -> [4] Observation: Create
+// [4] Observation -> [6] ObservationHandler: onStart
+// [4] Observation -> [7] Code to Instrument: Wrap in Scope
 [source,subs=+attributes]
 -----
-┌───────────────────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐┌──────────┐┌──────────────────┐
-│RequestReplyReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
-└─────────────┬─────────────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘└────┬─────┘└────────┬─────────┘
-              │                  │               │                 │               │               │               │
-              │       Wrap       │               │                 │               │               │               │
-              │─────────────────>│               │                 │               │               │               │
-              │                  │               │                 │               │               │               │
-              │                  │               │     Create      │               │               │               │
-              │                  │               │────────────────>│               │               │               │
-              │                  │               │                 │               │               │               │
-              │                  │    Create     │                 │               │               │               │
-              │───────────────────────────────────────────────────>│               │               │               │
-              │                  │               │                 │               │               │               │
-              │                  │               │                 │     Start     │               │               │
-              │                  │               │                 │──────────────>│               │               │
-              │                  │               │                 │               │               │               │
-              │                  │               │                 │               │Extract Carrier│               │
-              │                  │               │                 │               │──────────────>│               │
-              │                  │               │                 │               │               │               │
-              │                  │               │         Extract Carrier         │               │               │
-              │                  │<────────────────────────────────────────────────────────────────│               │
-              │                  │               │                 │               │               │               │
-              │                  │               │                 │               │ Wrap in Scope │               │
-              │                  │               │                 │──────────────────────────────────────────────>│
-┌─────────────┴─────────────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐┌────┴─────┐┌────────┴─────────┐
-│RequestReplyReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
-└───────────────────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘└──────────┘└──────────────────┘
------
-
-. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
-. Create a `RequestReplyReceiverContext` that wraps a carrier (e.g. `HttpRequest`)
-.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
-.. Set the carrier on the `RequestReplyReceiverContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, propagation will happen (e.g. tracing information will be retrieved from the headers)
-. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+┌───────────────────────────────┐┌───────────┐┌───────────────────────┐┌───────────────┐┌─────────────────────────┐┌──────────────────────┐┌──────────────────────┐
+│[1] RequestReplyReceiverContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└───────────────┬───────────────┘└─────┬─────┘└───────────┬───────────┘└───────┬───────┘└────────────┬────────────┘└──────────┬───────────┘└──────────┬───────────┘
+                │                      │                  │                    │                     │                        │                       │
+                │         Wrap         │                  │                    │                     │                        │                       │
+                │─────────────────────>│                  │                    │                     │                        │                       │
+                │                      │                  │                    │                     │                        │                       │
+                │                      │                  │       Create       │                     │                        │                       │
+                │                      │                  │───────────────────>│                     │                        │                       │
+                │                      │                  │                    │                     │                        │                       │
+                │                      │     Create       │                    │                     │                        │                       │
+                │─────────────────────────────────────────────────────────────>│                     │                        │                       │
+                │                      │                  │                    │                     │                        │                       │
+                │                      │                  │                    │       Create        │                        │                       │
+                │                      │                  │                    │<────────────────────│                        │                       │
+                │                      │                  │                    │                     │                        │                       │
+                │                      │                  │                    │                   onStart                    │                       │
+                │                      │                  │                    │─────────────────────────────────────────────>│                       │
+                │                      │                  │                    │                     │                        │                       │
+                │                      │                  │                    │                     │      Wrap in Scope     │                       │
+                │                      │                  │                    │─────────────────────────────────────────────────────────────────────>│
+┌───────────────┴───────────────┐┌─────┴─────┐┌───────────┴───────────┐┌───────┴───────┐┌────────────┴────────────┐┌──────────┴───────────┐┌──────────┴───────────┐
+│[1] RequestReplyReceiverContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└───────────────────────────────┘└───────────┘└───────────────────────┘└───────────────┘└─────────────────────────┘└──────────────────────┘└──────────────────────┘
+-----
+
+* In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+* Create a <1> `RequestReplyReceiverContext` that wraps a <2> carrier (e.g. `HttpRequest`)
+** In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+** Set the <2> carrier on the <1> `RequestReplyReceiverContext`
+* Create an <4> `Observation`, optionally using the <5> `ObservationConvention` with the sender context
+** On <4> `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers) via an <6> `ObservationHandler`
+* Wrap the <6> code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
 
 [[instrumentation_of_http_communication_example]]
 === Instrumentation of HTTP Communication Example
@@ -246,188 +158,99 @@ In this section you can find how to instrument libraries that do fire-and-forget
 [[instrumentation_of_messaging_communication_producer]]
 === Instrumentation of Messaging Producer Side
 
-*Basic explanation of messaging producer side instrumentation*
+*Explanation of messaging producer side instrumentation*
 
 // https://arthursonzogni.com/Diagon/#Sequence
-// SenderContext -> Carrier: Wrap
-// ObservationRegistry -> Observation: Create
-// SenderContext -> Observation: Create
-// ObservationConvention -> Observation: Create
-// Observation -> Code to Instrument: Wrap in Scope
+// [1] SenderContext -> [2] Carrier: Wrap
+// [3] ObservationRegistry -> [4] Observation: Create
+// [1] SenderContext -> [4] Observation: Create
+// [5] ObservationConvention -> [4] Observation: Create
+// [4] Observation -> [6] ObservationHandler: onStart
+// [4] Observation -> [7] Code to Instrument: Wrap in Scope
 [source,subs=+attributes]
 -----
-┌─────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
-│SenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└──────┬──────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
-       │           │              │                │                 │                    │
-       │   Wrap    │              │                │                 │                    │
-       │──────────>│              │                │                 │                    │
-       │           │              │                │                 │                    │
-       │           │              │     Create     │                 │                    │
-       │           │              │───────────────>│                 │                    │
-       │           │              │                │                 │                    │
-       │           │      Create  │                │                 │                    │
-       │──────────────────────────────────────────>│                 │                    │
-       │           │              │                │                 │                    │
-       │           │              │                │     Create      │                    │
-       │           │              │                │<────────────────│                    │
-       │           │              │                │                 │                    │
-       │           │              │                │            Wrap in Scope             │
-       │           │              │                │─────────────────────────────────────>│
-┌──────┴──────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
-│SenderContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└─────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
------
-
-. Create a `SenderContext` that wraps a carrier (e.g. `AmqpMessage`)
-.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> amqpMessage.header(key, value)`)
-.. Set the carrier on the `SenderContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. carrier will be enriched with proper headers)
-. Wrap the code to instrument (e.g. sending of an AMQP message) in scope (e.g. through the `observe` or `scoped` method)
-
-*More detailed explanation of messaging producer side instrumentation*
-
-// https://arthursonzogni.com/Diagon/#Sequence
-// SenderContext -> Carrier: Wrap
-// ObservationConvention -> Observation: Create
-// SenderContext -> Observation: Create
-// Observation -> ObservationHandler: Start
-// ObservationHandler -> Propagator: Instrument Carrier
-// Propagator -> Carrier: Instrument Carrier
-// Observation -> Code to Instrument: Wrap in Scope
-[source,subs=+attributes]
------
-┌─────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐   ┌──────────┐┌──────────────────┐
-│SenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
-└──────┬──────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘   └────┬─────┘└────────┬─────────┘
-       │           │               │                 │               │                  │               │
-       │   Wrap    │               │                 │               │                  │               │
-       │──────────>│               │                 │               │                  │               │
-       │           │               │                 │               │                  │               │
-       │           │               │     Create      │               │                  │               │
-       │           │               │────────────────>│               │                  │               │
-       │           │               │                 │               │                  │               │
-       │           │       Create  │                 │               │                  │               │
-       │────────────────────────────────────────────>│               │                  │               │
-       │           │               │                 │               │                  │               │
-       │           │               │                 │     Start     │                  │               │
-       │           │               │                 │──────────────>│                  │               │
-       │           │               │                 │               │                  │               │
-       │           │               │                 │               │Instrument Carrier│               │
-       │           │               │                 │               │─────────────────>│               │
-       │           │               │                 │               │                  │               │
-       │           │               │         Instrument Carrier      │                  │               │
-       │           │<───────────────────────────────────────────────────────────────────│               │
-       │           │               │                 │               │                  │               │
-       │           │               │                 │               │  Wrap in Scope   │               │
-       │           │               │                 │─────────────────────────────────────────────────>│
-┌──────┴──────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐   ┌────┴─────┐┌────────┴─────────┐
-│SenderContext││Carrier││ObservationConvention││Observation││ObservationHandler│   │Propagator││Code to Instrument│
-└─────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘   └──────────┘└──────────────────┘
------
-
-. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
-. Create a `SenderContext` that wraps a carrier (e.g. `AmqpMessage`)
-.. In its constructor explain how to enrich the headers (e.g. `(key, value) -> amqpMessage.header(key, value)`)
-.. Set the carrier on the `SenderContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers)
-. Wrap the code to instrument (e.g. sending of an AMQP message) in scope (e.g. through the `observe` or `scoped` method)
+┌─────────────────┐┌───────────┐┌───────────────────────┐┌───────────────┐┌─────────────────────────┐┌──────────────────────┐┌──────────────────────┐
+│[1] SenderContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└────────┬────────┘└─────┬─────┘└───────────┬───────────┘└───────┬───────┘└────────────┬────────────┘└──────────┬───────────┘└──────────┬───────────┘
+         │               │                  │                    │                     │                        │                       │
+         │     Wrap      │                  │                    │                     │                        │                       │
+         │──────────────>│                  │                    │                     │                        │                       │
+         │               │                  │                    │                     │                        │                       │
+         │               │                  │       Create       │                     │                        │                       │
+         │               │                  │───────────────────>│                     │                        │                       │
+         │               │                  │                    │                     │                        │                       │
+         │               │        Create    │                    │                     │                        │                       │
+         │──────────────────────────────────────────────────────>│                     │                        │                       │
+         │               │                  │                    │                     │                        │                       │
+         │               │                  │                    │       Create        │                        │                       │
+         │               │                  │                    │<────────────────────│                        │                       │
+         │               │                  │                    │                     │                        │                       │
+         │               │                  │                    │                   onStart                    │                       │
+         │               │                  │                    │─────────────────────────────────────────────>│                       │
+         │               │                  │                    │                     │                        │                       │
+         │               │                  │                    │                     │      Wrap in Scope     │                       │
+         │               │                  │                    │─────────────────────────────────────────────────────────────────────>│
+┌────────┴────────┐┌─────┴─────┐┌───────────┴───────────┐┌───────┴───────┐┌────────────┴────────────┐┌──────────┴───────────┐┌──────────┴───────────┐
+│[1] SenderContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└─────────────────┘└───────────┘└───────────────────────┘└───────────────┘└─────────────────────────┘└──────────────────────┘└──────────────────────┘
+-----
+
+* In the <3> `ObservationRegistry` register a <6> handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+* Create a <1> `SenderContext` that wraps a <2> carrier (e.g. `AmqpMessage`)
+** In its constructor explain how to enrich the headers (e.g. `(key, value) -> amqpMessage.header(key, value)`)
+** Set the <2> carrier on the <1> `SenderContext`
+* Create an <4> `Observation`, optionally using the <5> `ObservationConvention` with the sender context
+** On <4> `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers) via an <6> `ObservationHandler`
+* Wrap the <7> code to instrument (e.g. sending of an AMQP message) in scope (e.g. through the `observe` or `scoped` method)
 
 [[instrumentation_of_messaging_communication_consumer]]
 === Instrumentation of Messaging Consumer Side Communication
 
-*Basic explanation of messaging consumer side instrumentation*
-
-// https://arthursonzogni.com/Diagon/#Sequence
-// ReceiverContext -> Carrier: Wrap
-// ObservationRegistry -> Observation: Create
-// ReceiverContext -> Observation: Create
-// ObservationConvention -> Observation: Create
-// Observation -> Code to Instrument: Wrap in Scope
-[source,subs=+attributes]
------
-┌───────────────┐┌───────┐┌───────────────────┐┌───────────┐┌─────────────────────┐┌──────────────────┐
-│ReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└───────┬───────┘└───┬───┘└─────────┬─────────┘└─────┬─────┘└──────────┬──────────┘└────────┬─────────┘
-        │            │              │                │                 │                    │
-        │    Wrap    │              │                │                 │                    │
-        │───────────>│              │                │                 │                    │
-        │            │              │                │                 │                    │
-        │            │              │     Create     │                 │                    │
-        │            │              │───────────────>│                 │                    │
-        │            │              │                │                 │                    │
-        │            │      Create  │                │                 │                    │
-        │───────────────────────────────────────────>│                 │                    │
-        │            │              │                │                 │                    │
-        │            │              │                │     Create      │                    │
-        │            │              │                │<────────────────│                    │
-        │            │              │                │                 │                    │
-        │            │              │                │            Wrap in Scope             │
-        │            │              │                │─────────────────────────────────────>│
-┌───────┴───────┐┌───┴───┐┌─────────┴─────────┐┌─────┴─────┐┌──────────┴──────────┐┌────────┴─────────┐
-│ReceiverContext││Carrier││ObservationRegistry││Observation││ObservationConvention││Code to Instrument│
-└───────────────┘└───────┘└───────────────────┘└───────────┘└─────────────────────┘└──────────────────┘
------
-
-. Create a `ReceiverContext` that wraps a carrier (e.g. `AmqpMessage`)
-.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
-.. Set the carrier on the `ReceiverContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, assuming that there is a proper registered handler through the `ObservationRegistry`, propagation will happen (e.g. tracing information will be retrieved from the headers)
-. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
-.. Some libraries (e.g. RabbitMQ) you might not have a handle on user's code, and you may require the user to allow starting a consumer side Observation and opening its scope by the framework (putting values in thread local) with the requirement of manually closing both the scope and stopping the Observation later by the user in their code!
-
-*More detailed explanation of messaging consumer side instrumentation*
+*Explanation of messaging consumer side instrumentation*
 
 // https://arthursonzogni.com/Diagon/#Sequence
-// ReceiverContext -> Carrier: Wrap
-// ObservationConvention -> Observation: Create
-// ReceiverContext -> Observation: Create
-// Observation -> ObservationHandler: Start
-// ObservationHandler -> Propagator: Extract Carrier
-// Propagator -> Carrier: Extract Carrier
-// Observation -> Code to Instrument: Wrap in Scope
+// [1] ReceiverContext -> [2] Carrier: Wrap
+// [3] ObservationRegistry -> [4] Observation: Create
+// [1] ReceiverContext -> [4] Observation: Create
+// [5] ObservationConvention -> [4] Observation: Create
+// [4] Observation -> [6] ObservationHandler: onStart
+// [4] Observation -> [7] Code to Instrument: Wrap in Scope
 [source,subs=+attributes]
 -----
-┌───────────────┐┌───────┐┌─────────────────────┐┌───────────┐┌──────────────────┐┌──────────┐┌──────────────────┐
-│ReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
-└───────┬───────┘└───┬───┘└──────────┬──────────┘└─────┬─────┘└────────┬─────────┘└────┬─────┘└────────┬─────────┘
-        │            │               │                 │               │               │               │
-        │    Wrap    │               │                 │               │               │               │
-        │───────────>│               │                 │               │               │               │
-        │            │               │                 │               │               │               │
-        │            │               │     Create      │               │               │               │
-        │            │               │────────────────>│               │               │               │
-        │            │               │                 │               │               │               │
-        │            │       Create  │                 │               │               │               │
-        │─────────────────────────────────────────────>│               │               │               │
-        │            │               │                 │               │               │               │
-        │            │               │                 │     Start     │               │               │
-        │            │               │                 │──────────────>│               │               │
-        │            │               │                 │               │               │               │
-        │            │               │                 │               │Extract Carrier│               │
-        │            │               │                 │               │──────────────>│               │
-        │            │               │                 │               │               │               │
-        │            │               │         Extract Carrier         │               │               │
-        │            │<────────────────────────────────────────────────────────────────│               │
-        │            │               │                 │               │               │               │
-        │            │               │                 │               │ Wrap in Scope │               │
-        │            │               │                 │──────────────────────────────────────────────>│
-┌───────┴───────┐┌───┴───┐┌──────────┴──────────┐┌─────┴─────┐┌────────┴─────────┐┌────┴─────┐┌────────┴─────────┐
-│ReceiverContext││Carrier││ObservationConvention││Observation││ObservationHandler││Propagator││Code to Instrument│
-└───────────────┘└───────┘└─────────────────────┘└───────────┘└──────────────────┘└──────────┘└──────────────────┘
------
-
-. In the `ObservationRegistry` register a handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
-. Create a `ReceiverContext` that wraps a carrier (e.g. `AmqpMessage`)
-.. In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
-.. Set the carrier on the `ReceiverContext`
-. Create an `Observation`, optionally using the `ObservationConvention` with the sender context
-.. On `Observation` start, propagation will happen (e.g. tracing information will be retrieved from the headers)
-. Wrap the code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
-.. Some libraries (e.g. RabbitMQ) you might not have a handle on user's code, and you may require the user to allow starting a consumer side Observation and opening its scope by the framework (putting values in thread local) with the requirement of manually closing both the scope and stopping the Observation later by the user in their code!
+┌───────────────────┐┌───────────┐┌───────────────────────┐┌───────────────┐┌─────────────────────────┐┌──────────────────────┐┌──────────────────────┐
+│[1] ReceiverContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└─────────┬─────────┘└─────┬─────┘└───────────┬───────────┘└───────┬───────┘└────────────┬────────────┘└──────────┬───────────┘└──────────┬───────────┘
+          │                │                  │                    │                     │                        │                       │
+          │      Wrap      │                  │                    │                     │                        │                       │
+          │───────────────>│                  │                    │                     │                        │                       │
+          │                │                  │                    │                     │                        │                       │
+          │                │                  │       Create       │                     │                        │                       │
+          │                │                  │───────────────────>│                     │                        │                       │
+          │                │                  │                    │                     │                        │                       │
+          │                │        Create    │                    │                     │                        │                       │
+          │───────────────────────────────────────────────────────>│                     │                        │                       │
+          │                │                  │                    │                     │                        │                       │
+          │                │                  │                    │       Create        │                        │                       │
+          │                │                  │                    │<────────────────────│                        │                       │
+          │                │                  │                    │                     │                        │                       │
+          │                │                  │                    │                   onStart                    │                       │
+          │                │                  │                    │─────────────────────────────────────────────>│                       │
+          │                │                  │                    │                     │                        │                       │
+          │                │                  │                    │                     │      Wrap in Scope     │                       │
+          │                │                  │                    │─────────────────────────────────────────────────────────────────────>│
+┌─────────┴─────────┐┌─────┴─────┐┌───────────┴───────────┐┌───────┴───────┐┌────────────┴────────────┐┌──────────┴───────────┐┌──────────┴───────────┐
+│[1] ReceiverContext││[2] Carrier││[3] ObservationRegistry││[4] Observation││[5] ObservationConvention││[6] ObservationHandler││[7] Code to Instrument│
+└───────────────────┘└───────────┘└───────────────────────┘└───────────────┘└─────────────────────────┘└──────────────────────┘└──────────────────────┘
+-----
+
+* In the <3> `ObservationRegistry` register a <6> handler that will propagate context (e.g. `PropagatingReceiverTracingObservationHandler` from Micrometer Tracing)
+* Create a <1> `ReceiverContext` that wraps a <2> carrier (e.g. `AmqpMessage`)
+** In its constructor explain how to retrieve the header values (e.g. `(carrier, key) -> carrier.header(key)`)
+** Set the <2> carrier on the <1> `ReceiverContext`
+* Create an <4> `Observation`, optionally using the <6> `ObservationConvention` with the sender context
+** On <4> `Observation` start, propagation will happen (e.g. carrier will be enriched with proper headers) via an <6> `ObservationHandler`
+* Wrap the <7> code to instrument (e.g. processing of an HTTP request) in scope (e.g. through the `observe` or `scoped` method)
+** Some libraries (e.g. RabbitMQ) you might not have a handle on user's code, and you may require the user to allow starting a consumer side Observation and opening its scope by the framework (putting values in thread local) with the requirement of manually closing both the scope and stopping the Observation later by the user in their code!
 
 [[instrumentation_of_messaging_communication_example]]
 === Instrumentation of Messaging Communication Example

From e4b625fb26a79b561e1e0f502bec2ee3d464f230 Mon Sep 17 00:00:00 2001
From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com>
Date: Thu, 8 Feb 2024 17:11:53 +0900
Subject: [PATCH 62/73] Support jOOQ 3.15 and beyond (#4727)

Implementing jOOQ's `DSLContext` interface was causing revlock and subsequently frequent breaking. Now that jOOQ OSS supported versions no longer work with Java 8, we cannot compile against them to update our implementation `MetricsDSLContext`. This switches to extending `DefaultDSLContext` instead which eliminates a lot of boilerplate implementation and should be more compatible. A sample has been added that runs the tests against the latest version of jOOQ to ensure MetricsDSLContext works with it while compiling against the newest OSS version of jOOQ that supports Java 8.
---
 build.gradle                                  |    2 +
 dependencies.gradle                           |    1 -
 gradle/libs.versions.toml                     |    8 +-
 micrometer-core/build.gradle                  |    2 +-
 .../binder/db/MetricsDSLContext.java          | 5176 ++---------------
 samples/micrometer-samples-jooq/build.gradle  |   30 +
 .../samples/jooq/MetricsDSLContextTest.java   |  209 +
 settings.gradle                               |    2 +-
 8 files changed, 680 insertions(+), 4750 deletions(-)
 create mode 100644 samples/micrometer-samples-jooq/build.gradle
 create mode 100644 samples/micrometer-samples-jooq/src/test/java/io/micrometer/samples/jooq/MetricsDSLContextTest.java

diff --git a/build.gradle b/build.gradle
index 6033615f71..a1ad76f66e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -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']
diff --git a/dependencies.gradle b/dependencies.gradle
index d1d1a1df8f..26f723eeb4 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -65,7 +65,6 @@ def VERSIONS = [
         libs.hdrhistogram,
         libs.hibernateEntitymanager,
         libs.hsqldb,
-        libs.jooq,
         libs.jsr107,
         libs.junitJupiter,
         libs.junitPlatformLauncher,
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a4acb2a11a..1da912fae6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -47,7 +47,10 @@ jetty12 = "12.0.3"
 jersey2 = "2.41"
 jersey3 = "3.0.11"
 jmh = "1.37"
-jooq = "3.14.16"
+# newest version of OSS jOOQ that supports Java 8
+jooqOld = "3.14.16"
+# latest version of jOOQ to run tests against
+jooqNew = "3.19.3"
 jsr107 = "1.1.1"
 jsr305 = "3.0.2"
 junit = "5.10.1"
@@ -153,7 +156,8 @@ jersey3Hk2 = { module = "org.glassfish.jersey.inject:jersey-hk2", version.ref =
 jersey3TestFrameworkJdkHttp = { module = "org.glassfish.jersey.test-framework.providers:jersey-test-framework-provider-jdk-http", version.ref = "jersey3" }
 jmhCore = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" }
 jmhAnnotationProcessor = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" }
-jooq = { module = "org.jooq:jooq", version.ref = "jooq" }
+jooq = { module = "org.jooq:jooq", version.ref = "jooqOld" }
+jooqLatest = { module = "org.jooq:jooq", version.ref = "jooqNew" }
 jsonPath = { module = "com.jayway.jsonpath:json-path", version = "2.9.0" }
 jsr107 = { module = "org.jsr107.ri:cache-ri-impl", version.ref = "jsr107" }
 jsr305 = { module = "com.google.code.findbugs:jsr305", version.ref = "jsr305" }
diff --git a/micrometer-core/build.gradle b/micrometer-core/build.gradle
index f0a5d471ae..dc72ef1936 100644
--- a/micrometer-core/build.gradle
+++ b/micrometer-core/build.gradle
@@ -120,7 +120,7 @@ dependencies {
 
     optionalApi 'org.mongodb:mongodb-driver-sync'
 
-    optionalApi 'org.jooq:jooq'
+    optionalApi libs.jooq
 
     optionalApi 'org.apache.kafka:kafka-clients'
     optionalApi 'org.apache.kafka:kafka-streams'
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/db/MetricsDSLContext.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/db/MetricsDSLContext.java
index 18c9ab69a1..f73b4b1ca3 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/db/MetricsDSLContext.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/db/MetricsDSLContext.java
@@ -21,26 +21,10 @@
 import io.micrometer.core.instrument.Tags;
 import org.jooq.Record;
 import org.jooq.*;
-import org.jooq.conf.Settings;
-import org.jooq.exception.*;
-import org.jooq.impl.DSL;
-import org.jooq.tools.jdbc.MockCallable;
-import org.jooq.tools.jdbc.MockDataProvider;
-import org.jooq.tools.jdbc.MockRunnable;
-import org.jooq.util.xml.jaxb.InformationSchema;
+import org.jooq.impl.DefaultDSLContext;
 
-import javax.sql.DataSource;
-import java.math.BigInteger;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.*;
-import java.util.concurrent.CompletionStage;
-import java.util.concurrent.Executor;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-import java.util.stream.Stream;
+import java.util.Arrays;
+import java.util.Collection;
 
 /**
  * Time SQL queries passing through jOOQ.
@@ -61,35 +45,31 @@
  * @since 1.4.0
  */
 @Incubating(since = "1.4.0")
-public class MetricsDSLContext implements DSLContext {
-
-    private final DSLContext context;
+public class MetricsDSLContext extends DefaultDSLContext {
 
     private final MeterRegistry registry;
 
     private final Iterable tags;
 
-    private final ThreadLocal> contextTags = new ThreadLocal<>();
+    private static final ThreadLocal> contextTags = new ThreadLocal<>();
 
-    private final ExecuteListenerProvider defaultExecuteListenerProvider;
+    private static ExecuteListenerProvider defaultExecuteListenerProvider;
 
     public static MetricsDSLContext withMetrics(DSLContext jooq, MeterRegistry registry, Iterable tags) {
-        return new MetricsDSLContext(jooq, registry, tags);
-    }
-
-    MetricsDSLContext(DSLContext context, MeterRegistry registry, Iterable tags) {
-        this.registry = registry;
-        this.tags = tags;
-
-        this.defaultExecuteListenerProvider = () -> new JooqExecuteListener(registry, tags, () -> {
+        defaultExecuteListenerProvider = () -> new JooqExecuteListener(registry, tags, () -> {
             Iterable queryTags = contextTags.get();
             contextTags.remove();
             return queryTags;
         });
-        Configuration configuration = context.configuration().derive();
-        Configuration derivedConfiguration = derive(configuration, this.defaultExecuteListenerProvider);
+        Configuration configuration = jooq.configuration().derive();
+        Configuration derivedConfiguration = derive(configuration, defaultExecuteListenerProvider);
+        return new MetricsDSLContext(derivedConfiguration, registry, tags);
+    }
 
-        this.context = DSL.using(derivedConfiguration);
+    MetricsDSLContext(Configuration configuration, MeterRegistry registry, Iterable tags) {
+        super(configuration);
+        this.registry = registry;
+        this.tags = tags;
     }
 
     public  Q time(Q q) {
@@ -103,10 +83,10 @@ public Configuration time(Configuration c) {
         return derive(c, () -> new JooqExecuteListener(registry, tags, () -> queryTags));
     }
 
-    private Configuration derive(Configuration configuration, ExecuteListenerProvider executeListenerProvider) {
+    private static Configuration derive(Configuration configuration, ExecuteListenerProvider executeListenerProvider) {
         ExecuteListenerProvider[] providers = configuration.executeListenerProviders();
         for (int i = 0; i < providers.length; i++) {
-            if (providers[i] == this.defaultExecuteListenerProvider) {
+            if (providers[i] == defaultExecuteListenerProvider) {
                 ExecuteListenerProvider[] newProviders = Arrays.copyOf(providers, providers.length);
                 newProviders[i] = executeListenerProvider;
                 return configuration.derive(newProviders);
@@ -136,4972 +116,678 @@ public DSLContext tags(Iterable tags) {
     }
 
     @Override
-    public Schema map(Schema schema) {
-        return context.map(schema);
+    public  SelectWhereStep selectFrom(Table table) {
+        return time(super.selectFrom(table));
     }
 
     @Override
-    public  Table map(Table table) {
-        return context.map(table);
+    public SelectWhereStep selectFrom(Name table) {
+        return time(super.selectFrom(table));
     }
 
     @Override
-    public Parser parser() {
-        return context.parser();
+    public SelectWhereStep selectFrom(SQL sql) {
+        return time(super.selectFrom(sql));
     }
 
     @Override
-    public Connection parsingConnection() {
-        return context.parsingConnection();
+    public SelectWhereStep selectFrom(String sql) {
+        return time(super.selectFrom(sql));
     }
 
     @Override
-    public DataSource parsingDataSource() {
-        return context.parsingDataSource();
+    public SelectWhereStep selectFrom(String sql, Object... bindings) {
+        return time(super.selectFrom(sql, bindings));
     }
 
     @Override
-    public Connection diagnosticsConnection() {
-        return context.diagnosticsConnection();
+    public SelectWhereStep selectFrom(String sql, QueryPart... parts) {
+        return time(super.selectFrom(sql, parts));
     }
 
     @Override
-    public DataSource diagnosticsDataSource() {
-        return context.diagnosticsDataSource();
+    public SelectSelectStep select(Collection fields) {
+        return time(super.select(fields));
     }
 
     @Override
-    public Version version(String id) {
-        return context.version(id);
+    public SelectSelectStep select(SelectFieldOrAsterisk... fields) {
+        return time(super.select(fields));
     }
 
     @Override
-    public Migration migrateTo(Version to) {
-        return context.migrateTo(to);
+    public  SelectSelectStep> select(SelectField field1) {
+        return time(super.select(field1));
     }
 
     @Override
-    public Meta meta() {
-        return context.meta();
+    public  SelectSelectStep> select(SelectField field1, SelectField field2) {
+        return time(super.select(field1, field2));
     }
 
     @Override
-    public Meta meta(DatabaseMetaData meta) {
-        return context.meta(meta);
+    public  SelectSelectStep> select(SelectField field1, SelectField field2,
+            SelectField field3) {
+        return time(super.select(field1, field2, field3));
     }
 
     @Override
-    public Meta meta(Catalog... catalogs) {
-        return context.meta(catalogs);
+    public  SelectSelectStep> select(SelectField field1,
+            SelectField field2, SelectField field3, SelectField field4) {
+        return time(super.select(field1, field2, field3, field4));
     }
 
     @Override
-    public Meta meta(Schema... schemas) {
-        return context.meta(schemas);
+    public  SelectSelectStep> select(SelectField field1,
+            SelectField field2, SelectField field3, SelectField field4, SelectField field5) {
+        return time(super.select(field1, field2, field3, field4, field5));
     }
 
     @Override
-    public Meta meta(Table... tables) {
-        return context.meta(tables);
+    public  SelectSelectStep> select(SelectField field1,
+            SelectField field2, SelectField field3, SelectField field4, SelectField field5,
+            SelectField field6) {
+        return time(super.select(field1, field2, field3, field4, field5, field6));
     }
 
     @Override
-    public Meta meta(InformationSchema schema) {
-        return context.meta(schema);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7));
     }
 
     @Override
-    public Meta meta(String... sources) {
-        return context.meta(sources);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8));
     }
 
     @Override
-    @Internal
-    public Meta meta(Source... scripts) {
-        return context.meta(scripts);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9));
     }
 
     @Override
-    public Meta meta(Query... queries) {
-        return context.meta(queries);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10));
     }
 
     @Override
-    public InformationSchema informationSchema(Catalog catalog) {
-        return context.informationSchema(catalog);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11) {
+        return time(
+                super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10, field11));
     }
 
     @Override
-    public InformationSchema informationSchema(Catalog... catalogs) {
-        return context.informationSchema(catalogs);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12));
     }
 
     @Override
-    public InformationSchema informationSchema(Schema schema) {
-        return context.informationSchema(schema);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13));
     }
 
     @Override
-    public InformationSchema informationSchema(Schema... schemas) {
-        return context.informationSchema(schemas);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14));
     }
 
     @Override
-    public InformationSchema informationSchema(Table table) {
-        return context.informationSchema(table);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15));
     }
 
     @Override
-    public InformationSchema informationSchema(Table... table) {
-        return context.informationSchema(table);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16));
     }
 
     @Override
-    public Explain explain(Query query) {
-        return context.explain(query);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17));
     }
 
     @Override
-    public  T transactionResult(TransactionalCallable transactional) {
-        return context.transactionResult(transactional);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17, field18));
     }
 
     @Override
-    public  T transactionResult(ContextTransactionalCallable transactional) throws ConfigurationException {
-        return context.transactionResult(transactional);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17, field18, field19));
     }
 
     @Override
-    public void transaction(TransactionalRunnable transactional) {
-        context.transaction(transactional);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
     }
 
     @Override
-    public void transaction(ContextTransactionalRunnable transactional) throws ConfigurationException {
-        context.transaction(transactional);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
+            SelectField field21) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21));
     }
 
     @Override
-    public  CompletionStage transactionResultAsync(TransactionalCallable transactional)
-            throws ConfigurationException {
-        return context.transactionResultAsync(transactional);
+    public  SelectSelectStep> select(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
+            SelectField field21, SelectField field22) {
+        return time(super.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
+                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
+                field22));
     }
 
     @Override
-    public CompletionStage transactionAsync(TransactionalRunnable transactional) throws ConfigurationException {
-        return context.transactionAsync(transactional);
+    public SelectSelectStep selectDistinct(Collection fields) {
+        return time(super.selectDistinct(fields));
     }
 
     @Override
-    public  CompletionStage transactionResultAsync(Executor executor, TransactionalCallable transactional)
-            throws ConfigurationException {
-        return context.transactionResultAsync(executor, transactional);
+    public SelectSelectStep selectDistinct(SelectFieldOrAsterisk... fields) {
+        return time(super.selectDistinct(fields));
     }
 
     @Override
-    public CompletionStage transactionAsync(Executor executor, TransactionalRunnable transactional)
-            throws ConfigurationException {
-        return context.transactionAsync(executor, transactional);
+    public  SelectSelectStep> selectDistinct(SelectField field1) {
+        return time(super.selectDistinct(field1));
     }
 
     @Override
-    public  T connectionResult(ConnectionCallable callable) {
-        return context.connectionResult(callable);
+    public  SelectSelectStep> selectDistinct(SelectField field1, SelectField field2) {
+        return time(super.selectDistinct(field1, field2));
     }
 
     @Override
-    public void connection(ConnectionRunnable runnable) {
-        context.connection(runnable);
+    public  SelectSelectStep> selectDistinct(SelectField field1,
+            SelectField field2, SelectField field3) {
+        return time(super.selectDistinct(field1, field2, field3));
     }
 
     @Override
-    public  T mockResult(MockDataProvider provider, MockCallable mockable) {
-        return context.mockResult(provider, mockable);
+    public  SelectSelectStep> selectDistinct(SelectField field1,
+            SelectField field2, SelectField field3, SelectField field4) {
+        return time(super.selectDistinct(field1, field2, field3, field4));
     }
 
     @Override
-    public void mock(MockDataProvider provider, MockRunnable mockable) {
-        context.mock(provider, mockable);
+    public  SelectSelectStep> selectDistinct(SelectField field1,
+            SelectField field2, SelectField field3, SelectField field4, SelectField field5) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5));
     }
 
     @Override
-    @Internal
-    @Deprecated
-    public RenderContext renderContext() {
-        return context.renderContext();
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6));
     }
 
     @Override
-    public String render(QueryPart part) {
-        return context.render(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7));
     }
 
     @Override
-    public String renderNamedParams(QueryPart part) {
-        return context.renderNamedParams(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8));
     }
 
     @Override
-    public String renderNamedOrInlinedParams(QueryPart part) {
-        return context.renderNamedOrInlinedParams(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9));
     }
 
     @Override
-    public String renderInlined(QueryPart part) {
-        return context.renderInlined(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10) {
+        return time(
+                super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10));
     }
 
     @Override
-    public List extractBindValues(QueryPart part) {
-        return context.extractBindValues(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11));
     }
 
     @Override
-    public Map> extractParams(QueryPart part) {
-        return context.extractParams(part);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12));
     }
 
     @Override
-    public Param extractParam(QueryPart part, String name) {
-        return context.extractParam(part, name);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13));
     }
 
     @Override
-    @Internal
-    @Deprecated
-    public BindContext bindContext(PreparedStatement stmt) {
-        return context.bindContext(stmt);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14));
     }
 
     @Override
-    @Deprecated
-    public int bind(QueryPart part, PreparedStatement stmt) {
-        return context.bind(part, stmt);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15));
     }
 
     @Override
-    public void attach(Attachable... attachables) {
-        context.attach(attachables);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16));
     }
 
     @Override
-    public void attach(Collection attachables) {
-        context.attach(attachables);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17));
     }
 
     @Override
-    public  LoaderOptionsStep loadInto(Table table) {
-        return context.loadInto(table);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18));
     }
 
     @Override
-    public Queries queries(Query... queries) {
-        return context.queries(queries);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19));
     }
 
     @Override
-    public Queries queries(Collection queries) {
-        return context.queries(queries);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
     }
 
     @Override
-    public Block begin(Statement... statements) {
-        return context.begin(statements);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
+            SelectField field21) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
+                field21));
     }
 
     @Override
-    public Block begin(Collection statements) {
-        return context.begin(statements);
+    public  SelectSelectStep> selectDistinct(
+            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
+            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
+            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
+            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
+            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
+            SelectField field21, SelectField field22) {
+        return time(super.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
+                field21, field22));
     }
 
     @Override
-    public RowCountQuery query(SQL sql) {
-        return context.query(sql);
+    public SelectSelectStep> selectZero() {
+        return time(super.selectZero());
     }
 
     @Override
-    public RowCountQuery query(String sql) {
-        return context.query(sql);
+    public SelectSelectStep> selectOne() {
+        return time(super.selectOne());
     }
 
     @Override
-    public RowCountQuery query(String sql, Object... bindings) {
-        return context.query(sql, bindings);
+    public SelectSelectStep> selectCount() {
+        return time(super.selectCount());
     }
 
     @Override
-    public RowCountQuery query(String sql, QueryPart... parts) {
-        return context.query(sql, parts);
+    public SelectQuery selectQuery() {
+        return time(super.selectQuery());
     }
 
     @Override
-    public Result fetch(SQL sql) throws DataAccessException {
-        return context.fetch(sql);
+    public  SelectQuery selectQuery(TableLike table) {
+        return time(super.selectQuery(table));
     }
 
     @Override
-    public Result fetch(String sql) throws DataAccessException {
-        return context.fetch(sql);
+    public  InsertQuery insertQuery(Table into) {
+        return time(super.insertQuery(into));
     }
 
     @Override
-    public Result fetch(String sql, Object... bindings) throws DataAccessException {
-        return context.fetch(sql, bindings);
+    public  InsertSetStep insertInto(Table into) {
+        return timeCoercable(super.insertInto(into));
     }
 
     @Override
-    public Result fetch(String sql, QueryPart... parts) throws DataAccessException {
-        return context.fetch(sql, parts);
+    public  InsertValuesStep1 insertInto(Table into, Field field1) {
+        return time(super.insertInto(into, field1));
     }
 
     @Override
-    public Cursor fetchLazy(SQL sql) throws DataAccessException {
-        return context.fetchLazy(sql);
+    public  InsertValuesStep2 insertInto(Table into, Field field1,
+            Field field2) {
+        return time(super.insertInto(into, field1, field2));
     }
 
     @Override
-    public Cursor fetchLazy(String sql) throws DataAccessException {
-        return context.fetchLazy(sql);
+    public  InsertValuesStep3 insertInto(Table into, Field field1,
+            Field field2, Field field3) {
+        return time(super.insertInto(into, field1, field2, field3));
     }
 
     @Override
-    public Cursor fetchLazy(String sql, Object... bindings) throws DataAccessException {
-        return context.fetchLazy(sql, bindings);
+    public  InsertValuesStep4 insertInto(Table into,
+            Field field1, Field field2, Field field3, Field field4) {
+        return time(super.insertInto(into, field1, field2, field3, field4));
     }
 
     @Override
-    public Cursor fetchLazy(String sql, QueryPart... parts) throws DataAccessException {
-        return context.fetchLazy(sql, parts);
+    public  InsertValuesStep5 insertInto(Table into,
+            Field field1, Field field2, Field field3, Field field4, Field field5) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5));
     }
 
     @Override
-    public CompletionStage> fetchAsync(SQL sql) {
-        return context.fetchAsync(sql);
+    public  InsertValuesStep6 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6));
     }
 
     @Override
-    public CompletionStage> fetchAsync(String sql) {
-        return context.fetchAsync(sql);
+    public  InsertValuesStep7 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7));
     }
 
     @Override
-    public CompletionStage> fetchAsync(String sql, Object... bindings) {
-        return context.fetchAsync(sql, bindings);
+    public  InsertValuesStep8 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8));
     }
 
     @Override
-    public CompletionStage> fetchAsync(String sql, QueryPart... parts) {
-        return context.fetchAsync(sql, parts);
+    public  InsertValuesStep9 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9));
     }
 
     @Override
-    public CompletionStage> fetchAsync(Executor executor, SQL sql) {
-        return context.fetchAsync(executor, sql);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, String sql) {
-        return context.fetchAsync(executor, sql);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, String sql, Object... bindings) {
-        return context.fetchAsync(executor, sql, bindings);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, String sql, QueryPart... parts) {
-        return context.fetchAsync(executor, sql, parts);
-    }
-
-    @Override
-    public Stream fetchStream(SQL sql) throws DataAccessException {
-        return context.fetchStream(sql);
-    }
-
-    @Override
-    public Stream fetchStream(String sql) throws DataAccessException {
-        return context.fetchStream(sql);
-    }
-
-    @Override
-    public Stream fetchStream(String sql, Object... bindings) throws DataAccessException {
-        return context.fetchStream(sql, bindings);
-    }
-
-    @Override
-    public Stream fetchStream(String sql, QueryPart... parts) throws DataAccessException {
-        return context.fetchStream(sql, parts);
-    }
-
-    @Override
-    public Results fetchMany(SQL sql) throws DataAccessException {
-        return context.fetchMany(sql);
-    }
-
-    @Override
-    public Results fetchMany(String sql) throws DataAccessException {
-        return context.fetchMany(sql);
-    }
-
-    @Override
-    public Results fetchMany(String sql, Object... bindings) throws DataAccessException {
-        return context.fetchMany(sql, bindings);
-    }
-
-    @Override
-    public Results fetchMany(String sql, QueryPart... parts) throws DataAccessException {
-        return context.fetchMany(sql, parts);
-    }
-
-    @Override
-    public Record fetchOne(SQL sql) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(sql);
-    }
-
-    @Override
-    public Record fetchOne(String sql) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(sql);
-    }
-
-    @Override
-    public Record fetchOne(String sql, Object... bindings) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(sql, bindings);
-    }
-
-    @Override
-    public Record fetchOne(String sql, QueryPart... parts) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(sql, parts);
-    }
-
-    @Override
-    public Record fetchSingle(SQL sql) throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(sql);
-    }
-
-    @Override
-    public Record fetchSingle(String sql) throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(sql);
-    }
-
-    @Override
-    public Record fetchSingle(String sql, Object... bindings)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(sql, bindings);
-    }
-
-    @Override
-    public Record fetchSingle(String sql, QueryPart... parts)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(sql, parts);
-    }
-
-    @Override
-    public Optional fetchOptional(SQL sql) throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(sql);
-    }
-
-    @Override
-    public Optional fetchOptional(String sql) throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(sql);
-    }
-
-    @Override
-    public Optional fetchOptional(String sql, Object... bindings)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(sql, bindings);
-    }
-
-    @Override
-    public Optional fetchOptional(String sql, QueryPart... parts)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(sql, parts);
-    }
-
-    @Override
-    public Object fetchValue(SQL sql) throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(sql);
-    }
-
-    @Override
-    public Object fetchValue(String sql) throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(sql);
-    }
-
-    @Override
-    public Object fetchValue(String sql, Object... bindings)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(sql, bindings);
-    }
-
-    @Override
-    public Object fetchValue(String sql, QueryPart... parts)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(sql, parts);
-    }
-
-    @Override
-    public Optional fetchOptionalValue(SQL sql)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(sql);
-    }
-
-    @Override
-    public Optional fetchOptionalValue(String sql)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(sql);
-    }
-
-    @Override
-    public Optional fetchOptionalValue(String sql, Object... bindings)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(sql, bindings);
-    }
-
-    @Override
-    public Optional fetchOptionalValue(String sql, QueryPart... parts)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(sql, parts);
-    }
-
-    @Override
-    public List fetchValues(SQL sql) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(sql);
-    }
-
-    @Override
-    public List fetchValues(String sql) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(sql);
-    }
-
-    @Override
-    public List fetchValues(String sql, Object... bindings) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(sql, bindings);
-    }
-
-    @Override
-    public List fetchValues(String sql, QueryPart... parts) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(sql, parts);
-    }
-
-    @Override
-    public int execute(SQL sql) throws DataAccessException {
-        return context.execute(sql);
-    }
-
-    @Override
-    public int execute(String sql) throws DataAccessException {
-        return context.execute(sql);
-    }
-
-    @Override
-    public int execute(String sql, Object... bindings) throws DataAccessException {
-        return context.execute(sql, bindings);
-    }
-
-    @Override
-    public int execute(String sql, QueryPart... parts) throws DataAccessException {
-        return context.execute(sql, parts);
-    }
-
-    @Override
-    public ResultQuery resultQuery(SQL sql) {
-        return context.resultQuery(sql);
-    }
-
-    @Override
-    public ResultQuery resultQuery(String sql) {
-        return context.resultQuery(sql);
-    }
-
-    @Override
-    public ResultQuery resultQuery(String sql, Object... bindings) {
-        return context.resultQuery(sql, bindings);
-    }
-
-    @Override
-    public ResultQuery resultQuery(String sql, QueryPart... parts) {
-        return context.resultQuery(sql, parts);
-    }
-
-    @Override
-    public Result fetch(ResultSet rs) throws DataAccessException {
-        return context.fetch(rs);
-    }
-
-    @Override
-    public Result fetch(ResultSet rs, Field... fields) throws DataAccessException {
-        return context.fetch(rs, fields);
-    }
-
-    @Override
-    public Result fetch(ResultSet rs, DataType... types) throws DataAccessException {
-        return context.fetch(rs, types);
-    }
-
-    @Override
-    public Result fetch(ResultSet rs, Class... types) throws DataAccessException {
-        return context.fetch(rs, types);
-    }
-
-    @Override
-    public Record fetchOne(ResultSet rs) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(rs);
-    }
-
-    @Override
-    public Record fetchOne(ResultSet rs, Field... fields) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(rs, fields);
-    }
-
-    @Override
-    public Record fetchOne(ResultSet rs, DataType... types) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(rs, types);
-    }
-
-    @Override
-    public Record fetchOne(ResultSet rs, Class... types) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(rs, types);
-    }
-
-    @Override
-    public Record fetchSingle(ResultSet rs) throws DataAccessException, TooManyRowsException {
-        return context.fetchSingle(rs);
-    }
-
-    @Override
-    public Record fetchSingle(ResultSet rs, Field... fields)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(rs, fields);
-    }
-
-    @Override
-    public Record fetchSingle(ResultSet rs, DataType... types)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(rs, types);
-    }
-
-    @Override
-    public Record fetchSingle(ResultSet rs, Class... types)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(rs, types);
-    }
-
-    @Override
-    public Optional fetchOptional(ResultSet rs)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchOptional(rs);
-    }
-
-    @Override
-    public Optional fetchOptional(ResultSet rs, Field... fields)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(rs, fields);
-    }
-
-    @Override
-    public Optional fetchOptional(ResultSet rs, DataType... types)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(rs, types);
-    }
-
-    @Override
-    public Optional fetchOptional(ResultSet rs, Class... types)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(rs, types);
-    }
-
-    @Override
-    public Object fetchValue(ResultSet rs) throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(rs);
-    }
-
-    @Override
-    public  T fetchValue(ResultSet rs, Field field)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(rs, field);
-    }
-
-    @Override
-    public  T fetchValue(ResultSet rs, DataType type)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(rs, type);
-    }
-
-    @Override
-    public  T fetchValue(ResultSet rs, Class type)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchValue(rs, type);
-    }
-
-    @Override
-    public Optional fetchOptionalValue(ResultSet rs)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(rs);
-    }
-
-    @Override
-    public  Optional fetchOptionalValue(ResultSet rs, Field field)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(rs, field);
-    }
-
-    @Override
-    public  Optional fetchOptionalValue(ResultSet rs, DataType type)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(rs, type);
-    }
-
-    @Override
-    public  Optional fetchOptionalValue(ResultSet rs, Class type)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(rs, type);
-    }
-
-    @Override
-    public List fetchValues(ResultSet rs) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(rs);
-    }
-
-    @Override
-    public  List fetchValues(ResultSet rs, Field field) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(rs, field);
-    }
-
-    @Override
-    public  List fetchValues(ResultSet rs, DataType type) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(rs, type);
-    }
-
-    @Override
-    public  List fetchValues(ResultSet rs, Class type) throws DataAccessException, InvalidResultException {
-        return context.fetchValues(rs, type);
-    }
-
-    @Override
-    public Cursor fetchLazy(ResultSet rs) throws DataAccessException {
-        return context.fetchLazy(rs);
-    }
-
-    @Override
-    public Cursor fetchLazy(ResultSet rs, Field... fields) throws DataAccessException {
-        return context.fetchLazy(rs, fields);
-    }
-
-    @Override
-    public Cursor fetchLazy(ResultSet rs, DataType... types) throws DataAccessException {
-        return context.fetchLazy(rs, types);
-    }
-
-    @Override
-    public Cursor fetchLazy(ResultSet rs, Class... types) throws DataAccessException {
-        return context.fetchLazy(rs, types);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(ResultSet rs) {
-        return context.fetchAsync(rs);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(ResultSet rs, Field... fields) {
-        return context.fetchAsync(rs, fields);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(ResultSet rs, DataType... types) {
-        return context.fetchAsync(rs, types);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(ResultSet rs, Class... types) {
-        return context.fetchAsync(rs, types);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, ResultSet rs) {
-        return context.fetchAsync(executor, rs);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, ResultSet rs, Field... fields) {
-        return context.fetchAsync(executor, rs, fields);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, ResultSet rs, DataType... types) {
-        return context.fetchAsync(executor, rs, types);
-    }
-
-    @Override
-    public CompletionStage> fetchAsync(Executor executor, ResultSet rs, Class... types) {
-        return context.fetchAsync(executor, rs, types);
-    }
-
-    @Override
-    public Stream fetchStream(ResultSet rs) throws DataAccessException {
-        return context.fetchStream(rs);
-    }
-
-    @Override
-    public Stream fetchStream(ResultSet rs, Field... fields) throws DataAccessException {
-        return context.fetchStream(rs, fields);
-    }
-
-    @Override
-    public Stream fetchStream(ResultSet rs, DataType... types) throws DataAccessException {
-        return context.fetchStream(rs, types);
-    }
-
-    @Override
-    public Stream fetchStream(ResultSet rs, Class... types) throws DataAccessException {
-        return context.fetchStream(rs, types);
-    }
-
-    @Override
-    public Result fetchFromTXT(String string) throws DataAccessException {
-        return context.fetchFromTXT(string);
-    }
-
-    @Override
-    public Result fetchFromTXT(String string, String nullLiteral) throws DataAccessException {
-        return context.fetchFromTXT(string, nullLiteral);
-    }
-
-    @Override
-    public Result fetchFromHTML(String string) throws DataAccessException {
-        return context.fetchFromHTML(string);
-    }
-
-    @Override
-    public Result fetchFromCSV(String string) throws DataAccessException {
-        return context.fetchFromCSV(string);
-    }
-
-    @Override
-    public Result fetchFromCSV(String string, char delimiter) throws DataAccessException {
-        return context.fetchFromCSV(string, delimiter);
-    }
-
-    @Override
-    public Result fetchFromCSV(String string, boolean header) throws DataAccessException {
-        return context.fetchFromCSV(string, header);
-    }
-
-    @Override
-    public Result fetchFromCSV(String string, boolean header, char delimiter) throws DataAccessException {
-        return context.fetchFromCSV(string, header, delimiter);
-    }
-
-    @Override
-    public Result fetchFromJSON(String string) {
-        return context.fetchFromJSON(string);
-    }
-
-    @Override
-    public Result fetchFromXML(String string) {
-        return context.fetchFromXML(string);
-    }
-
-    @Override
-    public Result fetchFromStringData(String[]... data) {
-        return context.fetchFromStringData(data);
-    }
-
-    @Override
-    public Result fetchFromStringData(List data) {
-        return context.fetchFromStringData(data);
-    }
-
-    @Override
-    public Result fetchFromStringData(List data, boolean header) {
-        return context.fetchFromStringData(data, header);
-    }
-
-    @Override
-    public WithAsStep with(String alias) {
-        return context.with(alias);
-    }
-
-    @Override
-    public WithAsStep with(String alias, String... fieldAliases) {
-        return context.with(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep with(String alias, Collection fieldAliases) {
-        return context.with(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep with(Name alias) {
-        return context.with(alias);
-    }
-
-    @Override
-    public WithAsStep with(Name alias, Name... fieldAliases) {
-        return context.with(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep with(Name alias, Collection fieldAliases) {
-        return context.with(alias, fieldAliases);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public WithAsStep with(String alias, Function, ? extends String> fieldNameFunction) {
-        return context.with(alias, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public WithAsStep with(String alias,
-            BiFunction, ? super Integer, ? extends String> fieldNameFunction) {
-        return context.with(alias, fieldNameFunction);
-    }
-
-    @Override
-    public WithAsStep1 with(String alias, String fieldAlias1) {
-        return context.with(alias, fieldAlias1);
-    }
-
-    @Override
-    public WithAsStep2 with(String alias, String fieldAlias1, String fieldAlias2) {
-        return context.with(alias, fieldAlias1, fieldAlias2);
-    }
-
-    @Override
-    public WithAsStep3 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3);
-    }
-
-    @Override
-    public WithAsStep4 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4);
-    }
-
-    @Override
-    public WithAsStep5 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5);
-    }
-
-    @Override
-    public WithAsStep6 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6);
-    }
-
-    @Override
-    public WithAsStep7 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7);
-    }
-
-    @Override
-    public WithAsStep8 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8);
-    }
-
-    @Override
-    public WithAsStep9 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9);
-    }
-
-    @Override
-    public WithAsStep10 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10);
-    }
-
-    @Override
-    public WithAsStep11 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11);
-    }
-
-    @Override
-    public WithAsStep12 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12);
-    }
-
-    @Override
-    public WithAsStep13 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13);
-    }
-
-    @Override
-    public WithAsStep14 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14);
-    }
-
-    @Override
-    public WithAsStep15 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15);
-    }
-
-    @Override
-    public WithAsStep16 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16);
-    }
-
-    @Override
-    public WithAsStep17 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17);
-    }
-
-    @Override
-    public WithAsStep18 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18);
-    }
-
-    @Override
-    public WithAsStep19 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19);
-    }
-
-    @Override
-    public WithAsStep20 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20);
-    }
-
-    @Override
-    public WithAsStep21 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20, String fieldAlias21) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20,
-                fieldAlias21);
-    }
-
-    @Override
-    public WithAsStep22 with(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20, String fieldAlias21, String fieldAlias22) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20,
-                fieldAlias21, fieldAlias22);
-    }
-
-    @Override
-    public WithAsStep1 with(Name alias, Name fieldAlias1) {
-        return context.with(alias, fieldAlias1);
-    }
-
-    @Override
-    public WithAsStep2 with(Name alias, Name fieldAlias1, Name fieldAlias2) {
-        return context.with(alias, fieldAlias1, fieldAlias2);
-    }
-
-    @Override
-    public WithAsStep3 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3);
-    }
-
-    @Override
-    public WithAsStep4 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4);
-    }
-
-    @Override
-    public WithAsStep5 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5);
-    }
-
-    @Override
-    public WithAsStep6 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6);
-    }
-
-    @Override
-    public WithAsStep7 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7);
-    }
-
-    @Override
-    public WithAsStep8 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8);
-    }
-
-    @Override
-    public WithAsStep9 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9);
-    }
-
-    @Override
-    public WithAsStep10 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10);
-    }
-
-    @Override
-    public WithAsStep11 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11);
-    }
-
-    @Override
-    public WithAsStep12 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12);
-    }
-
-    @Override
-    public WithAsStep13 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13);
-    }
-
-    @Override
-    public WithAsStep14 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14);
-    }
-
-    @Override
-    public WithAsStep15 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15);
-    }
-
-    @Override
-    public WithAsStep16 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16);
-    }
-
-    @Override
-    public WithAsStep17 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17);
-    }
-
-    @Override
-    public WithAsStep18 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17, Name fieldAlias18) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18);
-    }
-
-    @Override
-    public WithAsStep19 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19);
-    }
-
-    @Override
-    public WithAsStep20 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19, Name fieldAlias20) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20);
-    }
-
-    @Override
-    public WithAsStep21 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19, Name fieldAlias20,
-            Name fieldAlias21) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20,
-                fieldAlias21);
-    }
-
-    @Override
-    public WithAsStep22 with(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9, Name fieldAlias10,
-            Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14, Name fieldAlias15,
-            Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19, Name fieldAlias20,
-            Name fieldAlias21, Name fieldAlias22) {
-        return context.with(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5, fieldAlias6,
-                fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12, fieldAlias13,
-                fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19, fieldAlias20,
-                fieldAlias21, fieldAlias22);
-    }
-
-    @Override
-    public WithStep with(CommonTableExpression... tables) {
-        return context.with(tables);
-    }
-
-    @Override
-    public WithStep with(Collection> tables) {
-        return context.with(tables);
-    }
-
-    @Override
-    public WithAsStep withRecursive(String alias) {
-        return context.withRecursive(alias);
-    }
-
-    @Override
-    public WithAsStep withRecursive(String alias, String... fieldAliases) {
-        return context.withRecursive(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep withRecursive(String alias, Collection fieldAliases) {
-        return context.withRecursive(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep withRecursive(Name alias) {
-        return context.withRecursive(alias);
-    }
-
-    @Override
-    public WithAsStep withRecursive(Name alias, Name... fieldAliases) {
-        return context.withRecursive(alias, fieldAliases);
-    }
-
-    @Override
-    public WithAsStep withRecursive(Name alias, Collection fieldAliases) {
-        return context.withRecursive(alias, fieldAliases);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public WithAsStep withRecursive(String alias, Function, ? extends String> fieldNameFunction) {
-        return context.withRecursive(alias, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public WithAsStep withRecursive(String alias,
-            BiFunction, ? super Integer, ? extends String> fieldNameFunction) {
-        return context.withRecursive(alias, fieldNameFunction);
-    }
-
-    @Override
-    public WithAsStep1 withRecursive(String alias, String fieldAlias1) {
-        return context.withRecursive(alias, fieldAlias1);
-    }
-
-    @Override
-    public WithAsStep2 withRecursive(String alias, String fieldAlias1, String fieldAlias2) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2);
-    }
-
-    @Override
-    public WithAsStep3 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3);
-    }
-
-    @Override
-    public WithAsStep4 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4);
-    }
-
-    @Override
-    public WithAsStep5 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5);
-    }
-
-    @Override
-    public WithAsStep6 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6);
-    }
-
-    @Override
-    public WithAsStep7 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7);
-    }
-
-    @Override
-    public WithAsStep8 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8);
-    }
-
-    @Override
-    public WithAsStep9 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9);
-    }
-
-    @Override
-    public WithAsStep10 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10);
-    }
-
-    @Override
-    public WithAsStep11 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11);
-    }
-
-    @Override
-    public WithAsStep12 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12);
-    }
-
-    @Override
-    public WithAsStep13 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13);
-    }
-
-    @Override
-    public WithAsStep14 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14);
-    }
-
-    @Override
-    public WithAsStep15 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15);
-    }
-
-    @Override
-    public WithAsStep16 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16);
-    }
-
-    @Override
-    public WithAsStep17 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17);
-    }
-
-    @Override
-    public WithAsStep18 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18);
-    }
-
-    @Override
-    public WithAsStep19 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19);
-    }
-
-    @Override
-    public WithAsStep20 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20);
-    }
-
-    @Override
-    public WithAsStep21 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20, String fieldAlias21) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20, fieldAlias21);
-    }
-
-    @Override
-    public WithAsStep22 withRecursive(String alias, String fieldAlias1, String fieldAlias2, String fieldAlias3,
-            String fieldAlias4, String fieldAlias5, String fieldAlias6, String fieldAlias7, String fieldAlias8,
-            String fieldAlias9, String fieldAlias10, String fieldAlias11, String fieldAlias12, String fieldAlias13,
-            String fieldAlias14, String fieldAlias15, String fieldAlias16, String fieldAlias17, String fieldAlias18,
-            String fieldAlias19, String fieldAlias20, String fieldAlias21, String fieldAlias22) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20, fieldAlias21, fieldAlias22);
-    }
-
-    @Override
-    public WithAsStep1 withRecursive(Name alias, Name fieldAlias1) {
-        return context.withRecursive(alias, fieldAlias1);
-    }
-
-    @Override
-    public WithAsStep2 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2);
-    }
-
-    @Override
-    public WithAsStep3 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3);
-    }
-
-    @Override
-    public WithAsStep4 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4);
-    }
-
-    @Override
-    public WithAsStep5 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5);
-    }
-
-    @Override
-    public WithAsStep6 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6);
-    }
-
-    @Override
-    public WithAsStep7 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7);
-    }
-
-    @Override
-    public WithAsStep8 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8);
-    }
-
-    @Override
-    public WithAsStep9 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3, Name fieldAlias4,
-            Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9);
-    }
-
-    @Override
-    public WithAsStep10 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10);
-    }
-
-    @Override
-    public WithAsStep11 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11);
-    }
-
-    @Override
-    public WithAsStep12 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12);
-    }
-
-    @Override
-    public WithAsStep13 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13);
-    }
-
-    @Override
-    public WithAsStep14 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14);
-    }
-
-    @Override
-    public WithAsStep15 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15);
-    }
-
-    @Override
-    public WithAsStep16 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16);
-    }
-
-    @Override
-    public WithAsStep17 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17);
-    }
-
-    @Override
-    public WithAsStep18 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17, Name fieldAlias18) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18);
-    }
-
-    @Override
-    public WithAsStep19 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19);
-    }
-
-    @Override
-    public WithAsStep20 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19,
-            Name fieldAlias20) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20);
-    }
-
-    @Override
-    public WithAsStep21 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19,
-            Name fieldAlias20, Name fieldAlias21) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20, fieldAlias21);
-    }
-
-    @Override
-    public WithAsStep22 withRecursive(Name alias, Name fieldAlias1, Name fieldAlias2, Name fieldAlias3,
-            Name fieldAlias4, Name fieldAlias5, Name fieldAlias6, Name fieldAlias7, Name fieldAlias8, Name fieldAlias9,
-            Name fieldAlias10, Name fieldAlias11, Name fieldAlias12, Name fieldAlias13, Name fieldAlias14,
-            Name fieldAlias15, Name fieldAlias16, Name fieldAlias17, Name fieldAlias18, Name fieldAlias19,
-            Name fieldAlias20, Name fieldAlias21, Name fieldAlias22) {
-        return context.withRecursive(alias, fieldAlias1, fieldAlias2, fieldAlias3, fieldAlias4, fieldAlias5,
-                fieldAlias6, fieldAlias7, fieldAlias8, fieldAlias9, fieldAlias10, fieldAlias11, fieldAlias12,
-                fieldAlias13, fieldAlias14, fieldAlias15, fieldAlias16, fieldAlias17, fieldAlias18, fieldAlias19,
-                fieldAlias20, fieldAlias21, fieldAlias22);
-    }
-
-    @Override
-    public WithStep withRecursive(CommonTableExpression... tables) {
-        return context.withRecursive(tables);
-    }
-
-    @Override
-    public WithStep withRecursive(Collection> tables) {
-        return context.withRecursive(tables);
-    }
-
-    @Override
-    public  SelectWhereStep selectFrom(Table table) {
-        return time(context.selectFrom(table));
-    }
-
-    @Override
-    public SelectWhereStep selectFrom(Name table) {
-        return time(context.selectFrom(table));
-    }
-
-    @Override
-    public SelectWhereStep selectFrom(SQL sql) {
-        return time(context.selectFrom(sql));
-    }
-
-    @Override
-    public SelectWhereStep selectFrom(String sql) {
-        return time(context.selectFrom(sql));
-    }
-
-    @Override
-    public SelectWhereStep selectFrom(String sql, Object... bindings) {
-        return time(context.selectFrom(sql, bindings));
-    }
-
-    @Override
-    public SelectWhereStep selectFrom(String sql, QueryPart... parts) {
-        return time(context.selectFrom(sql, parts));
-    }
-
-    @Override
-    public SelectSelectStep select(Collection fields) {
-        return time(context.select(fields));
-    }
-
-    @Override
-    public SelectSelectStep select(SelectFieldOrAsterisk... fields) {
-        return time(context.select(fields));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1) {
-        return time(context.select(field1));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1, SelectField field2) {
-        return time(context.select(field1, field2));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1, SelectField field2,
-            SelectField field3) {
-        return time(context.select(field1, field2, field3));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4) {
-        return time(context.select(field1, field2, field3, field4));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5) {
-        return time(context.select(field1, field2, field3, field4, field5));
-    }
-
-    @Override
-    public  SelectSelectStep> select(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5,
-            SelectField field6) {
-        return time(context.select(field1, field2, field3, field4, field5, field6));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21));
-    }
-
-    @Override
-    public  SelectSelectStep> select(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21, SelectField field22) {
-        return time(context.select(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
-                field22));
-    }
-
-    @Override
-    public SelectSelectStep selectDistinct(Collection fields) {
-        return time(context.selectDistinct(fields));
-    }
-
-    @Override
-    public SelectSelectStep selectDistinct(SelectFieldOrAsterisk... fields) {
-        return time(context.selectDistinct(fields));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(SelectField field1) {
-        return time(context.selectDistinct(field1));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(SelectField field1, SelectField field2) {
-        return time(context.selectDistinct(field1, field2));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(SelectField field1,
-            SelectField field2, SelectField field3) {
-        return time(context.selectDistinct(field1, field2, field3));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4) {
-        return time(context.selectDistinct(field1, field2, field3, field4));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
-                field21));
-    }
-
-    @Override
-    public  SelectSelectStep> selectDistinct(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21, SelectField field22) {
-        return time(context.selectDistinct(field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
-                field21, field22));
-    }
-
-    @Override
-    public SelectSelectStep> selectZero() {
-        return time(context.selectZero());
-    }
-
-    @Override
-    public SelectSelectStep> selectOne() {
-        return time(context.selectOne());
-    }
-
-    @Override
-    public SelectSelectStep> selectCount() {
-        return time(context.selectCount());
-    }
-
-    @Override
-    public SelectQuery selectQuery() {
-        return time(context.selectQuery());
-    }
-
-    @Override
-    public  SelectQuery selectQuery(TableLike table) {
-        return time(context.selectQuery(table));
-    }
-
-    @Override
-    public  InsertQuery insertQuery(Table into) {
-        return time(context.insertQuery(into));
-    }
-
-    @Override
-    public  InsertSetStep insertInto(Table into) {
-        return timeCoercable(context.insertInto(into));
-    }
-
-    @Override
-    public  InsertValuesStep1 insertInto(Table into, Field field1) {
-        return time(context.insertInto(into, field1));
-    }
-
-    @Override
-    public  InsertValuesStep2 insertInto(Table into, Field field1,
-            Field field2) {
-        return time(context.insertInto(into, field1, field2));
-    }
-
-    @Override
-    public  InsertValuesStep3 insertInto(Table into, Field field1,
-            Field field2, Field field3) {
-        return time(context.insertInto(into, field1, field2, field3));
-    }
-
-    @Override
-    public  InsertValuesStep4 insertInto(Table into,
-            Field field1, Field field2, Field field3, Field field4) {
-        return time(context.insertInto(into, field1, field2, field3, field4));
-    }
-
-    @Override
-    public  InsertValuesStep5 insertInto(Table into,
-            Field field1, Field field2, Field field3, Field field4, Field field5) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5));
-    }
-
-    @Override
-    public  InsertValuesStep6 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6));
-    }
-
-    @Override
-    public  InsertValuesStep7 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7));
-    }
-
-    @Override
-    public  InsertValuesStep8 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8));
-    }
-
-    @Override
-    public  InsertValuesStep9 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9));
-    }
-
-    @Override
-    public  InsertValuesStep10 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10));
-    }
-
-    @Override
-    public  InsertValuesStep11 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11));
-    }
-
-    @Override
-    public  InsertValuesStep12 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12));
-    }
-
-    @Override
-    public  InsertValuesStep13 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13));
-    }
-
-    @Override
-    public  InsertValuesStep14 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14));
-    }
-
-    @Override
-    public  InsertValuesStep15 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15));
-    }
-
-    @Override
-    public  InsertValuesStep16 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16));
-    }
-
-    @Override
-    public  InsertValuesStep17 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17));
-    }
-
-    @Override
-    public  InsertValuesStep18 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18));
-    }
-
-    @Override
-    public  InsertValuesStep19 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19));
-    }
-
-    @Override
-    public  InsertValuesStep20 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
-    }
-
-    @Override
-    public  InsertValuesStep21 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20,
-            Field field21) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
-                field21));
-    }
-
-    @Override
-    public  InsertValuesStep22 insertInto(
-            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20,
-            Field field21, Field field22) {
-        return time(context.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
-                field21, field22));
-    }
-
-    @Override
-    public  InsertValuesStepN insertInto(Table into, Field... fields) {
-        return time(context.insertInto(into, fields));
-    }
-
-    @Override
-    public  InsertValuesStepN insertInto(Table into, Collection> fields) {
-        return time(context.insertInto(into, fields));
-    }
-
-    @Override
-    public  UpdateQuery updateQuery(Table table) {
-        return time(context.updateQuery(table));
-    }
-
-    @Override
-    public  UpdateSetFirstStep update(Table table) {
-        return timeCoercable(context.update(table));
-    }
-
-    @Override
-    public  MergeUsingStep mergeInto(Table table) {
-        return context.mergeInto(table);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep1 mergeInto(Table table, Field field1) {
-        return context.mergeInto(table, field1);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep2 mergeInto(Table table, Field field1,
-            Field field2) {
-        return context.mergeInto(table, field1, field2);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep3 mergeInto(Table table, Field field1,
-            Field field2, Field field3) {
-        return context.mergeInto(table, field1, field2, field3);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep4 mergeInto(Table table,
-            Field field1, Field field2, Field field3, Field field4) {
-        return context.mergeInto(table, field1, field2, field3, field4);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep5 mergeInto(Table table,
-            Field field1, Field field2, Field field3, Field field4, Field field5) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep6 mergeInto(Table table,
-            Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep7 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep8 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep9 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep10 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9,
-                field10);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep11 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep12 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep13 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep14 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep15 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep16 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep17 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep18 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep19 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep20 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep21 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20,
-            Field field21) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStep22 mergeInto(
-            Table table, Field field1, Field field2, Field field3, Field field4, Field field5,
-            Field field6, Field field7, Field field8, Field field9, Field field10,
-            Field field11, Field field12, Field field13, Field field14, Field field15,
-            Field field16, Field field17, Field field18, Field field19, Field field20,
-            Field field21, Field field22) {
-        return context.mergeInto(table, field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
-                field22);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStepN mergeInto(Table table, Field... fields) {
-        return context.mergeInto(table, fields);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public  MergeKeyStepN mergeInto(Table table, Collection> fields) {
-        return context.mergeInto(table, fields);
-    }
-
-    @Override
-    public  DeleteQuery deleteQuery(Table table) {
-        return context.deleteQuery(table);
-    }
-
-    @Override
-    public  DeleteUsingStep deleteFrom(Table table) {
-        return context.deleteFrom(table);
-    }
-
-    @Override
-    public  DeleteUsingStep delete(Table table) {
-        return context.delete(table);
-    }
-
-    @Override
-    public void batched(BatchedRunnable runnable) {
-        context.batched(runnable);
-    }
-
-    @Override
-    public  T batchedResult(BatchedCallable callable) {
-        return context.batchedResult(callable);
-    }
-
-    @Override
-    public Batch batch(Query... queries) {
-        return context.batch(queries);
-    }
-
-    @Override
-    public Batch batch(Queries queries) {
-        return context.batch(queries);
-    }
-
-    @Override
-    public Batch batch(String... queries) {
-        return context.batch(queries);
-    }
-
-    @Override
-    public Batch batch(Collection queries) {
-        return context.batch(queries);
-    }
-
-    @Override
-    public BatchBindStep batch(Query query) {
-        return context.batch(query);
-    }
-
-    @Override
-    public BatchBindStep batch(String sql) {
-        return context.batch(sql);
-    }
-
-    @Override
-    public Batch batch(Query query, Object[]... bindings) {
-        return context.batch(query, bindings);
-    }
-
-    @Override
-    public Batch batch(String sql, Object[]... bindings) {
-        return context.batch(sql, bindings);
-    }
-
-    @Override
-    public Batch batchStore(UpdatableRecord... records) {
-        return context.batchStore(records);
-    }
-
-    @Override
-    public Batch batchStore(Collection> records) {
-        return context.batchStore(records);
-    }
-
-    @Override
-    public Batch batchInsert(TableRecord... records) {
-        return context.batchInsert(records);
-    }
-
-    @Override
-    public Batch batchInsert(Collection> records) {
-        return context.batchInsert(records);
-    }
-
-    @Override
-    public Batch batchUpdate(UpdatableRecord... records) {
-        return context.batchUpdate(records);
-    }
-
-    @Override
-    public Batch batchUpdate(Collection> records) {
-        return context.batchUpdate(records);
-    }
-
-    @Override
-    public Batch batchMerge(UpdatableRecord... records) {
-        return context.batchMerge(records);
-    }
-
-    @Override
-    public Batch batchMerge(Collection> records) {
-        return context.batchMerge(records);
-    }
-
-    @Override
-    public Batch batchDelete(UpdatableRecord... records) {
-        return context.batchDelete(records);
-    }
-
-    @Override
-    public Batch batchDelete(Collection> records) {
-        return context.batchDelete(records);
-    }
-
-    @Override
-    public Queries ddl(Catalog catalog) {
-        return context.ddl(catalog);
-    }
-
-    @Override
-    public Queries ddl(Catalog schema, DDLExportConfiguration configuration) {
-        return context.ddl(schema, configuration);
-    }
-
-    @Override
-    public Queries ddl(Catalog schema, DDLFlag... flags) {
-        return context.ddl(schema, flags);
-    }
-
-    @Override
-    public Queries ddl(Schema schema) {
-        return context.ddl(schema);
-    }
-
-    @Override
-    public Queries ddl(Schema schema, DDLExportConfiguration configuration) {
-        return context.ddl(schema, configuration);
-    }
-
-    @Override
-    public Queries ddl(Schema schema, DDLFlag... flags) {
-        return context.ddl(schema, flags);
-    }
-
-    @Override
-    public Queries ddl(Table table) {
-        return context.ddl(table);
-    }
-
-    @Override
-    public Queries ddl(Table table, DDLExportConfiguration configuration) {
-        return context.ddl(table, configuration);
-    }
-
-    @Override
-    public Queries ddl(Table table, DDLFlag... flags) {
-        return context.ddl(table, flags);
-    }
-
-    @Override
-    public Queries ddl(Table... tables) {
-        return context.ddl(tables);
-    }
-
-    @Override
-    public Queries ddl(Table[] tables, DDLExportConfiguration configuration) {
-        return context.ddl(tables, configuration);
-    }
-
-    @Override
-    public Queries ddl(Table[] tables, DDLFlag... flags) {
-        return context.ddl(tables, flags);
-    }
-
-    @Override
-    public Queries ddl(Collection> tables) {
-        return context.ddl(tables);
-    }
-
-    @Override
-    public Queries ddl(Collection> tables, DDLFlag... flags) {
-        return context.ddl(tables, flags);
-    }
-
-    @Override
-    public Queries ddl(Collection> tables, DDLExportConfiguration configuration) {
-        return context.ddl(tables, configuration);
-    }
-
-    @Override
-    public RowCountQuery setCatalog(String catalog) {
-        return context.setCatalog(catalog);
-    }
-
-    @Override
-    public RowCountQuery setCatalog(Name catalog) {
-        return context.setCatalog(catalog);
-    }
-
-    @Override
-    public RowCountQuery setCatalog(Catalog catalog) {
-        return context.setCatalog(catalog);
-    }
-
-    @Override
-    public RowCountQuery setSchema(String schema) {
-        return context.setSchema(schema);
-    }
-
-    @Override
-    public RowCountQuery setSchema(Name schema) {
-        return context.setSchema(schema);
-    }
-
-    @Override
-    public RowCountQuery setSchema(Schema schema) {
-        return context.setSchema(schema);
-    }
-
-    @Override
-    public RowCountQuery set(Name name, Param param) {
-        return context.set(name, param);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabase(String database) {
-        return context.createDatabase(database);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabase(Name database) {
-        return context.createDatabase(database);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabase(Catalog database) {
-        return context.createDatabase(database);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabaseIfNotExists(String database) {
-        return context.createDatabaseIfNotExists(database);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabaseIfNotExists(Name database) {
-        return context.createDatabaseIfNotExists(database);
-    }
-
-    @Override
-    public CreateDatabaseFinalStep createDatabaseIfNotExists(Catalog database) {
-        return context.createDatabaseIfNotExists(database);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomain(String domain) {
-        return context.createDomain(domain);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomain(Name domain) {
-        return context.createDomain(domain);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomain(Domain domain) {
-        return context.createDomain(domain);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomainIfNotExists(String domain) {
-        return context.createDomainIfNotExists(domain);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomainIfNotExists(Name domain) {
-        return context.createDomainIfNotExists(domain);
-    }
-
-    @Override
-    public CreateDomainAsStep createDomainIfNotExists(Domain domain) {
-        return context.createDomainIfNotExists(domain);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnTable(String tableName) {
-        return context.commentOnTable(tableName);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnTable(Name tableName) {
-        return context.commentOnTable(tableName);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnTable(Table table) {
-        return context.commentOnTable(table);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnView(String viewName) {
-        return context.commentOnView(viewName);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnView(Name viewName) {
-        return context.commentOnView(viewName);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnView(Table view) {
-        return context.commentOnView(view);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnColumn(Name columnName) {
-        return context.commentOnColumn(columnName);
-    }
-
-    @Override
-    public CommentOnIsStep commentOnColumn(Field field) {
-        return context.commentOnColumn(field);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchema(String schema) {
-        return context.createSchema(schema);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchema(Name schema) {
-        return context.createSchema(schema);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchema(Schema schema) {
-        return context.createSchema(schema);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchemaIfNotExists(String schema) {
-        return context.createSchemaIfNotExists(schema);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchemaIfNotExists(Name schema) {
-        return context.createSchemaIfNotExists(schema);
-    }
-
-    @Override
-    public CreateSchemaFinalStep createSchemaIfNotExists(Schema schema) {
-        return context.createSchemaIfNotExists(schema);
-    }
-
-    @Override
-    public CreateTableColumnStep createTable(String table) {
-        return context.createTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTable(Name table) {
-        return context.createTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTable(Table table) {
-        return context.createTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTableIfNotExists(String table) {
-        return context.createTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTableIfNotExists(Name table) {
-        return context.createTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTableIfNotExists(Table table) {
-        return context.createTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTable(String table) {
-        return context.createTemporaryTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTable(Name table) {
-        return context.createTemporaryTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTable(Table table) {
-        return context.createTemporaryTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTableIfNotExists(String table) {
-        return context.createTemporaryTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTableIfNotExists(Name table) {
-        return context.createTemporaryTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createTemporaryTableIfNotExists(Table table) {
-        return context.createTemporaryTableIfNotExists(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createGlobalTemporaryTable(String table) {
-        return context.createGlobalTemporaryTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createGlobalTemporaryTable(Name table) {
-        return context.createGlobalTemporaryTable(table);
-    }
-
-    @Override
-    public CreateTableColumnStep createGlobalTemporaryTable(Table table) {
-        return context.createGlobalTemporaryTable(table);
-    }
-
-    @Override
-    public CreateViewAsStep createView(String view, String... fields) {
-        return context.createView(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createView(Name view, Name... fields) {
-        return context.createView(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createView(Table view, Field... fields) {
-        return context.createView(view, fields);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(String view,
-            Function, ? extends String> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(String view,
-            BiFunction, ? super Integer, ? extends String> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(Name view,
-            Function, ? extends Name> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(Name view,
-            BiFunction, ? super Integer, ? extends Name> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(Table view,
-            Function, ? extends Field> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createView(Table view,
-            BiFunction, ? super Integer, ? extends Field> fieldNameFunction) {
-        return context.createView(view, fieldNameFunction);
-    }
-
-    @Override
-    public CreateViewAsStep createOrReplaceView(String view, String... fields) {
-        return context.createOrReplaceView(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createOrReplaceView(Name view, Name... fields) {
-        return context.createOrReplaceView(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createOrReplaceView(Table view, Field... fields) {
-        return context.createOrReplaceView(view, fields);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(String view,
-            Function, ? extends String> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(String view,
-            BiFunction, ? super Integer, ? extends String> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(Name view,
-            Function, ? extends Name> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(Name view,
-            BiFunction, ? super Integer, ? extends Name> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(Table view,
-            Function, ? extends Field> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createOrReplaceView(Table view,
-            BiFunction, ? super Integer, ? extends Field> fieldNameFunction) {
-        return context.createOrReplaceView(view, fieldNameFunction);
-    }
-
-    @Override
-    public CreateViewAsStep createViewIfNotExists(String view, String... fields) {
-        return context.createViewIfNotExists(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Name view, Name... fields) {
-        return context.createViewIfNotExists(view, fields);
-    }
-
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Table view, Field... fields) {
-        return context.createViewIfNotExists(view, fields);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(String view,
-            Function, ? extends String> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(String view,
-            BiFunction, ? super Integer, ? extends String> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Name view,
-            Function, ? extends Name> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Name view,
-            BiFunction, ? super Integer, ? extends Name> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Table view,
-            Function, ? extends Field> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @SuppressWarnings("deprecation")
-    @Override
-    public CreateViewAsStep createViewIfNotExists(Table view,
-            BiFunction, ? super Integer, ? extends Field> fieldNameFunction) {
-        return context.createViewIfNotExists(view, fieldNameFunction);
-    }
-
-    @Override
-    public CreateTypeStep createType(String type) {
-        return context.createType(type);
-    }
-
-    @Override
-    public CreateTypeStep createType(Name type) {
-        return context.createType(type);
-    }
-
-    @Override
-    public AlterTypeStep alterType(String type) {
-        return context.alterType(type);
-    }
-
-    @Override
-    public AlterTypeStep alterType(Name type) {
-        return context.alterType(type);
-    }
-
-    @Override
-    public DropTypeStep dropType(String type) {
-        return context.dropType(type);
-    }
-
-    @Override
-    public DropTypeStep dropType(Name type) {
-        return context.dropType(type);
-    }
-
-    @Override
-    public DropTypeStep dropType(String... type) {
-        return context.dropType(type);
-    }
-
-    @Override
-    public DropTypeStep dropType(Name... type) {
-        return context.dropType(type);
-    }
-
-    @Override
-    public DropTypeStep dropType(Collection type) {
-        return context.dropType(type);
-    }
-
-    @Override
-    public DropTypeStep dropTypeIfExists(String type) {
-        return context.dropTypeIfExists(type);
-    }
-
-    @Override
-    public DropTypeStep dropTypeIfExists(Name type) {
-        return context.dropTypeIfExists(type);
-    }
-
-    @Override
-    public DropTypeStep dropTypeIfExists(String... type) {
-        return context.dropTypeIfExists(type);
-    }
-
-    @Override
-    public DropTypeStep dropTypeIfExists(Name... type) {
-        return context.dropTypeIfExists(type);
-    }
-
-    @Override
-    public DropTypeStep dropTypeIfExists(Collection type) {
-        return context.dropTypeIfExists(type);
-    }
-
-    @Override
-    public CreateIndexStep createIndex() {
-        return context.createIndex();
-    }
-
-    @Override
-    public CreateIndexStep createIndex(String index) {
-        return context.createIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createIndex(Name index) {
-        return context.createIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createIndex(Index index) {
-        return context.createIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createIndexIfNotExists(String index) {
-        return context.createIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateIndexStep createIndexIfNotExists(Name index) {
-        return context.createIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateIndexStep createIndexIfNotExists(Index index) {
-        return context.createIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndex() {
-        return context.createUniqueIndex();
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndex(String index) {
-        return context.createUniqueIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndex(Name index) {
-        return context.createUniqueIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndex(Index index) {
-        return context.createUniqueIndex(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndexIfNotExists(String index) {
-        return context.createUniqueIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndexIfNotExists(Name index) {
-        return context.createUniqueIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateIndexStep createUniqueIndexIfNotExists(Index index) {
-        return context.createUniqueIndexIfNotExists(index);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequence(String sequence) {
-        return context.createSequence(sequence);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequence(Name sequence) {
-        return context.createSequence(sequence);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequence(Sequence sequence) {
-        return context.createSequence(sequence);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequenceIfNotExists(String sequence) {
-        return context.createSequenceIfNotExists(sequence);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequenceIfNotExists(Name sequence) {
-        return context.createSequenceIfNotExists(sequence);
-    }
-
-    @Override
-    public CreateSequenceFlagsStep createSequenceIfNotExists(Sequence sequence) {
-        return context.createSequenceIfNotExists(sequence);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabase(String database) {
-        return context.alterDatabase(database);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabase(Name database) {
-        return context.alterDatabase(database);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabase(Catalog database) {
-        return context.alterDatabase(database);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabaseIfExists(String database) {
-        return context.alterDatabaseIfExists(database);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabaseIfExists(Name database) {
-        return context.alterDatabaseIfExists(database);
-    }
-
-    @Override
-    public AlterDatabaseStep alterDatabaseIfExists(Catalog database) {
-        return context.alterDatabaseIfExists(database);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomain(String domain) {
-        return context.alterDomain(domain);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomain(Name domain) {
-        return context.alterDomain(domain);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomain(Domain domain) {
-        return context.alterDomain(domain);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomainIfExists(String domain) {
-        return context.alterDomainIfExists(domain);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomainIfExists(Name domain) {
-        return context.alterDomainIfExists(domain);
-    }
-
-    @Override
-    public  AlterDomainStep alterDomainIfExists(Domain domain) {
-        return context.alterDomainIfExists(domain);
-    }
-
-    @Override
-    public AlterSequenceStep alterSequence(String sequence) {
-        return context.alterSequence(sequence);
-    }
-
-    @Override
-    public AlterSequenceStep alterSequence(Name sequence) {
-        return context.alterSequence(sequence);
-    }
-
-    @Override
-    public  AlterSequenceStep alterSequence(Sequence sequence) {
-        return context.alterSequence(sequence);
-    }
-
-    @Override
-    public AlterSequenceStep alterSequenceIfExists(String sequence) {
-        return context.alterSequenceIfExists(sequence);
-    }
-
-    @Override
-    public AlterSequenceStep alterSequenceIfExists(Name sequence) {
-        return context.alterSequenceIfExists(sequence);
-    }
-
-    @Override
-    public  AlterSequenceStep alterSequenceIfExists(Sequence sequence) {
-        return context.alterSequenceIfExists(sequence);
-    }
-
-    @Override
-    public AlterTableStep alterTable(String table) {
-        return context.alterTable(table);
-    }
-
-    @Override
-    public AlterTableStep alterTable(Name table) {
-        return context.alterTable(table);
-    }
-
-    @Override
-    public AlterTableStep alterTable(Table table) {
-        return context.alterTable(table);
-    }
-
-    @Override
-    public AlterTableStep alterTableIfExists(String table) {
-        return context.alterTableIfExists(table);
-    }
-
-    @Override
-    public AlterTableStep alterTableIfExists(Name table) {
-        return context.alterTableIfExists(table);
-    }
-
-    @Override
-    public AlterTableStep alterTableIfExists(Table table) {
-        return context.alterTableIfExists(table);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchema(String schema) {
-        return context.alterSchema(schema);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchema(Name schema) {
-        return context.alterSchema(schema);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchema(Schema schema) {
-        return context.alterSchema(schema);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchemaIfExists(String schema) {
-        return context.alterSchemaIfExists(schema);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchemaIfExists(Name schema) {
-        return context.alterSchemaIfExists(schema);
-    }
-
-    @Override
-    public AlterSchemaStep alterSchemaIfExists(Schema schema) {
-        return context.alterSchemaIfExists(schema);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabase(String database) {
-        return context.dropDatabase(database);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabase(Name database) {
-        return context.dropDatabase(database);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabase(Catalog database) {
-        return context.dropDatabase(database);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabaseIfExists(String database) {
-        return context.dropDatabaseIfExists(database);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabaseIfExists(Name database) {
-        return context.dropDatabaseIfExists(database);
-    }
-
-    @Override
-    public DropDatabaseFinalStep dropDatabaseIfExists(Catalog database) {
-        return context.dropDatabaseIfExists(database);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomain(String domain) {
-        return context.dropDomain(domain);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomain(Name domain) {
-        return context.dropDomain(domain);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomain(Domain domain) {
-        return context.dropDomain(domain);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomainIfExists(String domain) {
-        return context.dropDomainIfExists(domain);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomainIfExists(Name domain) {
-        return context.dropDomainIfExists(domain);
-    }
-
-    @Override
-    public DropDomainCascadeStep dropDomainIfExists(Domain domain) {
-        return context.dropDomainIfExists(domain);
-    }
-
-    @Override
-    public AlterViewStep alterView(String view) {
-        return context.alterView(view);
-    }
-
-    @Override
-    public AlterViewStep alterView(Name view) {
-        return context.alterView(view);
-    }
-
-    @Override
-    public AlterViewStep alterView(Table view) {
-        return context.alterView(view);
-    }
-
-    @Override
-    public AlterViewStep alterViewIfExists(String view) {
-        return context.alterViewIfExists(view);
-    }
-
-    @Override
-    public AlterViewStep alterViewIfExists(Name view) {
-        return context.alterViewIfExists(view);
-    }
-
-    @Override
-    public AlterViewStep alterViewIfExists(Table view) {
-        return context.alterViewIfExists(view);
-    }
-
-    @Override
-    public AlterIndexOnStep alterIndex(String index) {
-        return context.alterIndex(index);
-    }
-
-    @Override
-    public AlterIndexOnStep alterIndex(Name index) {
-        return context.alterIndex(index);
-    }
-
-    @Override
-    public AlterIndexOnStep alterIndex(Index index) {
-        return context.alterIndex(index);
-    }
-
-    @Override
-    public AlterIndexStep alterIndexIfExists(String index) {
-        return context.alterIndexIfExists(index);
-    }
-
-    @Override
-    public AlterIndexStep alterIndexIfExists(Name index) {
-        return context.alterIndexIfExists(index);
-    }
-
-    @Override
-    public AlterIndexStep alterIndexIfExists(Index index) {
-        return context.alterIndexIfExists(index);
-    }
-
-    @Override
-    public DropSchemaStep dropSchema(String schema) {
-        return context.dropSchema(schema);
-    }
-
-    @Override
-    public DropSchemaStep dropSchema(Name schema) {
-        return context.dropSchema(schema);
-    }
-
-    @Override
-    public DropSchemaStep dropSchema(Schema schema) {
-        return context.dropSchema(schema);
-    }
-
-    @Override
-    public DropSchemaStep dropSchemaIfExists(String schema) {
-        return context.dropSchemaIfExists(schema);
-    }
-
-    @Override
-    public DropSchemaStep dropSchemaIfExists(Name schema) {
-        return context.dropSchemaIfExists(schema);
-    }
-
-    @Override
-    public DropSchemaStep dropSchemaIfExists(Schema schema) {
-        return context.dropSchemaIfExists(schema);
-    }
-
-    @Override
-    public DropViewFinalStep dropView(String view) {
-        return context.dropView(view);
-    }
-
-    @Override
-    public DropViewFinalStep dropView(Name view) {
-        return context.dropView(view);
-    }
-
-    @Override
-    public DropViewFinalStep dropView(Table view) {
-        return context.dropView(view);
-    }
-
-    @Override
-    public DropViewFinalStep dropViewIfExists(String view) {
-        return context.dropViewIfExists(view);
-    }
-
-    @Override
-    public DropViewFinalStep dropViewIfExists(Name view) {
-        return context.dropViewIfExists(view);
-    }
-
-    @Override
-    public DropViewFinalStep dropViewIfExists(Table view) {
-        return context.dropViewIfExists(view);
-    }
-
-    @Override
-    public DropTableStep dropTable(String table) {
-        return context.dropTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTable(Name table) {
-        return context.dropTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTable(Table table) {
-        return context.dropTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTableIfExists(String table) {
-        return context.dropTableIfExists(table);
-    }
-
-    @Override
-    public DropTableStep dropTableIfExists(Name table) {
-        return context.dropTableIfExists(table);
-    }
-
-    @Override
-    public DropTableStep dropTableIfExists(Table table) {
-        return context.dropTableIfExists(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTable(String table) {
-        return context.dropTemporaryTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTable(Name table) {
-        return context.dropTemporaryTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTable(Table table) {
-        return context.dropTemporaryTable(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTableIfExists(String table) {
-        return context.dropTemporaryTableIfExists(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTableIfExists(Name table) {
-        return context.dropTemporaryTableIfExists(table);
-    }
-
-    @Override
-    public DropTableStep dropTemporaryTableIfExists(Table table) {
-        return context.dropTemporaryTableIfExists(table);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndex(String index) {
-        return context.dropIndex(index);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndex(Name index) {
-        return context.dropIndex(index);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndex(Index index) {
-        return context.dropIndex(index);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndexIfExists(String index) {
-        return context.dropIndexIfExists(index);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndexIfExists(Name index) {
-        return context.dropIndexIfExists(index);
-    }
-
-    @Override
-    public DropIndexOnStep dropIndexIfExists(Index index) {
-        return context.dropIndexIfExists(index);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequence(String sequence) {
-        return context.dropSequence(sequence);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequence(Name sequence) {
-        return context.dropSequence(sequence);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequence(Sequence sequence) {
-        return context.dropSequence(sequence);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequenceIfExists(String sequence) {
-        return context.dropSequenceIfExists(sequence);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequenceIfExists(Name sequence) {
-        return context.dropSequenceIfExists(sequence);
-    }
-
-    @Override
-    public DropSequenceFinalStep dropSequenceIfExists(Sequence sequence) {
-        return context.dropSequenceIfExists(sequence);
-    }
-
-    @Override
-    public TruncateIdentityStep truncate(String table) {
-        return context.truncate(table);
-    }
-
-    @Override
-    public TruncateIdentityStep truncate(Name table) {
-        return context.truncate(table);
-    }
-
-    @Override
-    public  TruncateIdentityStep truncate(Table table) {
-        return context.truncate(table);
-    }
-
-    @Override
-    public TruncateIdentityStep truncateTable(String table) {
-        return context.truncateTable(table);
-    }
-
-    @Override
-    public TruncateIdentityStep truncateTable(Name table) {
-        return context.truncateTable(table);
-    }
-
-    @Override
-    public  TruncateIdentityStep truncateTable(Table table) {
-        return context.truncateTable(table);
-    }
-
-    @Override
-    public GrantOnStep grant(Privilege privilege) {
-        return context.grant(privilege);
-    }
-
-    @Override
-    public GrantOnStep grant(Privilege... privileges) {
-        return context.grant(privileges);
-    }
-
-    @Override
-    public GrantOnStep grant(Collection privileges) {
-        return context.grant(privileges);
-    }
-
-    @Override
-    public RevokeOnStep revoke(Privilege privilege) {
-        return context.revoke(privilege);
-    }
-
-    @Override
-    public RevokeOnStep revoke(Privilege... privileges) {
-        return context.revoke(privileges);
-    }
-
-    @Override
-    public RevokeOnStep revoke(Collection privileges) {
-        return context.revoke(privileges);
-    }
-
-    @Override
-    public RevokeOnStep revokeGrantOptionFor(Privilege privilege) {
-        return context.revokeGrantOptionFor(privilege);
-    }
-
-    @Override
-    public RevokeOnStep revokeGrantOptionFor(Privilege... privileges) {
-        return context.revokeGrantOptionFor(privileges);
-    }
-
-    @Override
-    public RevokeOnStep revokeGrantOptionFor(Collection privileges) {
-        return context.revokeGrantOptionFor(privileges);
-    }
-
-    @Override
-    public BigInteger lastID() throws DataAccessException {
-        return context.lastID();
-    }
-
-    @Override
-    public BigInteger nextval(String sequence) throws DataAccessException {
-        return context.nextval(sequence);
-    }
-
-    @Override
-    public BigInteger nextval(Name sequence) throws DataAccessException {
-        return context.nextval(sequence);
-    }
-
-    @Override
-    public  T nextval(Sequence sequence) throws DataAccessException {
-        return context.nextval(sequence);
-    }
-
-    @Override
-    public  List nextvals(Sequence sequence, int size) throws DataAccessException {
-        return context.nextvals(sequence, size);
-    }
-
-    @Override
-    public BigInteger currval(String sequence) throws DataAccessException {
-        return context.currval(sequence);
-    }
-
-    @Override
-    public BigInteger currval(Name sequence) throws DataAccessException {
-        return context.currval(sequence);
-    }
-
-    @Override
-    public  T currval(Sequence sequence) throws DataAccessException {
-        return context.currval(sequence);
-    }
-
-    @Override
-    public > R newRecord(UDT type) {
-        return context.newRecord(type);
-    }
-
-    @Override
-    public  R newRecord(Table table) {
-        return context.newRecord(table);
-    }
-
-    @Override
-    public  R newRecord(Table table, Object source) {
-        return context.newRecord(table, source);
-    }
-
-    @Override
-    public Record newRecord(Field... fields) {
-        return context.newRecord(fields);
-    }
-
-    @Override
-    public Record newRecord(Collection> fields) {
-        return context.newRecord(fields);
-    }
-
-    @Override
-    public  Record1 newRecord(Field field1) {
-        return context.newRecord(field1);
-    }
-
-    @Override
-    public  Record2 newRecord(Field field1, Field field2) {
-        return context.newRecord(field1, field2);
-    }
-
-    @Override
-    public  Record3 newRecord(Field field1, Field field2, Field field3) {
-        return context.newRecord(field1, field2, field3);
-    }
-
-    @Override
-    public  Record4 newRecord(Field field1, Field field2, Field field3,
-            Field field4) {
-        return context.newRecord(field1, field2, field3, field4);
-    }
-
-    @Override
-    public  Record5 newRecord(Field field1, Field field2,
-            Field field3, Field field4, Field field5) {
-        return context.newRecord(field1, field2, field3, field4, field5);
-    }
-
-    @Override
-    public  Record6 newRecord(Field field1, Field field2,
-            Field field3, Field field4, Field field5, Field field6) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6);
-    }
-
-    @Override
-    public  Record7 newRecord(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7);
-    }
-
-    @Override
-    public  Record8 newRecord(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6, Field field7,
-            Field field8) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8);
-    }
-
-    @Override
-    public  Record9 newRecord(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6, Field field7,
-            Field field8, Field field9) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9);
-    }
-
-    @Override
-    public  Record10 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10);
-    }
-
-    @Override
-    public  Record11 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11);
-    }
-
-    @Override
-    public  Record12 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12);
-    }
-
-    @Override
-    public  Record13 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13);
-    }
-
-    @Override
-    public  Record14 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14);
-    }
-
-    @Override
-    public  Record15 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15);
-    }
-
-    @Override
-    public  Record16 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16);
-    }
-
-    @Override
-    public  Record17 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17);
-    }
-
-    @Override
-    public  Record18 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18);
-    }
-
-    @Override
-    public  Record19 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19);
-    }
-
-    @Override
-    public  Record20 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20);
-    }
-
-    @Override
-    public  Record21 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20, Field field21) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21);
-    }
-
-    @Override
-    public  Record22 newRecord(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20, Field field21,
-            Field field22) {
-        return context.newRecord(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
-                field22);
-    }
-
-    @Override
-    public  Result newResult(Table table) {
-        return context.newResult(table);
-    }
-
-    @Override
-    public Result newResult(Field... fields) {
-        return context.newResult(fields);
-    }
-
-    @Override
-    public Result newResult(Collection> fields) {
-        return context.newResult(fields);
-    }
-
-    @Override
-    public  Result> newResult(Field field1) {
-        return context.newResult(field1);
-    }
-
-    @Override
-    public  Result> newResult(Field field1, Field field2) {
-        return context.newResult(field1, field2);
-    }
-
-    @Override
-    public  Result> newResult(Field field1, Field field2, Field field3) {
-        return context.newResult(field1, field2, field3);
-    }
-
-    @Override
-    public  Result> newResult(Field field1, Field field2,
-            Field field3, Field field4) {
-        return context.newResult(field1, field2, field3, field4);
-    }
-
-    @Override
-    public  Result> newResult(Field field1, Field field2,
-            Field field3, Field field4, Field field5) {
-        return context.newResult(field1, field2, field3, field4, field5);
-    }
-
-    @Override
-    public  Result> newResult(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6) {
-        return context.newResult(field1, field2, field3, field4, field5, field6);
-    }
-
-    @Override
-    public  Result> newResult(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7);
-    }
-
-    @Override
-    public  Result> newResult(Field field1,
-            Field field2, Field field3, Field field4, Field field5, Field field6, Field field7,
-            Field field8) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20, Field field21) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21);
-    }
-
-    @Override
-    public  Result> newResult(
-            Field field1, Field field2, Field field3, Field field4, Field field5, Field field6,
-            Field field7, Field field8, Field field9, Field field10, Field field11,
-            Field field12, Field field13, Field field14, Field field15, Field field16,
-            Field field17, Field field18, Field field19, Field field20, Field field21,
-            Field field22) {
-        return context.newResult(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
-                field22);
-    }
-
-    @Override
-    public  Result fetch(ResultQuery query) throws DataAccessException {
-        return context.fetch(query);
-    }
-
-    @Override
-    public  Cursor fetchLazy(ResultQuery query) throws DataAccessException {
-        return context.fetchLazy(query);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(ResultQuery query) {
-        return context.fetchAsync(query);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Executor executor, ResultQuery query) {
-        return context.fetchAsync(executor, query);
-    }
-
-    @Override
-    public  Stream fetchStream(ResultQuery query) throws DataAccessException {
-        return context.fetchStream(query);
-    }
-
-    @Override
-    public  Results fetchMany(ResultQuery query) throws DataAccessException {
-        return context.fetchMany(query);
-    }
-
-    @Override
-    public  R fetchOne(ResultQuery query) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(query);
-    }
-
-    @Override
-    public  R fetchSingle(ResultQuery query)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(query);
-    }
-
-    @Override
-    public  Optional fetchOptional(ResultQuery query)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(query);
-    }
-
-    @Override
-    public  T fetchValue(Table> table) throws DataAccessException, TooManyRowsException {
-        return context.fetchValue(table);
-    }
-
-    @Override
-    public > T fetchValue(ResultQuery query)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchValue(query);
-    }
-
-    @Override
-    public  T fetchValue(TableField field) throws DataAccessException, TooManyRowsException {
-        return context.fetchValue(field);
-    }
-
-    @Override
-    public  T fetchValue(Field field) throws DataAccessException {
-        return context.fetchValue(field);
-    }
-
-    @Override
-    public > Optional fetchOptionalValue(ResultQuery query)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(query);
-    }
-
-    @Override
-    public  Optional fetchOptionalValue(TableField field)
-            throws DataAccessException, TooManyRowsException, InvalidResultException {
-        return context.fetchOptionalValue(field);
-    }
-
-    @Override
-    public  List fetchValues(Table> table) throws DataAccessException {
-        return context.fetchValues(table);
-    }
-
-    @Override
-    public > List fetchValues(ResultQuery query) throws DataAccessException {
-        return context.fetchValues(query);
-    }
-
-    @Override
-    public  List fetchValues(TableField field) throws DataAccessException {
-        return context.fetchValues(field);
-    }
-
-    @Override
-    public > Result fetchByExample(R example) throws DataAccessException {
-        return context.fetchByExample(example);
-    }
-
-    @Override
-    public int fetchCount(Select query) throws DataAccessException {
-        return context.fetchCount(query);
-    }
-
-    @Override
-    public int fetchCount(Table table) throws DataAccessException {
-        return context.fetchCount(table);
-    }
-
-    @Override
-    public int fetchCount(Table table, Condition condition) throws DataAccessException {
-        return context.fetchCount(table, condition);
-    }
-
-    @Override
-    public int fetchCount(Table table, Condition... conditions) throws DataAccessException {
-        return context.fetchCount(table, conditions);
-    }
-
-    @Override
-    public int fetchCount(Table table, Collection conditions) throws DataAccessException {
-        return context.fetchCount(table, conditions);
-    }
-
-    @Override
-    public boolean fetchExists(Select query) throws DataAccessException {
-        return context.fetchExists(query);
-    }
-
-    @Override
-    public boolean fetchExists(Table table) throws DataAccessException {
-        return context.fetchExists(table);
-    }
-
-    @Override
-    public boolean fetchExists(Table table, Condition condition) throws DataAccessException {
-        return context.fetchExists(table, condition);
-    }
-
-    @Override
-    public boolean fetchExists(Table table, Condition... conditions) throws DataAccessException {
-        return context.fetchExists(table, conditions);
-    }
-
-    @Override
-    public boolean fetchExists(Table table, Collection conditions) throws DataAccessException {
-        return context.fetchExists(table, conditions);
-    }
-
-    @Override
-    public int execute(Query query) throws DataAccessException {
-        return context.execute(query);
-    }
-
-    @Override
-    public  Result fetch(Table table) throws DataAccessException {
-        return context.fetch(table);
-    }
-
-    @Override
-    public  Result fetch(Table table, Condition condition) throws DataAccessException {
-        return context.fetch(table, condition);
-    }
-
-    @Override
-    public  Result fetch(Table table, Condition... conditions) throws DataAccessException {
-        return context.fetch(table, conditions);
-    }
-
-    @Override
-    public  Result fetch(Table table, Collection conditions)
-            throws DataAccessException {
-        return context.fetch(table, conditions);
-    }
-
-    @Override
-    public  R fetchOne(Table table) throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(table);
-    }
-
-    @Override
-    public  R fetchOne(Table table, Condition condition)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(table, condition);
-    }
-
-    @Override
-    public  R fetchOne(Table table, Condition... conditions)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(table, conditions);
-    }
-
-    @Override
-    public  R fetchOne(Table table, Collection conditions)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOne(table, conditions);
-    }
-
-    @Override
-    public  R fetchSingle(Table table)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(table);
-    }
-
-    @Override
-    public  R fetchSingle(Table table, Condition condition)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(table, condition);
-    }
-
-    @Override
-    public  R fetchSingle(Table table, Condition... conditions)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(table, conditions);
-    }
-
-    @Override
-    public  R fetchSingle(Table table, Collection conditions)
-            throws DataAccessException, NoDataFoundException, TooManyRowsException {
-        return context.fetchSingle(table, conditions);
-    }
-
-    @Override
-    public Record fetchSingle(SelectField... fields) throws DataAccessException {
-        return context.fetchSingle(fields);
-    }
-
-    @Override
-    public Record fetchSingle(Collection> fields) throws DataAccessException {
-        return context.fetchSingle(fields);
-    }
-
-    @Override
-    public  Record1 fetchSingle(SelectField field1) throws DataAccessException {
-        return context.fetchSingle(field1);
-    }
-
-    @Override
-    public  Record2 fetchSingle(SelectField field1, SelectField field2)
-            throws DataAccessException {
-        return context.fetchSingle(field1, field2);
-    }
-
-    @Override
-    public  Record3 fetchSingle(SelectField field1, SelectField field2,
-            SelectField field3) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3);
-    }
-
-    @Override
-    public  Record4 fetchSingle(SelectField field1, SelectField field2,
-            SelectField field3, SelectField field4) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4);
-    }
-
-    @Override
-    public  Record5 fetchSingle(SelectField field1, SelectField field2,
-            SelectField field3, SelectField field4, SelectField field5) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5);
-    }
-
-    @Override
-    public  Record6 fetchSingle(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5,
-            SelectField field6) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6);
-    }
-
-    @Override
-    public  Record7 fetchSingle(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5,
-            SelectField field6, SelectField field7) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7);
-    }
-
-    @Override
-    public  Record8 fetchSingle(SelectField field1,
-            SelectField field2, SelectField field3, SelectField field4, SelectField field5,
-            SelectField field6, SelectField field7, SelectField field8) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8);
-    }
-
-    @Override
-    public  Record9 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9);
-    }
-
-    @Override
-    public  Record10 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10);
-    }
-
-    @Override
-    public  Record11 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11);
-    }
-
-    @Override
-    public  Record12 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12)
-            throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12);
-    }
-
-    @Override
-    public  Record13 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13);
-    }
-
-    @Override
-    public  Record14 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14);
-    }
-
-    @Override
-    public  Record15 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15);
-    }
-
-    @Override
-    public  Record16 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16)
-            throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16);
-    }
-
-    @Override
-    public  Record17 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17);
-    }
-
-    @Override
-    public  Record18 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18);
-    }
-
-    @Override
-    public  Record19 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19);
-    }
-
-    @Override
-    public  Record20 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20)
-            throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20);
-    }
-
-    @Override
-    public  Record21 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21);
-    }
-
-    @Override
-    public  Record22 fetchSingle(
-            SelectField field1, SelectField field2, SelectField field3, SelectField field4,
-            SelectField field5, SelectField field6, SelectField field7, SelectField field8,
-            SelectField field9, SelectField field10, SelectField field11, SelectField field12,
-            SelectField field13, SelectField field14, SelectField field15, SelectField field16,
-            SelectField field17, SelectField field18, SelectField field19, SelectField field20,
-            SelectField field21, SelectField field22) throws DataAccessException {
-        return context.fetchSingle(field1, field2, field3, field4, field5, field6, field7, field8, field9, field10,
-                field11, field12, field13, field14, field15, field16, field17, field18, field19, field20, field21,
-                field22);
-    }
-
-    @Override
-    public  Optional fetchOptional(Table table)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(table);
-    }
-
-    @Override
-    public  Optional fetchOptional(Table table, Condition condition)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(table, condition);
-    }
-
-    @Override
-    public  Optional fetchOptional(Table table, Condition... conditions)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(table, conditions);
-    }
-
-    @Override
-    public  Optional fetchOptional(Table table, Collection conditions)
-            throws DataAccessException, TooManyRowsException {
-        return context.fetchOptional(table, conditions);
-    }
-
-    @Override
-    public  R fetchAny(Table table) throws DataAccessException {
-        return context.fetchAny(table);
-    }
-
-    @Override
-    public  R fetchAny(Table table, Condition condition) throws DataAccessException {
-        return context.fetchAny(table, condition);
-    }
-
-    @Override
-    public  R fetchAny(Table table, Condition... conditions) throws DataAccessException {
-        return context.fetchAny(table, conditions);
-    }
-
-    @Override
-    public  R fetchAny(Table table, Collection conditions)
-            throws DataAccessException {
-        return context.fetchAny(table, conditions);
-    }
-
-    @Override
-    public  Cursor fetchLazy(Table table) throws DataAccessException {
-        return context.fetchLazy(table);
-    }
-
-    @Override
-    public  Cursor fetchLazy(Table table, Condition condition) throws DataAccessException {
-        return context.fetchLazy(table, condition);
-    }
-
-    @Override
-    public  Cursor fetchLazy(Table table, Condition... conditions) throws DataAccessException {
-        return context.fetchLazy(table, conditions);
-    }
-
-    @Override
-    public  Cursor fetchLazy(Table table, Collection conditions)
-            throws DataAccessException {
-        return context.fetchLazy(table, conditions);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Table table) {
-        return context.fetchAsync(table);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Table table, Condition condition) {
-        return context.fetchAsync(table, condition);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Table table, Condition... condition) {
-        return context.fetchAsync(table, condition);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Table table,
-            Collection condition) {
-        return context.fetchAsync(table, condition);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Executor executor, Table table) {
-        return context.fetchAsync(executor, table);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Executor executor, Table table,
-            Condition condition) {
-        return context.fetchAsync(executor, table, condition);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Executor executor, Table table,
-            Condition... conditions) {
-        return context.fetchAsync(executor, table, conditions);
-    }
-
-    @Override
-    public  CompletionStage> fetchAsync(Executor executor, Table table,
-            Collection conditions) {
-        return context.fetchAsync(executor, table, conditions);
-    }
-
-    @Override
-    public  Stream fetchStream(Table table) throws DataAccessException {
-        return context.fetchStream(table);
+    public  InsertValuesStep10 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10));
     }
 
     @Override
-    public  Stream fetchStream(Table table, Condition condition) throws DataAccessException {
-        return context.fetchStream(table, condition);
+    public  InsertValuesStep11 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11));
     }
 
     @Override
-    public  Stream fetchStream(Table table, Condition... conditions)
-            throws DataAccessException {
-        return context.fetchStream(table, conditions);
+    public  InsertValuesStep12 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12));
     }
 
     @Override
-    public  Stream fetchStream(Table table, Collection conditions)
-            throws DataAccessException {
-        return context.fetchStream(table, conditions);
+    public  InsertValuesStep13 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13));
     }
 
     @Override
-    public int executeInsert(TableRecord record) throws DataAccessException {
-        return context.executeInsert(record);
+    public  InsertValuesStep14 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14));
     }
 
     @Override
-    public int executeUpdate(UpdatableRecord record) throws DataAccessException {
-        return context.executeUpdate(record);
+    public  InsertValuesStep15 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15));
     }
 
     @Override
-    public int executeUpdate(TableRecord record, Condition condition) throws DataAccessException {
-        return context.executeUpdate(record, condition);
+    public  InsertValuesStep16 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16));
     }
 
     @Override
-    public int executeDelete(UpdatableRecord record) throws DataAccessException {
-        return context.executeDelete(record);
+    public  InsertValuesStep17 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17));
     }
 
     @Override
-    public int executeDelete(TableRecord record, Condition condition) throws DataAccessException {
-        return context.executeDelete(record, condition);
+    public  InsertValuesStep18 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17, Field field18) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18));
     }
 
     @Override
-    public Configuration configuration() {
-        return context.configuration();
+    public  InsertValuesStep19 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17, Field field18, Field field19) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19));
     }
 
     @Override
-    public DSLContext dsl() {
-        return context.dsl();
+    public  InsertValuesStep20 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17, Field field18, Field field19, Field field20) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20));
     }
 
     @Override
-    public Settings settings() {
-        return context.settings();
+    public  InsertValuesStep21 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17, Field field18, Field field19, Field field20,
+            Field field21) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
+                field21));
     }
 
     @Override
-    public SQLDialect dialect() {
-        return context.dialect();
+    public  InsertValuesStep22 insertInto(
+            Table into, Field field1, Field field2, Field field3, Field field4, Field field5,
+            Field field6, Field field7, Field field8, Field field9, Field field10,
+            Field field11, Field field12, Field field13, Field field14, Field field15,
+            Field field16, Field field17, Field field18, Field field19, Field field20,
+            Field field21, Field field22) {
+        return time(super.insertInto(into, field1, field2, field3, field4, field5, field6, field7, field8, field9,
+                field10, field11, field12, field13, field14, field15, field16, field17, field18, field19, field20,
+                field21, field22));
     }
 
     @Override
-    public SQLDialect family() {
-        return context.family();
+    public  InsertValuesStepN insertInto(Table into, Field... fields) {
+        return time(super.insertInto(into, fields));
     }
 
     @Override
-    public Map data() {
-        return context.data();
+    public  InsertValuesStepN insertInto(Table into, Collection> fields) {
+        return time(super.insertInto(into, fields));
     }
 
     @Override
-    public Object data(Object key) {
-        return context.data(key);
+    public  UpdateQuery updateQuery(Table table) {
+        return time(super.updateQuery(table));
     }
 
     @Override
-    public Object data(Object key, Object value) {
-        return context.data(key, value);
+    public  UpdateSetFirstStep update(Table table) {
+        return timeCoercable(super.update(table));
     }
 
 }
diff --git a/samples/micrometer-samples-jooq/build.gradle b/samples/micrometer-samples-jooq/build.gradle
new file mode 100644
index 0000000000..1f91a77145
--- /dev/null
+++ b/samples/micrometer-samples-jooq/build.gradle
@@ -0,0 +1,30 @@
+plugins {
+    id 'java'
+}
+
+// Latest open source jOOQ versions only support Java 17+
+// skip this module when building with jdk <17
+if (!javaLanguageVersion.canCompileOrRun(17)) {
+    project.tasks.configureEach { task -> task.enabled = false }
+}
+
+dependencies {
+    implementation project(":micrometer-core")
+    implementation libs.jooqLatest
+
+    testImplementation libs.junitJupiter
+    testImplementation libs.assertj
+    testImplementation libs.mockitoCore
+
+    testRuntimeOnly libs.h2
+}
+
+java {
+    targetCompatibility = JavaVersion.VERSION_17
+}
+
+compileJava {
+    sourceCompatibility = JavaVersion.VERSION_17
+    targetCompatibility = JavaVersion.VERSION_17
+    options.release = 17
+}
diff --git a/samples/micrometer-samples-jooq/src/test/java/io/micrometer/samples/jooq/MetricsDSLContextTest.java b/samples/micrometer-samples-jooq/src/test/java/io/micrometer/samples/jooq/MetricsDSLContextTest.java
new file mode 100644
index 0000000000..0807e2f1cc
--- /dev/null
+++ b/samples/micrometer-samples-jooq/src/test/java/io/micrometer/samples/jooq/MetricsDSLContextTest.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2020 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.micrometer.samples.jooq;
+
+import io.micrometer.common.lang.NonNull;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.Tags;
+import io.micrometer.core.instrument.binder.db.MetricsDSLContext;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
+import org.jooq.*;
+import org.jooq.Record;
+import org.jooq.exception.DataAccessException;
+import org.jooq.impl.DSL;
+import org.jooq.impl.DefaultConfiguration;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import static io.micrometer.core.instrument.binder.db.MetricsDSLContext.withMetrics;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
+import static org.jooq.impl.DSL.*;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Tests for {@link MetricsDSLContext} run on the latest version of jOOQ.
+ *
+ * @author Jon Schneider
+ * @author Johnny Lim
+ */
+class MetricsDSLContextTest {
+
+    private MeterRegistry meterRegistry = new SimpleMeterRegistry();
+
+    @Test
+    void timeFluentSelectStatement() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            Result result = jooq.tag("name", "selectAllAuthors").select(asterisk()).from("author").fetch();
+            assertThat(result.size()).isEqualTo(1);
+
+            // intentionally don't time this operation to demonstrate that the
+            // configuration hasn't been globally mutated
+            jooq.select(asterisk()).from("author").fetch();
+
+            assertThat(
+                    meterRegistry.get("jooq.query").tag("name", "selectAllAuthors").tag("type", "read").timer().count())
+                .isEqualTo(1);
+        }
+    }
+
+    @Test
+    void timeParsedSelectStatement() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:parsedSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+            jooq.tag("name", "selectAllAuthors").fetch("SELECT * FROM author");
+
+            // intentionally don't time this operation to demonstrate that the
+            // configuration hasn't been globally mutated
+            jooq.fetch("SELECT * FROM author");
+
+            assertThat(
+                    meterRegistry.get("jooq.query").tag("name", "selectAllAuthors").tag("type", "read").timer().count())
+                .isEqualTo(1);
+        }
+    }
+
+    @Test
+    void timeFaultySelectStatement() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:faultySelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+            jooq.tag("name", "selectAllAuthors").fetch("SELECT non_existent_field FROM author");
+
+            failBecauseExceptionWasNotThrown(DataAccessException.class);
+        }
+        catch (DataAccessException ignored) {
+        }
+
+        assertThat(meterRegistry.get("jooq.query")
+            .tag("name", "selectAllAuthors")
+            .tag("type", "read")
+            .tag("exception", "c42 syntax error or access rule violation")
+            .tag("exception.subclass", "none")
+            .timer()
+            .count()).isEqualTo(1);
+    }
+
+    @Test
+    void timeExecute() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            jooq.tag("name", "selectAllAuthors").execute("SELECT * FROM author");
+
+            assertThat(meterRegistry.get("jooq.query").tag("name", "selectAllAuthors").timer().count()).isEqualTo(1);
+        }
+    }
+
+    @Test
+    void timeInsert() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            jooq.tag("name", "insertAuthor").insertInto(table("author")).values("2", "jon", "schneider").execute();
+
+            assertThat(meterRegistry.get("jooq.query").tag("name", "insertAuthor").timer().count()).isEqualTo(1);
+        }
+    }
+
+    @Test
+    void timeUpdate() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            jooq.tag("name", "updateAuthor").update(table("author")).set(field("author.first_name"), "jon").execute();
+
+            assertThat(meterRegistry.get("jooq.query").tag("name", "updateAuthor").timer().count()).isEqualTo(1);
+        }
+    }
+
+    @Test
+    void timingBatchQueriesNotSupported() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            jooq.tag("name", "batch")
+                .batch(jooq.insertInto(table("author")).values("3", "jon", "schneider"),
+                        jooq.insertInto(table("author")).values("4", "jon", "schneider"))
+                .execute();
+
+            assertThat(meterRegistry.find("jooq.query").timer()).isNull();
+        }
+    }
+
+    /**
+     * Ensures that we are holding tag state in a way that doesn't conflict between two
+     * unexecuted queries.
+     */
+    @Test
+    void timeTwoStatementsCreatedBeforeEitherIsExecuted() throws SQLException {
+        try (Connection conn = DriverManager.getConnection("jdbc:h2:mem:fluentSelect")) {
+            MetricsDSLContext jooq = createDatabase(conn);
+
+            SelectJoinStep select1 = jooq.tag("name", "selectAllAuthors").select(asterisk()).from("author");
+            SelectJoinStep> select2 = jooq.tag("name", "selectAllAuthors2")
+                .select(field("first_name"))
+                .from("author");
+
+            select1.fetch();
+            select2.fetch();
+            select1.fetch();
+
+            assertThat(meterRegistry.get("jooq.query").tag("name", "selectAllAuthors").timer().count()).isEqualTo(2);
+
+            assertThat(meterRegistry.get("jooq.query").tag("name", "selectAllAuthors2").timer().count()).isEqualTo(1);
+        }
+    }
+
+    @Test
+    void userExecuteListenerShouldBePreserved() {
+        ExecuteListener userExecuteListener = mock(ExecuteListener.class);
+        Configuration configuration = new DefaultConfiguration().set(() -> userExecuteListener);
+
+        MetricsDSLContext jooq = withMetrics(using(configuration), meterRegistry, Tags.empty());
+
+        ExecuteListenerProvider[] executeListenerProviders = jooq.configuration().executeListenerProviders();
+        assertThat(executeListenerProviders).hasSize(2);
+        assertThat(executeListenerProviders[0].provide()).isSameAs(userExecuteListener);
+        assertThat(executeListenerProviders[1].provide().getClass().getCanonicalName())
+            .isEqualTo("io.micrometer.core.instrument.binder.db.JooqExecuteListener");
+
+        SelectSelectStep select = jooq.tag("name", "selectAllAuthors").select(asterisk());
+        executeListenerProviders = select.configuration().executeListenerProviders();
+        assertThat(executeListenerProviders).hasSize(2);
+        assertThat(executeListenerProviders[0].provide()).isSameAs(userExecuteListener);
+        assertThat(executeListenerProviders[1].provide().getClass().getCanonicalName())
+            .isEqualTo("io.micrometer.core.instrument.binder.db.JooqExecuteListener");
+    }
+
+    @NonNull
+    private MetricsDSLContext createDatabase(Connection conn) {
+        Configuration configuration = new DefaultConfiguration().set(conn).set(SQLDialect.H2);
+
+        MetricsDSLContext jooq = MetricsDSLContext.withMetrics(DSL.using(configuration), meterRegistry, Tags.empty());
+
+        jooq.execute("CREATE TABLE author (" + "  id int NOT NULL," + "  first_name varchar(255) DEFAULT NULL,"
+                + "  last_name varchar(255) DEFAULT NULL," + "  PRIMARY KEY (id)" + ")");
+
+        jooq.execute("INSERT INTO author VALUES(1, 'jon', 'schneider')");
+        return jooq;
+    }
+
+}
diff --git a/settings.gradle b/settings.gradle
index 1b6f881eb0..fb3afa156a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -25,7 +25,7 @@ gradleEnterprise {
 
 include 'micrometer-commons', 'micrometer-core', 'micrometer-observation'
 
-['core', 'boot2', 'boot2-reactive', 'spring-integration', 'hazelcast', 'hazelcast3', 'javalin', 'jersey3', 'jetty12', 'kotlin'].each { sample ->
+['core', 'boot2', 'boot2-reactive', 'spring-integration', 'hazelcast', 'hazelcast3', 'javalin', 'jersey3', 'jetty12', 'jooq', 'kotlin'].each { sample ->
     include "micrometer-samples-$sample"
     project(":micrometer-samples-$sample").projectDir = new File(rootProject.projectDir, "samples/micrometer-samples-$sample")
 }

From ce60b13ed0d0ac7470032a2439bf4205b98aecd7 Mon Sep 17 00:00:00 2001
From: John Burns 
Date: Thu, 8 Feb 2024 21:32:10 -0600
Subject: [PATCH 63/73] remove metrics when shutting down
 JettyServerThreadPoolMetrics/InstrumentedQueuedThreadPool (#4003)

Jetty servers may be stopped and started. The metrics from stopped servers will not be updated anymore, so they can be removed. Keeps track of registered metrics in JettyServerThreadPoolMetrics and removes them on `close`.

fixes gh-4000
---
 .../jetty/InstrumentedQueuedThreadPool.java   |  16 ++-
 .../jetty/JettyServerThreadPoolMetrics.java   |  53 +++++++--
 .../InstrumentedQueuedThreadPoolTest.java     | 103 ++++++++++++++++++
 .../JettyServerThreadPoolMetricsTest.java     |  15 ++-
 4 files changed, 174 insertions(+), 13 deletions(-)
 create mode 100644 micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPoolTest.java

diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPool.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPool.java
index 46674388d6..a55148f5a9 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPool.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPool.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 VMware, Inc.
+ * Copyright 2024 VMware, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
  */
 package io.micrometer.core.instrument.binder.jetty;
 
+import io.micrometer.common.lang.Nullable;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -39,6 +40,9 @@ public class InstrumentedQueuedThreadPool extends QueuedThreadPool {
 
     private final Iterable tags;
 
+    @Nullable
+    private JettyServerThreadPoolMetrics threadPoolMetrics;
+
     /**
      * Default values for the instrumented thread pool.
      * @param registry where metrics will be bound
@@ -112,8 +116,16 @@ public InstrumentedQueuedThreadPool(MeterRegistry registry, Iterable tags,
     @Override
     protected void doStart() throws Exception {
         super.doStart();
-        JettyServerThreadPoolMetrics threadPoolMetrics = new JettyServerThreadPoolMetrics(this, tags);
+        threadPoolMetrics = new JettyServerThreadPoolMetrics(this, tags);
         threadPoolMetrics.bindTo(registry);
     }
 
+    @Override
+    protected void doStop() throws Exception {
+        if (threadPoolMetrics != null) {
+            threadPoolMetrics.close();
+        }
+        super.doStop();
+    }
+
 }
diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetrics.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetrics.java
index 9178e2864f..f844ffa1d9 100644
--- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetrics.java
+++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetrics.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 VMware, Inc.
+ * Copyright 2024 VMware, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,7 +15,9 @@
  */
 package io.micrometer.core.instrument.binder.jetty;
 
+import io.micrometer.common.lang.Nullable;
 import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.Meter;
 import io.micrometer.core.instrument.MeterRegistry;
 import io.micrometer.core.instrument.Tag;
 import io.micrometer.core.instrument.binder.MeterBinder;
@@ -23,6 +25,9 @@
 import org.eclipse.jetty.util.thread.ThreadPool;
 import org.eclipse.jetty.util.thread.ThreadPool.SizedThreadPool;
 
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
 /**
  * {@link MeterBinder} for Jetty {@link ThreadPool}.
  * 

@@ -41,12 +46,29 @@ * @since 1.1.0 * @see InstrumentedQueuedThreadPool */ -public class JettyServerThreadPoolMetrics implements MeterBinder { +public class JettyServerThreadPoolMetrics implements MeterBinder, AutoCloseable { private final ThreadPool threadPool; private final Iterable tags; + private final String MIN = "jetty.threads.config.min"; + + private final String MAX = "jetty.threads.config.max"; + + private final String BUSY = "jetty.threads.busy"; + + private final String JOBS = "jetty.threads.jobs"; + + private final String CURRENT = "jetty.threads.current"; + + private final String IDLE = "jetty.threads.idle"; + + private final Set registeredMeterIds = ConcurrentHashMap.newKeySet(); + + @Nullable + private MeterRegistry registry; + public JettyServerThreadPoolMetrics(ThreadPool threadPool, Iterable tags) { this.threadPool = threadPool; this.tags = tags; @@ -54,36 +76,51 @@ public JettyServerThreadPoolMetrics(ThreadPool threadPool, Iterable tags) { @Override public void bindTo(MeterRegistry registry) { + this.registry = registry; if (threadPool instanceof SizedThreadPool) { SizedThreadPool sizedThreadPool = (SizedThreadPool) threadPool; - Gauge.builder("jetty.threads.config.min", sizedThreadPool, SizedThreadPool::getMinThreads) + Gauge minGauge = Gauge.builder(MIN, sizedThreadPool, SizedThreadPool::getMinThreads) .description("The minimum number of threads in the pool") .tags(tags) .register(registry); - Gauge.builder("jetty.threads.config.max", sizedThreadPool, SizedThreadPool::getMaxThreads) + registeredMeterIds.add(minGauge.getId()); + Gauge maxGauge = Gauge.builder(MAX, sizedThreadPool, SizedThreadPool::getMaxThreads) .description("The maximum number of threads in the pool") .tags(tags) .register(registry); + registeredMeterIds.add(maxGauge.getId()); if (threadPool instanceof QueuedThreadPool) { QueuedThreadPool queuedThreadPool = (QueuedThreadPool) threadPool; - Gauge.builder("jetty.threads.busy", queuedThreadPool, QueuedThreadPool::getBusyThreads) + Gauge busyGauge = Gauge.builder(BUSY, queuedThreadPool, QueuedThreadPool::getBusyThreads) .description("The number of busy threads in the pool") .tags(tags) .register(registry); - Gauge.builder("jetty.threads.jobs", queuedThreadPool, QueuedThreadPool::getQueueSize) + registeredMeterIds.add(busyGauge.getId()); + Gauge jobsGauge = Gauge.builder(JOBS, queuedThreadPool, QueuedThreadPool::getQueueSize) .description("Number of jobs queued waiting for a thread") .tags(tags) .register(registry); + registeredMeterIds.add(jobsGauge.getId()); } } - Gauge.builder("jetty.threads.current", threadPool, ThreadPool::getThreads) + Gauge currentGauge = Gauge.builder(CURRENT, threadPool, ThreadPool::getThreads) .description("The total number of threads in the pool") .tags(tags) .register(registry); - Gauge.builder("jetty.threads.idle", threadPool, ThreadPool::getIdleThreads) + registeredMeterIds.add(currentGauge.getId()); + Gauge idleGauge = Gauge.builder(IDLE, threadPool, ThreadPool::getIdleThreads) .description("The number of idle threads in the pool") .tags(tags) .register(registry); + registeredMeterIds.add(idleGauge.getId()); + } + + @Override + public void close() throws Exception { + if (registry != null) { + registeredMeterIds.forEach(registry::remove); + registeredMeterIds.clear(); + } } } diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPoolTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPoolTest.java new file mode 100644 index 0000000000..98fad13490 --- /dev/null +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/InstrumentedQueuedThreadPoolTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.core.instrument.binder.jetty; + +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import org.assertj.core.api.ListAssert; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.function.BiFunction; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +class InstrumentedQueuedThreadPoolTest { + + @Test + void registeredMetricsShouldBeRemovedAfterClosingTheBinder() throws Exception { + MeterRegistry meterRegistry = new SimpleMeterRegistry(); + QueuedThreadPool instance = new InstrumentedQueuedThreadPool(meterRegistry, + Collections.singletonList(Tag.of("pool", "1"))); + + instance.start(); + + assertThatMetricsExist(meterRegistry); + + Gauge jobsGauge = meterRegistry.find("jetty.threads.jobs").gauge(); + + assertThat(jobsGauge.getId().getTags()).as("ensure metrics have thread pool tag").contains(Tag.of("pool", "1")); + + instance.stop(); + + assertThatMetricsDontExist(meterRegistry); + } + + @Test + void shouldOnlyRemoveMetricsBelongingToItsOwnPool() throws Exception { + MeterRegistry meterRegistry = new SimpleMeterRegistry(); + QueuedThreadPool pool1 = new InstrumentedQueuedThreadPool(meterRegistry, + Collections.singletonList(Tag.of("pool", "1"))); + + QueuedThreadPool pool2 = new InstrumentedQueuedThreadPool(meterRegistry, + Collections.singletonList(Tag.of("pool", "2"))); + + pool1.start(); + pool2.start(); + + assertThatMetricsExist(meterRegistry); + + assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "1").gauge()).as("pool 1 gauge exists") + .isNotNull(); + assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "2").gauge()).as("pool 2 gauge exists") + .isNotNull(); + + pool1.stop(); + + assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "1").gauge()) + .as("pool 1 gauge no longer exists") + .isNull(); + assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "2").gauge()).as("pool 2 gauge exists") + .isNotNull(); + + pool2.stop(); + + assertThatMetricsDontExist(meterRegistry); + } + + private void assertThatMetricsExist(MeterRegistry meterRegistry) { + assertThatMetrics(meterRegistry, (l, a) -> a.containsAll(l)); + } + + private void assertThatMetricsDontExist(MeterRegistry meterRegistry) { + assertThatMetrics(meterRegistry, (l, a) -> a.doesNotContainAnyElementsOf(l)); + } + + private void assertThatMetrics(MeterRegistry meterRegistry, + BiFunction, ListAssert, ListAssert> assertFunction) { + assertFunction.apply( + Arrays.asList("jetty.threads.jobs", "jetty.threads.busy", "jetty.threads.idle", + "jetty.threads.config.max", "jetty.threads.config.min", "jetty.threads.current"), + assertThat( + meterRegistry.getMeters().stream().map(m -> m.getId().getName()).collect(Collectors.toList()))); + } + +} diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetricsTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetricsTest.java index bd3e3bdf3b..51e7059d39 100644 --- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetricsTest.java +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jetty/JettyServerThreadPoolMetricsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 VMware, Inc. + * Copyright 2024 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,18 +40,23 @@ class JettyServerThreadPoolMetricsTest { private Server server; + private JettyServerThreadPoolMetrics threadPoolMetrics; + @BeforeEach void setup() throws Exception { registry = new SimpleMeterRegistry(SimpleConfig.DEFAULT, new MockClock()); Iterable tags = Collections.singletonList(Tag.of("id", "0")); - QueuedThreadPool threadPool = new InstrumentedQueuedThreadPool(registry, tags); + QueuedThreadPool threadPool = new QueuedThreadPool(); + threadPool.setMinThreads(32); threadPool.setMaxThreads(100); server = new Server(threadPool); ServerConnector connector = new ServerConnector(server); server.setConnectors(new Connector[] { connector }); server.start(); + threadPoolMetrics = new JettyServerThreadPoolMetrics(threadPool, tags); + threadPoolMetrics.bindTo(registry); } @AfterEach @@ -60,11 +65,15 @@ void teardown() throws Exception { } @Test - void threadMetrics() { + void threadMetrics() throws Exception { assertThat(registry.get("jetty.threads.config.min").gauge().value()).isEqualTo(32.0); assertThat(registry.get("jetty.threads.config.max").gauge().value()).isEqualTo(100.0); assertThat(registry.get("jetty.threads.current").gauge().value()).isNotEqualTo(0.0); assertThat(registry.get("jetty.threads.busy").gauge().value()).isGreaterThanOrEqualTo(0.0); + + threadPoolMetrics.close(); + + assertThat(registry.getMeters()).as("Meters are removed after close").isEmpty(); } } From eb64b3904d58b448ec9bb8032cb5b44680621c3b Mon Sep 17 00:00:00 2001 From: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> Date: Fri, 9 Feb 2024 14:08:54 +0900 Subject: [PATCH 64/73] Remove 1.10.x target dependabot config Branch protections have been enabled for `1.10.x` as the source has been moved to the private commercial repository. This ensures dependabot doesn't open pull requests for `1.10.x` since we won't be able to merge them anyway. --- .github/dependabot.yml | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index aefa1c774d..827320aeab 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -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: From b5847d07a52476631b6d5766726806e2752d1be3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:22:02 +0900 Subject: [PATCH 65/73] Bump testcontainers from 1.19.4 to 1.19.5 (#4735) Bumps `testcontainers` from 1.19.4 to 1.19.5. Updates `org.testcontainers:junit-jupiter` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:kafka` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:postgresql` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:mongodb` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) Updates `org.testcontainers:testcontainers` from 1.19.4 to 1.19.5 - [Release notes](https://github.com/testcontainers/testcontainers-java/releases) - [Changelog](https://github.com/testcontainers/testcontainers-java/blob/main/CHANGELOG.md) - [Commits](https://github.com/testcontainers/testcontainers-java/compare/1.19.4...1.19.5) --- updated-dependencies: - dependency-name: org.testcontainers:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:kafka dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:postgresql dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:mongodb dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.testcontainers:testcontainers dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 860c494150..a0fe71f58a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -68,7 +68,7 @@ slf4j = "1.7.36" spectator-atlas = "1.3.10" spring = "5.3.31" spring-javaformat = "0.0.41" -testcontainers = "1.19.4" +testcontainers = "1.19.5" tomcat = "8.5.98" wavefront = "3.0.4" # pinned to avoid issues with shaded slf4j version - see gh-3414 From 0c7a43f01c1503c0d7a8e470981aad334901b8fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:22:40 +0900 Subject: [PATCH 66/73] Bump com.amazonaws:aws-java-sdk-cloudwatch from 1.12.650 to 1.12.655 (#4739) Bumps [com.amazonaws:aws-java-sdk-cloudwatch](https://github.com/aws/aws-sdk-java) from 1.12.650 to 1.12.655. - [Changelog](https://github.com/aws/aws-sdk-java/blob/master/CHANGELOG.md) - [Commits](https://github.com/aws/aws-sdk-java/compare/1.12.650...1.12.655) --- updated-dependencies: - dependency-name: com.amazonaws:aws-java-sdk-cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a0fe71f58a..1ad29a086b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ aspectjweaver = "1.8.14" assertj = "3.24.2" awaitility = "4.2.0" # legacy SDK -aws-cloudwatch = "1.12.650" +aws-cloudwatch = "1.12.655" caffeine = "2.9.3" cloudwatch2 = "2.18.41" colt = "1.2.0" From 96a3ff840d2177aeff4f3b85f645cd89d7ab2c08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 16:48:33 +0900 Subject: [PATCH 67/73] Bump org.junit.platform:junit-platform-launcher from 1.10.1 to 1.10.2 (#4738) Bumps [org.junit.platform:junit-platform-launcher](https://github.com/junit-team/junit5) from 1.10.1 to 1.10.2. - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/commits) --- updated-dependencies: - dependency-name: org.junit.platform:junit-platform-launcher dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b88f8e7f51..8add670eec 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ jooq = "3.14.16" jsr107 = "1.1.1" jsr305 = "3.0.2" junit = "5.10.1" -junit-platform = "1.10.1" +junit-platform = "1.10.2" kafka = "2.8.2" kafka-junit = "4.2.10" latency-utils = "2.0.3" From 26c25185edab854e17fb84b8015c022f734d5842 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:02:03 +0900 Subject: [PATCH 68/73] Bump junit from 5.10.1 to 5.10.2 (#4737) Bumps `junit` from 5.10.1 to 5.10.2. Updates `org.junit:junit-bom` from 5.10.1 to 5.10.2 - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.10.2) Updates `org.junit.jupiter:junit-jupiter` from 5.10.1 to 5.10.2 - [Release notes](https://github.com/junit-team/junit5/releases) - [Commits](https://github.com/junit-team/junit5/compare/r5.10.1...r5.10.2) --- updated-dependencies: - dependency-name: org.junit:junit-bom dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: org.junit.jupiter:junit-jupiter dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8add670eec..fb12d68112 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -49,7 +49,7 @@ jmh = "1.37" jooq = "3.14.16" jsr107 = "1.1.1" jsr305 = "3.0.2" -junit = "5.10.1" +junit = "5.10.2" junit-platform = "1.10.2" kafka = "2.8.2" kafka-junit = "4.2.10" From 559bd23ac725b9abcfa536cfb1748c86c207f645 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:24:09 +0900 Subject: [PATCH 69/73] Bump software.amazon.awssdk:cloudwatch from 2.23.17 to 2.23.21 (#4740) Bumps software.amazon.awssdk:cloudwatch from 2.23.17 to 2.23.21. --- updated-dependencies: - dependency-name: software.amazon.awssdk:cloudwatch dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f9c13142da..96611b44bc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ awaitility = "4.2.0" # legacy SDK aws-cloudwatch = "1.12.655" caffeine = "2.9.3" -cloudwatch2 = "2.23.17" +cloudwatch2 = "2.23.21" colt = "1.2.0" dagger = "2.50" dropwizard-metrics = "4.2.25" From 27b4e0bf476014a5b4aa390201ae68aa774d5fac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:24:32 +0900 Subject: [PATCH 70/73] Bump org.assertj:assertj-core from 3.25.2 to 3.25.3 (#4744) Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.25.2 to 3.25.3. - [Release notes](https://github.com/assertj/assertj/releases) - [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.25.2...assertj-build-3.25.3) --- updated-dependencies: - dependency-name: org.assertj:assertj-core dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 96611b44bc..c6c737bbe3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ application-insights = "2.6.4" archunit = "1.2.1" asmForPlugins = "7.3.1" aspectjweaver = "1.9.21" -assertj = "3.25.2" +assertj = "3.25.3" awaitility = "4.2.0" # legacy SDK aws-cloudwatch = "1.12.655" From cbf8797f9f50a6e63189cd3d5c44d2eda67caa07 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:24:52 +0900 Subject: [PATCH 71/73] Bump com.google.auth:google-auth-library-oauth2-http (#4732) Bumps com.google.auth:google-auth-library-oauth2-http from 1.22.0 to 1.23.0. --- updated-dependencies: - dependency-name: com.google.auth:google-auth-library-oauth2-http dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c6c737bbe3..3423880927 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -112,7 +112,7 @@ felixScr = "org.apache.felix:org.apache.felix.scr:2.2.10" gmetric4j = { module = "info.ganglia.gmetric4j:gmetric4j", version.ref = "gmetric4j" } googleCloudLibrariesBom = { module = "com.google.cloud:libraries-bom", version = "26.31.0" } googleCloudMonitoring = { module = "com.google.cloud:google-cloud-monitoring", version.ref = "google-cloud-monitoring" } -googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.22.0"} +googleOauth2Http = { module = "com.google.auth:google-auth-library-oauth2-http", version = "1.23.0"} grpcApi = { module = "io.grpc:grpc-api", version.ref = "grpc" } grpcCore = { module = "io.grpc:grpc-core", version.ref = "grpc" } grpcInprocess = { module = "io.grpc:grpc-inprocess", version.ref = "grpc" } From f704fc3ad7dd90d8a4bd4e2b8047620d400547d6 Mon Sep 17 00:00:00 2001 From: Jonatan Ivanov Date: Mon, 12 Feb 2024 11:59:53 -0800 Subject: [PATCH 72/73] Use latest release (1.1.1) of context-propagation Closes gh-4745 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fb12d68112..00b3cd25b1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -92,7 +92,7 @@ caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version.ref = "c cloudwatch2 = { module = "software.amazon.awssdk:cloudwatch", version.ref = "cloudwatch2" } colt = { module = "colt:colt", version.ref = "colt" } commonsPool2 = "org.apache.commons:commons-pool2:2.12.0" -contextPropagation = { module = "io.micrometer:context-propagation", version = "1.1.0" } +contextPropagation = { module = "io.micrometer:context-propagation", version = "1.1.1" } dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" } daggerCompiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } dropwizardMetricsCore = { module = "io.dropwizard.metrics:metrics-core", version.ref = "dropwizard-metrics" } From c69180d6819b1fdd278807e87eccdc9c0e16d333 Mon Sep 17 00:00:00 2001 From: Andrei Nevedomskii Date: Tue, 13 Feb 2024 08:52:38 +0100 Subject: [PATCH 73/73] Publish a separate module with jdk11 classes (#4728) Introduces a new module named micrometer-java11 with a copy of the classes for the JDK http client instrumentation currently in micrometer-core as multi-release jar classes for Java 11. This also deprecates the corresponding classes in micrometer-core and directs users to the new module. Fixes gh-3577 --------- Co-authored-by: Tommy Ludwig <8924140+shakuzen@users.noreply.github.com> --- build.gradle | 2 +- ...efaultHttpClientObservationConvention.java | 2 + .../binder/jdk/HttpClientContext.java | 2 + .../jdk/HttpClientObservationConvention.java | 2 + .../HttpClientObservationDocumentation.java | 1 + .../binder/jdk/MicrometerHttpClient.java | 2 + .../instrument/binder/jdk/package-info.java | 4 +- .../binder/jdk/MicrometerHttpClientTests.java | 1 + micrometer-java11/build.gradle | 24 ++ ...efaultHttpClientObservationConvention.java | 84 +++++ .../binder/jdk/HttpClientContext.java | 45 +++ .../jdk/HttpClientObservationConvention.java | 36 +++ .../HttpClientObservationDocumentation.java | 86 +++++ .../binder/jdk/MicrometerHttpClient.java | 306 ++++++++++++++++++ .../instrument/binder/jdk/package-info.java | 25 ++ .../binder/jdk/MicrometerHttpClientTests.java | 111 +++++++ micrometer-test/build.gradle | 63 ++-- ...imingInstrumentationVerificationTests.java | 2 +- settings.gradle | 1 + 19 files changed, 758 insertions(+), 41 deletions(-) create mode 100644 micrometer-java11/build.gradle create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/DefaultHttpClientObservationConvention.java create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientContext.java create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationConvention.java create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationDocumentation.java create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClient.java create mode 100644 micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/package-info.java create mode 100644 micrometer-java11/src/test/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClientTests.java rename micrometer-test/src/test/java11/io/micrometer/{core => java11}/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java (98%) diff --git a/build.gradle b/build.gradle index a1ad76f66e..a74e1497a0 100644 --- a/build.gradle +++ b/build.gradle @@ -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' diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/DefaultHttpClientObservationConvention.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/DefaultHttpClientObservationConvention.java index 91e4b9871c..44622f0564 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/DefaultHttpClientObservationConvention.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/DefaultHttpClientObservationConvention.java @@ -29,7 +29,9 @@ * * @author Marcin Grzejszczak * @since 1.10.0 + * @deprecated since 1.13.0 use the same class in the micrometer-java11 module instead */ +@Deprecated public class DefaultHttpClientObservationConvention implements HttpClientObservationConvention { /** diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientContext.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientContext.java index 3ddf09dc6b..284fc119b0 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientContext.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientContext.java @@ -28,7 +28,9 @@ * * @author Marcin Grzejszczak * @since 1.10.0 + * @deprecated since 1.13.0 use the same class in the micrometer-java11 module instead */ +@Deprecated public class HttpClientContext extends RequestReplySenderContext> { private final Function uriMapper; diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationConvention.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationConvention.java index c25ae6b6ea..466da1af75 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationConvention.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationConvention.java @@ -25,7 +25,9 @@ * * @author Marcin Grzejszczak * @since 1.10.0 + * @deprecated since 1.13.0 use the same class in the micrometer-java11 module instead */ +@Deprecated public interface HttpClientObservationConvention extends ObservationConvention { @Override diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationDocumentation.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationDocumentation.java index e5c313c153..f306d754e8 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationDocumentation.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/HttpClientObservationDocumentation.java @@ -20,6 +20,7 @@ import io.micrometer.observation.ObservationConvention; import io.micrometer.observation.docs.ObservationDocumentation; +@SuppressWarnings("deprecation") enum HttpClientObservationDocumentation implements ObservationDocumentation { /** diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClient.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClient.java index 37c7a7a1cb..178ea68cb7 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClient.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClient.java @@ -50,7 +50,9 @@ * * @author Marcin Grzejszczak * @since 1.10.0 + * @deprecated since 1.13.0 use the same class in the micrometer-java11 module instead */ +@Deprecated public class MicrometerHttpClient extends HttpClient { /** diff --git a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/package-info.java b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/package-info.java index 3120b9f8bf..d0e7dab6a7 100644 --- a/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/package-info.java +++ b/micrometer-core/src/main/java11/io/micrometer/core/instrument/binder/jdk/package-info.java @@ -15,8 +15,10 @@ */ /** - * Instrumentation of JDK classes. + * Instrumentation of JDK classes. Deprecated since 1.13.0 use the micrometer-java11 + * module instead. */ +// Note we can't use the @deprecated JavaDoc tag due to compiler bug JDK-8160601 @NonNullApi @NonNullFields package io.micrometer.core.instrument.binder.jdk; diff --git a/micrometer-core/src/test/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClientTests.java b/micrometer-core/src/test/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClientTests.java index d3a69a978b..5a61d08ec3 100644 --- a/micrometer-core/src/test/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClientTests.java +++ b/micrometer-core/src/test/java11/io/micrometer/core/instrument/binder/jdk/MicrometerHttpClientTests.java @@ -37,6 +37,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.*; import static org.assertj.core.api.BDDAssertions.then; +@SuppressWarnings("deprecation") @WireMockTest class MicrometerHttpClientTests { diff --git a/micrometer-java11/build.gradle b/micrometer-java11/build.gradle new file mode 100644 index 0000000000..b947fb18eb --- /dev/null +++ b/micrometer-java11/build.gradle @@ -0,0 +1,24 @@ +description 'Micrometer core classes that require Java 11' + +dependencies { + api project(":micrometer-core") + + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.assertj:assertj-core' +} + +java { + targetCompatibility = 11 +} + +tasks.withType(JavaCompile).configureEach { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + options.release = 11 +} + +dependencies { + testImplementation 'ru.lanwen.wiremock:wiremock-junit5' + testImplementation 'com.github.tomakehurst:wiremock-jre8-standalone' + testImplementation project(":micrometer-observation-test") +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/DefaultHttpClientObservationConvention.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/DefaultHttpClientObservationConvention.java new file mode 100644 index 0000000000..93e4963782 --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/DefaultHttpClientObservationConvention.java @@ -0,0 +1,84 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.common.KeyValues; +import io.micrometer.common.lang.NonNull; +import io.micrometer.common.lang.Nullable; +import io.micrometer.core.instrument.binder.http.Outcome; + +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.function.Function; + +/** + * Default implementation of {@link HttpClientObservationConvention}. + * + * @author Marcin Grzejszczak + * @since 1.13.0 + */ +public class DefaultHttpClientObservationConvention implements HttpClientObservationConvention { + + /** + * Instance of this {@link DefaultHttpClientObservationConvention}. + */ + public static DefaultHttpClientObservationConvention INSTANCE = new DefaultHttpClientObservationConvention(); + + @Override + public KeyValues getLowCardinalityKeyValues(HttpClientContext context) { + if (context.getCarrier() == null) { + return KeyValues.empty(); + } + HttpRequest httpRequest = context.getCarrier().build(); + KeyValues keyValues = KeyValues.of( + HttpClientObservationDocumentation.LowCardinalityKeys.METHOD.withValue(httpRequest.method()), + HttpClientObservationDocumentation.LowCardinalityKeys.URI + .withValue(getUriTag(httpRequest, context.getResponse(), context.getUriMapper()))); + if (context.getResponse() != null) { + keyValues = keyValues + .and(HttpClientObservationDocumentation.LowCardinalityKeys.STATUS + .withValue(String.valueOf(context.getResponse().statusCode()))) + .and(HttpClientObservationDocumentation.LowCardinalityKeys.OUTCOME + .withValue(Outcome.forStatus(context.getResponse().statusCode()).name())); + } + return keyValues; + } + + String getUriTag(@Nullable HttpRequest request, @Nullable HttpResponse httpResponse, + Function uriMapper) { + if (request == null) { + return null; + } + return httpResponse != null && (httpResponse.statusCode() == 404 || httpResponse.statusCode() == 301) + ? "NOT_FOUND" : uriMapper.apply(request); + } + + @Override + @NonNull + public String getName() { + return "http.client.requests"; + } + + @Nullable + @Override + public String getContextualName(HttpClientContext context) { + if (context.getCarrier() == null) { + return null; + } + return "HTTP " + context.getCarrier().build().method(); + } + +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientContext.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientContext.java new file mode 100644 index 0000000000..40ed4471ee --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientContext.java @@ -0,0 +1,45 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.observation.transport.RequestReplySenderContext; + +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.Objects; +import java.util.function.Function; + +/** + * A {@link RequestReplySenderContext} for an {@link HttpClient}. + * + * @author Marcin Grzejszczak + * @since 1.13.0 + */ +public class HttpClientContext extends RequestReplySenderContext> { + + private final Function uriMapper; + + public HttpClientContext(Function uriMapper) { + super((carrier, key, value) -> Objects.requireNonNull(carrier).header(key, value)); + this.uriMapper = uriMapper; + } + + public Function getUriMapper() { + return uriMapper; + } + +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationConvention.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationConvention.java new file mode 100644 index 0000000000..d3c4d87fe6 --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationConvention.java @@ -0,0 +1,36 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationConvention; + +import java.net.http.HttpClient; + +/** + * An {@link ObservationConvention} for an {@link HttpClient}. + * + * @author Marcin Grzejszczak + * @since 1.13.0 + */ +public interface HttpClientObservationConvention extends ObservationConvention { + + @Override + default boolean supportsContext(Observation.Context context) { + return context instanceof HttpClientContext; + } + +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationDocumentation.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationDocumentation.java new file mode 100644 index 0000000000..77ebef4be6 --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/HttpClientObservationDocumentation.java @@ -0,0 +1,86 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.common.docs.KeyName; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationConvention; +import io.micrometer.observation.docs.ObservationDocumentation; + +enum HttpClientObservationDocumentation implements ObservationDocumentation { + + /** + * Observation when an HTTP call is being made. + */ + HTTP_CALL { + @Override + public Class> getDefaultConvention() { + return DefaultHttpClientObservationConvention.class; + } + + @Override + public KeyName[] getLowCardinalityKeyNames() { + return LowCardinalityKeys.values(); + } + + }; + + enum LowCardinalityKeys implements KeyName { + + /** + * HTTP Method. + */ + METHOD { + @Override + public String asString() { + return "method"; + } + }, + + /** + * HTTP Status. + */ + STATUS { + @Override + public String asString() { + return "status"; + } + }, + + /** + * Key name for outcome. + * @since 1.11.0 + */ + OUTCOME { + @Override + public String asString() { + return "outcome"; + } + }, + + /** + * HTTP URI. + */ + URI { + @Override + public String asString() { + return "uri"; + } + } + + } + +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClient.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClient.java new file mode 100644 index 0000000000..00f38721c9 --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClient.java @@ -0,0 +1,306 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.common.lang.Nullable; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.binder.http.Outcome; +import io.micrometer.core.instrument.observation.ObservationOrTimerCompatibleInstrumentation; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationRegistry; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieHandler; +import java.net.ProxySelector; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Function; + +/** + * Delegates to an {@link HttpClient} while instrumenting with Micrometer any HTTP calls + * made. Example setup:

{@code
+ * HttpClient observedClient = MicrometerHttpClient.instrumentationBuilder(HttpClient.newHttpClient(), meterRegistry).build();
+ * }
+ * + * Inspired by interceptable-http-client. + * + * @author Marcin Grzejszczak + * @since 1.13.0 + */ +public class MicrometerHttpClient extends HttpClient { + + /** + * Header name for URI pattern. + */ + public static final String URI_PATTERN_HEADER = "URI_PATTERN"; + + private final MeterRegistry meterRegistry; + + private final HttpClient client; + + @Nullable + private final ObservationRegistry observationRegistry; + + @Nullable + private final HttpClientObservationConvention customObservationConvention; + + private final Function uriMapper; + + private MicrometerHttpClient(MeterRegistry meterRegistry, HttpClient client, + @Nullable ObservationRegistry observationRegistry, + @Nullable HttpClientObservationConvention customObservationConvention, + Function uriMapper) { + this.meterRegistry = meterRegistry; + this.client = client; + this.observationRegistry = observationRegistry; + this.customObservationConvention = customObservationConvention; + this.uriMapper = uriMapper; + } + + /** + * Builder for instrumentation of {@link HttpClient}. + * @param httpClient HttpClient to wrap + * @param meterRegistry meter registry + * @return builder + */ + public static InstrumentationBuilder instrumentationBuilder(HttpClient httpClient, MeterRegistry meterRegistry) { + return new InstrumentationBuilder(httpClient, meterRegistry); + } + + /** + * Builder for {@link MicrometerHttpClient}. + */ + public static class InstrumentationBuilder { + + private final HttpClient client; + + private final MeterRegistry meterRegistry; + + @Nullable + private ObservationRegistry observationRegistry; + + @Nullable + private HttpClientObservationConvention customObservationConvention; + + private Function uriMapper = request -> request.headers() + .firstValue(URI_PATTERN_HEADER) + .orElse("UNKNOWN"); + + /** + * Creates a new instance of {@link InstrumentationBuilder}. + * @param client client to wrap + * @param meterRegistry a {@link MeterRegistry} + */ + public InstrumentationBuilder(HttpClient client, MeterRegistry meterRegistry) { + this.client = client; + this.meterRegistry = meterRegistry; + } + + /** + * Set {@link ObservationRegistry} if you want to use {@link Observation}. + * @param observationRegistry observation registry + * @return this + */ + public InstrumentationBuilder observationRegistry(ObservationRegistry observationRegistry) { + this.observationRegistry = observationRegistry; + return this; + } + + /** + * When used with {@link ObservationRegistry}, it will override the default + * {@link HttpClientObservationConvention}. + * @param customObservationConvention custom observation convention + * @return this + */ + public InstrumentationBuilder customObservationConvention( + HttpClientObservationConvention customObservationConvention) { + this.customObservationConvention = customObservationConvention; + return this; + } + + /** + * Provides custom URI mapper mechanism. + * @param uriMapper URI mapper + * @return this + */ + public InstrumentationBuilder uriMapper(Function uriMapper) { + this.uriMapper = uriMapper; + return this; + } + + /** + * Builds a wrapped {@link HttpClient}. + * @return a wrapped {@link HttpClient} + */ + public HttpClient build() { + return new MicrometerHttpClient(this.meterRegistry, this.client, this.observationRegistry, + this.customObservationConvention, this.uriMapper); + } + + } + + @Override + public Optional cookieHandler() { + return client.cookieHandler(); + } + + @Override + public Optional connectTimeout() { + return client.connectTimeout(); + } + + @Override + public Redirect followRedirects() { + return client.followRedirects(); + } + + @Override + public Optional proxy() { + return client.proxy(); + } + + @Override + public SSLContext sslContext() { + return client.sslContext(); + } + + @Override + public SSLParameters sslParameters() { + return client.sslParameters(); + } + + @Override + public Optional authenticator() { + return client.authenticator(); + } + + @Override + public Version version() { + return client.version(); + } + + @Override + public Optional executor() { + return client.executor(); + } + + @Override + public HttpResponse send(HttpRequest httpRequest, HttpResponse.BodyHandler bodyHandler) + throws IOException, InterruptedException { + HttpRequest.Builder httpRequestBuilder = decorate(httpRequest); + ObservationOrTimerCompatibleInstrumentation instrumentation = observationOrTimer( + httpRequestBuilder); + HttpRequest request = httpRequestBuilder.build(); + HttpResponse response = null; + try { + response = client.send(request, bodyHandler); + instrumentation.setResponse(response); + return response; + } + catch (IOException ex) { + instrumentation.setThrowable(ex); + throw ex; + } + finally { + stopObservationOrTimer(instrumentation, request, response); + } + } + + private void stopObservationOrTimer( + ObservationOrTimerCompatibleInstrumentation instrumentation, HttpRequest request, + @Nullable HttpResponse res) { + instrumentation.stop(DefaultHttpClientObservationConvention.INSTANCE.getName(), "Timer for JDK's HttpClient", + () -> { + Tags tags = Tags.of(HttpClientObservationDocumentation.LowCardinalityKeys.METHOD.asString(), + request.method(), HttpClientObservationDocumentation.LowCardinalityKeys.URI.asString(), + DefaultHttpClientObservationConvention.INSTANCE.getUriTag(request, res, uriMapper)); + if (res != null) { + tags = tags + .and(Tag.of(HttpClientObservationDocumentation.LowCardinalityKeys.STATUS.asString(), + String.valueOf(res.statusCode()))) + .and(Tag.of(HttpClientObservationDocumentation.LowCardinalityKeys.OUTCOME.asString(), + Outcome.forStatus(res.statusCode()).name())); + } + return tags; + }); + } + + private ObservationOrTimerCompatibleInstrumentation observationOrTimer( + HttpRequest.Builder httpRequestBuilder) { + return ObservationOrTimerCompatibleInstrumentation.start(this.meterRegistry, this.observationRegistry, () -> { + HttpClientContext context = new HttpClientContext(this.uriMapper); + context.setCarrier(httpRequestBuilder); + return context; + }, this.customObservationConvention, DefaultHttpClientObservationConvention.INSTANCE); + } + + @Override + public CompletableFuture> sendAsync(HttpRequest httpRequest, + HttpResponse.BodyHandler bodyHandler) { + return sendAsync(httpRequest, bodyHandler, null); + } + + @Override + public CompletableFuture> sendAsync(HttpRequest httpRequest, + HttpResponse.BodyHandler bodyHandler, @Nullable HttpResponse.PushPromiseHandler pushPromiseHandler) { + HttpRequest.Builder httpRequestBuilder = decorate(httpRequest); + ObservationOrTimerCompatibleInstrumentation instrumentation = observationOrTimer( + httpRequestBuilder); + HttpRequest request = httpRequestBuilder.build(); + return client.sendAsync(request, bodyHandler, pushPromiseHandler).handle((response, throwable) -> { + if (throwable != null) { + instrumentation.setThrowable(throwable); + } + instrumentation.setResponse(response); + stopObservationOrTimer(instrumentation, request, response); + return response; + }); + } + + private HttpRequest.Builder decorate(HttpRequest httpRequest) { + HttpRequest.Builder builder = HttpRequest.newBuilder(httpRequest.uri()); + builder.expectContinue(httpRequest.expectContinue()); + httpRequest.headers().map().forEach((key, values) -> values.forEach(value -> builder.header(key, value))); + httpRequest.bodyPublisher() + .ifPresentOrElse(publisher -> builder.method(httpRequest.method(), publisher), () -> { + switch (httpRequest.method()) { + case "GET": + builder.GET(); + break; + case "DELETE": + builder.DELETE(); + break; + default: + throw new IllegalStateException(httpRequest.method()); + } + }); + httpRequest.timeout().ifPresent(builder::timeout); + httpRequest.version().ifPresent(builder::version); + return builder; + } + +} diff --git a/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/package-info.java b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/package-info.java new file mode 100644 index 0000000000..f50aa57223 --- /dev/null +++ b/micrometer-java11/src/main/java/io/micrometer/java11/instrument/binder/jdk/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Instrumentation of JDK classes. + */ +@NonNullApi +@NonNullFields +package io.micrometer.java11.instrument.binder.jdk; + +import io.micrometer.common.lang.NonNullApi; +import io.micrometer.common.lang.NonNullFields; diff --git a/micrometer-java11/src/test/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClientTests.java b/micrometer-java11/src/test/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClientTests.java new file mode 100644 index 0000000000..df509ea4cc --- /dev/null +++ b/micrometer-java11/src/test/java/io/micrometer/java11/instrument/binder/jdk/MicrometerHttpClientTests.java @@ -0,0 +1,111 @@ +/* + * Copyright 2024 VMware, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.micrometer.java11.instrument.binder.jdk; + +import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo; +import com.github.tomakehurst.wiremock.junit5.WireMockTest; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import io.micrometer.observation.Observation; +import io.micrometer.observation.ObservationHandler; +import io.micrometer.observation.ObservationRegistry; +import io.micrometer.observation.tck.TestObservationRegistry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.assertj.core.api.BDDAssertions.then; + +@WireMockTest +class MicrometerHttpClientTests { + + MeterRegistry meterRegistry = new SimpleMeterRegistry(); + + HttpClient httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(2)).build(); + + @BeforeEach + void setup() { + stubFor(any(urlEqualTo("/metrics")).willReturn(ok().withBody("body"))); + } + + @Test + void shouldInstrumentHttpClientWithObservation(WireMockRuntimeInfo wmInfo) + throws IOException, InterruptedException { + ObservationRegistry observationRegistry = TestObservationRegistry.create(); + observationRegistry.observationConfig() + .observationHandler(new ObservationHandler.AllMatchingCompositeObservationHandler(headerSettingHandler(), + new DefaultMeterObservationHandler(meterRegistry))); + + HttpRequest request = HttpRequest.newBuilder() + .GET() + .uri(URI.create(wmInfo.getHttpBaseUrl() + "/metrics")) + .build(); + + HttpClient observedClient = MicrometerHttpClient.instrumentationBuilder(httpClient, meterRegistry) + .observationRegistry(observationRegistry) + .build(); + observedClient.send(request, HttpResponse.BodyHandlers.ofString()); + + verify(anyRequestedFor(urlEqualTo("/metrics")).withHeader("foo", equalTo("bar"))); + thenMeterRegistryContainsHttpClientTags(); + } + + @Test + void shouldInstrumentHttpClientWithTimer(WireMockRuntimeInfo wmInfo) throws IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .GET() + .uri(URI.create(wmInfo.getHttpBaseUrl() + "/metrics")) + .build(); + + HttpClient observedClient = MicrometerHttpClient.instrumentationBuilder(httpClient, meterRegistry).build(); + observedClient.send(request, HttpResponse.BodyHandlers.ofString()); + + thenMeterRegistryContainsHttpClientTags(); + } + + private void thenMeterRegistryContainsHttpClientTags() { + then(meterRegistry.find("http.client.requests") + .tag("method", "GET") + .tag("status", "200") + .tag("outcome", "SUCCESS") + .tag("uri", "UNKNOWN") + .timer()).isNotNull(); + } + + private ObservationHandler headerSettingHandler() { + return new ObservationHandler<>() { + @Override + public boolean supportsContext(Observation.Context context) { + return context instanceof HttpClientContext; + } + + @Override + public void onStart(HttpClientContext context) { + HttpRequest.Builder carrier = context.getCarrier(); + context.getSetter().set(carrier, "foo", "bar"); + } + }; + } + +} diff --git a/micrometer-test/build.gradle b/micrometer-test/build.gradle index 8741265d61..d67fa7d4e3 100644 --- a/micrometer-test/build.gradle +++ b/micrometer-test/build.gradle @@ -1,19 +1,32 @@ -plugins { - id 'me.champeau.mrjar' version "0.1.1" -} - description 'Test compatibility kit for extensions of Micrometer' -multiRelease { - targetVersions 8, 11 +testing { + suites { + java11Test(JvmTestSuite) { + test { + useJUnitJupiter() + } + sources { + java { + srcDirs = ['src/test/java11'] + } + } + dependencies { + implementation project() + implementation project(':micrometer-java11') + } + + } + } } -// Otherwise java11 tests will not see java11 code -sourceSets { - java11Test { - compileClasspath += sourceSets.java11.output - runtimeClasspath += sourceSets.java11.output - } +compileJava11TestJava { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +check { + dependsOn(testing.suites.java11Test) } dependencies { @@ -21,8 +34,6 @@ dependencies { api project(':micrometer-observation') api project(':micrometer-observation-test') - java11TestImplementation project(":micrometer-core").sourceSets.java11.output - api 'org.assertj:assertj-core' api 'org.junit.jupiter:junit-jupiter' @@ -30,7 +41,6 @@ dependencies { api 'ru.lanwen.wiremock:wiremock-junit5' api 'com.github.tomakehurst:wiremock-jre8-standalone' - java11TestImplementation 'com.github.tomakehurst:wiremock-jre8-standalone' api 'org.mockito:mockito-core' implementation 'org.awaitility:awaitility' @@ -62,26 +72,3 @@ dependencies { // necessary for Jersey test framework testRuntimeOnly 'org.glassfish.jersey.inject:jersey-hk2' } - -java11Test { - // set heap size for the test JVM(s) - maxHeapSize = "1500m" - - useJUnitPlatform { - excludeTags 'docker' - } - - include { - it.getFile().getAbsolutePath().contains("java11Test") - } - - retry { - maxFailures = 5 - maxRetries = 3 - } -} - -compileJava11TestJava { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 -} diff --git a/micrometer-test/src/test/java11/io/micrometer/core/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java b/micrometer-test/src/test/java11/io/micrometer/java11/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java similarity index 98% rename from micrometer-test/src/test/java11/io/micrometer/core/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java rename to micrometer-test/src/test/java11/io/micrometer/java11/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java index b57c5c6723..a38624e4dc 100644 --- a/micrometer-test/src/test/java11/io/micrometer/core/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java +++ b/micrometer-test/src/test/java11/io/micrometer/java11/instrument/binder/jdk/JdkHttpClientTimingInstrumentationVerificationTests.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.micrometer.core.instrument.binder.jdk; +package io.micrometer.java11.instrument.binder.jdk; import io.micrometer.common.lang.Nullable; import io.micrometer.core.instrument.HttpClientTimingInstrumentationVerificationTests; diff --git a/settings.gradle b/settings.gradle index fb3afa156a..63bbe5ef99 100644 --- a/settings.gradle +++ b/settings.gradle @@ -44,6 +44,7 @@ include 'micrometer-test', 'micrometer-observation-test' include 'micrometer-bom' include 'micrometer-jakarta9' +include 'micrometer-java11' include 'micrometer-jetty11' include 'micrometer-osgi-test' include 'docs'