1

I am using Spring Modulith 2.0.0-M3 with Spring Boot 4.0.0-RC1. I have enabled zipkin tracing export and I can see that Spring Modulith adds a module.key and module.method tags to the trace.

I would like to expand this with two more high-cardinality tags: bean name and class name of the invoked methods. I can see that Modulith has a package-private implementation: DefaultModulithObservationConvention which seems like something I want to extend to add these 2 new tags.

I can copy/paste the default implementation and add these 2 tags, but that seems like a bad way to go and I cannot find any documentation for this.

Is there a better way to add these 2 tags?

2 Answers 2

1

Perhaps you use reflection to avoid copy/pasta?

@Bean
ModulithObservationConvention modulithObservationConvention() throws Exception {
    Class<?> type = Class.forName("org.springframework.modulith.observability.support.DefaultModulithObservationConvention");
    type.setAccessible(true);
    Constructor constructor = type.getDeclaredConstructor();
    constructor.setAccessible(true);
    ModulithObservationConvention delegate = (ModulithObservationConvention) constructor.newInstance();
    return new ModulithObservationConvention {
        @Override
        public boolean supportsContext(Observation.Context context) {
            return delegate.supportsContext(context);
        }

        @Override
        public String getName() {
            return delegate.getName();
        }

        @Override
        public KeyValues getLowCardinalityKeyValues(ModulithObservationContext context) {
            return delegate.getLowCardinalityKeyValues(context);
        }

        @Override
        public KeyValues getHighCardinalityKeyValues(ModulithObservationContext context) {
            KeyValues delegateKvs = delegate.getHighCardinalityKeyValues(context);
            KeyValues customKvs = KeyValues.of(
                "bean.name", "sample",
                "class.name", "foo.bar.Sample"
            );
            return KeyValues.concat(delegateKvs, customKvs); 
        }
    };
}
Sign up to request clarification or add additional context in comments.

2 Comments

That would work, but... :D I was hoping for a better support in the framework itself, but thanks for the suggestion, will keep it in mind
Its' a dirty hack for sure.... I won't tell if you don't :)
0

You can’t extend DefaultModulithObservationConvention, it’s package-private by design. The proper way is to define your own ObservationConvention<ModulithObservationContext> bean. Spring Modulith will automatically use it instead of the internal default.

@Bean
ObservationConvention<ModulithObservationContext> modulithObservationConvention() {
    return new ObservationConvention<>() {
        @Override
        public boolean supportsContext(Observation.Context context) {
            return context instanceof ModulithObservationContext;
        }

        @Override
        public String getName() {
            return "modulith.observation";
        }

        @Override
        public KeyValues getLowCardinalityKeyValues(ModulithObservationContext context) {
            return KeyValues.of(
                "module.key", context.getModule().getName(),
                "module.method", context.getMethod().getName()
            );
        }

        @Override
        public KeyValues getHighCardinalityKeyValues(ModulithObservationContext context) {
            return KeyValues.of(
                "bean.name", context.getBean().getClass().getSimpleName(),
                "class.name", context.getMethod().getDeclaringClass().getName()
            );
        }
    };
}

This replaces the built-in convention and lets you add any extra tags (bean.name, class.name, etc.) No internal classes need to be copied or modified.

In short: register your own ObservationConvention<ModulithObservationContext> bean : it safely overrides the default and gives you full control over trace tags.

2 Comments

Did you generate this answer?
This does not match the default implementation at all. There is no support for EventListener or the module.invocation-type tag and the module.method is a high-cardinality tag in that implementation. Of course I could do it like this and that is exactly what I said I DO NOT want to do in my question. I want to add 2 more tags without compromising on the default behavior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.