Skip to content

1.10 Migration Guide

Tommy Ludwig edited this page Nov 7, 2022 · 25 revisions

If you are upgrading from 1.9, there should not be breaking changes, and the main new API to check out is the Observation API, which has its own Observation API Migration Guide.

If you are upgrading from a 1.10 milestone or RC pre-release, the following guide describes how to adapt to the breaking changes that have happened in between those pre-releases.

Formerly released 2.0 milestones have been superseded by the 1.10 milestones.

Features that were being worked on in the 2.0 milestones will be released instead as 1.10 milestones and eventually a GA version. The 1.10.0-M1 milestone release follows the 2.0.0-M3 milestone.

Micrometer 1.10.0-RC1

  • [Breaking change] Observation factory methods that took a Context now take a Supplier<Context> instead. #3443

Anywhere you were passing a Context object to an Observation factory method (static methods on Observation and instance methods on ObservationDocumentation), the parameter type has been changed to Supplier<Context> to allow for lazy instantiation of the context. There are a few options available on how to migrate your code.

Lambda

Using a lambda is one way to adapt code to the new API. Before where you may have had code like the following:

JerseyContext jerseyContext = new JerseyContext(event);
Observation observation = JerseyObservationDocumentation.DEFAULT.start(this.jerseyObservationConvention,
                        new DefaultJerseyObservationConvention(this.metricName), jerseyContext, this.registry);

It can be updated to:

JerseyContext jerseyContext = new JerseyContext(event);
Observation observation = JerseyObservationDocumentation.DEFAULT.start(this.jerseyObservationConvention,
                        new DefaultJerseyObservationConvention(this.metricName), () -> jerseyContext, this.registry);

Method reference

If you do not need to pass arguments to the context, you can use a method reference to the constructor.

Observation.start("my.observation", Context::new, observationRegistry)

Make your context a supplier

Another alternative if you are using a custom context is to make it implement Supplier and then you can pass the context object as you were before. For example, an OkHttpContext class could be updated to the following.

public class OkHttpContext extends RequestReplySenderContext<Request.Builder, Response>
        implements Supplier<OkHttpContext> {
    // ...
    @Override
    public OkHttpContext get() {
        return this;
    }

And then used the same as before, such as:

Observation observation = OkHttpObservationDocumentation.DEFAULT.observation(this.observationConvention,
        new DefaultOkHttpObservationConvention(requestMetricName), okHttpContext, this.registry).start();
  • [Breaking change] DocumentedObservation is renamed to ObservationDocumentation. Likewise, DocumentedMeter and DocumentedSpan are renamed to MeterDocumentation and SpanDocumentation respectively. #3430
  • [Breaking change] We have updated Observation.Context#getParentObservation() to return ObservationView which provides readonly access to the parent observation context via getContextView() method. If you have an access to the parent observation context by getParentObservation().getContext(), update it to getParentObservation().getContextView(). (PR)
  • [Breaking change] We renamed DocumentedObservation#createNotStarted method to observation. (PR)
  • [Breaking change] We removed the varargs from ObservationRegistry#observationConvention if you want to register multiple conventions, please call the methods multiple times. (PR)
  • [Breaking change] We made ObservationRegistry#getObservationConvention and ObservationRegistry#isObservationEnabled package-private (the factory methods of Observation are using them, so users don't need to). (PR)
  • [Breaking change] We made Observation.getError return Throwable (instead of Optional<Throwable>), you need to do a null check or wrap it into an Optional. (PR)

Micrometer 1.10.0-M5

  • [Breaking change] We have moved the inner interfaces Observation.ObservationConvention and Observation.GlobalObservationConvention to io.micrometer.observation.ObservationConvention and io.micrometer.observation.GlobalObservationConvention respectively (PR)

Micrometer 1.10.0-M4

  • [Breaking change] We have removed the KeyValuesProviderAware and ObservationConventionAware interfaces. (PR). You can just remove their usage and remove the @Override annotation from the setter.
  • [Breaking change] We have removed all Http related abstractions and contexts (HTTP client and HTTP server). You should be using the RequestReplySenderContext and RequestReplyReceiverContext respectively. Also if you were using HttpRequest / HttpResponse and the like you can use directly the concrete HTTP request / response abstraction that you had to previously wrap in our version of it (PR)
  • [Breaking change] We have introduced the GlobalObservationConvention abstraction. You can set it on the ObservationRegistry#ObservationConfig. (PR). You can just remove their usage and remove the @Override annotation from the setter.
  • [Breaking change] TimerObservationHandler has been renamed to DefaultMeterObservationHandler which now registers a LongTaskTimer in addition to the Timer as well as a Counter for any Event on the Observation.

Micrometer 1.10.0-M3

  • Migrated the testing tools from io.micrometer.core.tck to io.micrometer.observation.tck package

  • KeyValuesProvider to ObserationConvention migration

    • Up till this 1.10.0-M3 the rule of thumb for instrumentations was as follows
      • Create a dedicated context for the given instrumentation (e.g. MongoContext)
      • Create an interface that extends the KeyValuesProvider with the concrete context type (e.g. interface MongoKeyValuesProvider extends KeyValuesProvider<MongoContext>)
      • Create a default implementation that sets default key values (e.g. class DefaultMongoKeyValuesProvider implements MongoKeyValuesProvider)
      • Your instrumentation would have a setter (you can use the KeyValuesProviderAware interface for your convenience) to allow the users to override the default KeyValuesProvider
    • With 1.10.0-M3 the flow looks the same but instead of plain KeyValuesProvider we're introducing a better concept which is the ObservationConvention<? extends Observation.Context>. That interface extends the KeyValuesProvider but also requires a default name.
    • The rationale is that we might have different naming convention that can be used locally (e.g. you want different name and tags for Mongo) or globally on the ObservationConfiguration (e.g. you want to rename all http client observations and their tags)

Micrometer 1.10.0-M1

micrometer-observation

There is a new module that contains an Observation API for instrumenting code. micrometer-core provides an integration that produces Timer metrics from this Observation instrumentation, and micrometer-tracing provides an integration to produce spans from that instrumentation. You can make your own integrations with this API, and instrument your code with this API.

See the Migration to the Observation API wiki.

micrometer-commons

We've moved TagKey and internal utilities from micrometer-observation to a new module called micrometer-commons. You'll need to update your imports like the following

Before : io.micrometer.observation.docs.TagKey, after: io.micrometer.common.docs.KeyName

More detailed migration guide

  • Classes
    • If you have a io.micrometer.common.Tags reference, change it to io.micrometer.common.KeyValues
    • If you have a io.micrometer.common.Tag reference, change it to io.micrometer.common.KeyValue
    • TagsProvider
      • After KeyValuesProvider
    • TagsProviderAware
      • After KeyValuesProviderAware
    • CompositeTagsProvider
      • After CompositeKeyValuesProvider
    • GlobalTagsProvider
      • After GlobalKeyValuesProvider
    • HttpTagsProvider
      • After HttpKeyValuesProvider
    • HttpTags
      • After HttpKeyValues
  • Methods
    • TagsProvider
      • Before Tags getLowCardinalityTags()
      • After KeyValues getLowCardinalityKeyValues()
    • Observation
      • lowCardinalityTag
        • After lowCardinalityKeyValue
      • highCardinalityTag
        • After highCardinalityKeyValue
      • tagsProvider
        • After keyValuesProvider
    • Observation.Context
      • addLowCardinalityTag
        • After addLowCardinalityKeyValue
      • addHighCardinalityTag
        • After addHighCardinalityKeyValue
      • addLowCardinalityTags
        • After addLowCardinalityKeyValues
      • addHighCardinalityTags
        • After addHighCardinalityKeyValues
      • getLowCardinalityTags
        • After getLowCardinalityKeyValues
      • getHighCardinalityTags
        • After getHighCardinalityKeyValues
      • getAllTags
        • After getAllKeyValues
    • TagsProviderAware
      • setTagsProvider
        • After setKeyValueProvider
    • CompositeTagsProvider
      • getTagsProviders
        • After getKeyValueProviders
    • ObservationRegistry.ObservationConfig
      • getTagsProviders
        • After getKeyValueProviders
      • tagsProvider
        • After keyValuesProvider
    • HttpTagsProvider
      • getLowCardinalityTags
        • After getLowCardinalityKeyValues
      • getHighCardinalityTags
        • After getHighCardinalityKeyValues
    • ObservationContextAssert
      • All methods containing Tag will be renamed to KeyValue
      • All methods containing Tags will be renamed to KeyValues

Up till Micrometer 2.0.0-M3

micrometer-tracing

See https://github.com/micrometer-metrics/tracing and the corresponding reference documentation.