[spring-projects/spring-boot]将用户定义的属性注入SdkTracerProvider

2024-05-08 193 views
7

用户定义的属性对于服务级别的标签很有用,例如 Jaeger UI 将其视为除了 span 标签之外的流程标签。 1

我们可以定义一个SdkTracerProviderBuilderCustomizer自定义属性,但这很繁琐,而且必须ResourceAttributes.SERVICE_NAME再次包含。

    @Bean
    SdkTracerProviderBuilderCustomizer sdkTracerProviderBuilderCustomizer(Environment environment) {
        return builder -> {
            String applicationName = environment.getProperty("spring.application.name", "application");
            Attributes attributes = Attributes.of(ResourceAttributes.SERVICE_NAME, applicationName,
                    AttributeKey.stringKey("java.version"), System.getProperty("java.version"));
            builder.setResource(Resource.create(attributes));
        };
    }

现在你可以这样做

    @Bean
    Attributes javaAttributes() {
        return Attributes.of(AttributeKey.stringKey("java.version"), System.getProperty("java.version"));
    }

回答

5

SdkTracerProviderBuilder定制器

SdkTracerProviderBuilder没有公开获取存在的方法Resource,这意味着你必须注入Environment和设置ResourceAttributes.SERVICE_NAME,这已经由 Spring Boot 完成了。

3

您的意思是添加默认方法吗SdkTracerProviderBuilderCustomizer

@FunctionalInterface
public interface SdkTracerProviderBuilderCustomizer {

    /**
     * Customize the given {@code builder}.
     * @param builder the builder to customize
     */
    void customize(SdkTracerProviderBuilder builder);

    /**
     * Customize the given {@code builder}.
     * @param builder the builder to customize
     */
    default void customize(AttributesBuilder builder) {

    }
}
        String applicationName = environment.getProperty("spring.application.name", DEFAULT_APPLICATION_NAME);
        AttributesBuilder attributesBuilder = Attributes.builder();
        attributesBuilder.put(ResourceAttributes.SERVICE_NAME, applicationName);
        customizers.orderedStream().forEach((customizer) -> customizer.customize(attributesBuilder));
        @Bean
        SdkTracerProviderBuilderCustomizer sdkTracerProviderBuilderCustomizer() {
            return new SdkTracerProviderBuilderCustomizer() {

                @Override
                public void customize(SdkTracerProviderBuilder builder) {

                }

                @Override
                public void customize(AttributesBuilder builder) {
                    builder.put(AttributeKey.stringKey("java.version"), System.getProperty("java.version"));
                }
            };
        }
2

是的,这就是我的意思。这与我们在org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer示例中所做的有些相似。

2

是的,这就是我的意思。这与我们在org.springframework.boot.autoconfigure.elasticsearch.RestClientBuilderCustomizer示例中所做的有些相似。

根据您的建议进行了更新。

0

@quaff 你检查过这个ObservationFilter组件了吗?有了它,您可以添加KeyValue将转换为 的 s Attributes。它有两个优点:

  • 它不依赖于 OTel,因此如果您想迁移会更容易
  • 您可以控制将属性设置为仅指标或指标和跨度(或您可以想出的其他东西)

我不认为它违背了此定制程序的目的(例如:如果您直接使用 OTel),但可能会有所帮助。

0

再次感谢 @quaff 的 PR 以及更新。不幸的是,我们今天讨论了这个问题并得出结论,我们没有足够的信息来在这一领域做出改变。目前还不清楚使用定制是应该在级别Attributes还是在Resource级别。后者将允许指定架构 URL。合并两个Resource实例,其中一个具有 URL,另一个不会导致 URL 被删除。如果我们允许在级别上进行自定义,这会使提供的默认属性变得复杂Resource。目前,我们认为重复设置属性的代码SERVICE_NAME是最不坏的选择。如果出现所需定制级别的清晰模式,我们可以在将来重新考虑这一点。

9

@quaff 你检查过这个ObservationFilter组件了吗?有了它,您可以添加KeyValue将转换为 的 s Attributes。它有两个优点:

  • 它不依赖于 OTel,因此如果您想迁移会更容易
  • 您可以控制将属性设置为仅指标或指标和跨度(或您可以想出的其他东西)

我不认为它违背了此定制程序的目的(例如:如果您直接使用 OTel),但可能会有所帮助。

@jonatan-ivanovObservationFilter有效,您能给我一个提示,如何控制将属性设置为仅指标或指标和跨度吗?

2

默认情况下,仪表处理程序将使用.lowCardinalityKeyValuelow- 和 ,跟踪处理程序将使用 low- 和.highCardinalityKeyValue。所以:

  • 两者:添加.lowCardinalityKeyValue
  • 仅跨度:添加.highCardinalityKeyValue
  • 仅指标:默认情况下不存在,您可以同时执行这两种操作并使用 a 删除标签,SpanFilter也可以覆盖DefaultTracingHandler

使信息仅可用于指标的用例是什么?

7

默认情况下,仪表处理程序将使用.lowCardinalityKeyValuelow- 和 ,跟踪处理程序将使用 low- 和.highCardinalityKeyValue。所以:

  • 两者:添加.lowCardinalityKeyValue
  • 仅跨度:添加.highCardinalityKeyValue
  • 仅指标:默认情况下不存在,您可以同时执行这两种操作并使用 a 删除标签,SpanFilter也可以覆盖DefaultTracingHandler

使信息仅可用于指标的用例是什么?

感谢您的详细阐述,我想使用仅MeterRegistryCustomizer配置指标。如果我理解正确,即使它的基数很低,例如? ,commonTags也必须添加仅跨度。.highCardinalityKeyValuejava.version

0

是的,Micrometer 不知道标签的基数,因此您可以添加低基数标签highCardinalityKeyValue(反之亦然,但如果您将高基数标签附加为lowCardinalityKeyValue,您的应用程序和指标后端将不喜欢高基数数据)。

0

@quaff 你检查过这个ObservationFilter组件了吗?有了它,您可以添加KeyValue将转换为 的 s Attributes。它有两个优点:

  • 它不依赖于 OTel,因此如果您想迁移会更容易
  • 您可以控制将属性设置为仅指标或指标和跨度(或您可以想出的其他东西)

我不认为它违背了此定制程序的目的(例如:如果您直接使用 OTel),但可能会有所帮助。

@jonatan-ivanov 添加的标签ObservationFilter是跨度级别而不是进程级别,不是我想要的行为。

4

我不确定我是否理解跨度与流程级别标签的含义。

3

我不确定我是否理解跨度与流程级别标签的含义。

您可以查看本线程开头的屏幕截图,Jaeger UI 会将进程级别标签与跨度级别标签分开,进程级别标签commonTags类似于MeterRegistry

1

您是否知道如果您使用 Zipkin 格式,Jaeger 的行为是否相同?如果是这样,我认为您“只”需要关心标签的命​​名,它们应该成为“过程”属性。我不知道这是否是现有功能(应该是)或命名约定是什么(如果有)。

9

您是否知道如果您使用 Zipkin 格式,Jaeger 的行为是否相同?如果是这样,我认为您“只”需要关心标签的命​​名,它们应该成为“过程”属性。我不知道这是否是现有功能(应该是)或命名约定是什么(如果有)。

@jonatan-ivanov 这是定义 OpenTelemetry 和 Jaeger 之间的映射的地方。 https://www.jaegertracing.io/docs/1.45/architecture/#terminology 您可以看到 Jaeger Process 标签来自 OpenTelemetry 资源,Span 标签来自 OpenTelemetry 属性映射。

6

您是否知道如果您使用 Zipkin 格式,Jaeger 的行为是否相同?如果是这样,我认为您“只”需要关心标签的命​​名,它们应该成为“过程”属性。我不知道这是否是现有功能(应该是)或命名约定是什么(如果有)。

我不认为这与命名有关,自 OpenTracing 以来,jaeger 就有跟踪器级别标签

https://github.com/jaegertracing/jaeger-client-java/blob/master/jaeger-core/src/main/java/io/jaegertracing/internal/JaegerTracer.java#L554

8

@amithkumarg

这是定义 OpenTelemetry 和 Jaeger 之间的映射的地方。

请再次检查我的问题,我问的是 Zipkin 格式而不是 OpenTelemetry。 OTel 对于 Jaeger 来说更容易处理,因为它有 s 的概念Resource,而 Zipkin 没有。

@quaff

我不认为这与命名有关,自 OpenTracing 以来,jaeger 就有跟踪器级别标签

没关系,我问的是 Zipkin,因为它没有任何东西,只有跨度上的标签。如果 Jaeger 实现了处理此问题(我希望他们做到了),那么您应该能够利用此行为。

3

@amithkumarg

这是定义 OpenTelemetry 和 Jaeger 之间的映射的地方。

请再次检查我的问题,我问的是 Zipkin 格式而不是 OpenTelemetry。 OTel 对于 Jaeger 来说更容易处理,因为它有 s 的概念Resource,而 Zipkin 没有。

@quaff

我不认为这与命名有关,自 OpenTracing 以来,jaeger 就有跟踪器级别标签

没关系,我问的是 Zipkin,因为它没有任何东西,只有跨度上的标签。如果 Jaeger 实现了处理此问题(我希望他们做到了),那么您应该能够利用此行为。

抱歉,我对 Zipkin 不熟悉,但我可以验证 Jaeger 使用ResourceSdkTracerProvider进程级标签,这就是我打开此 PR 的原因。我正在转向定制SdkTracerProvider,只是让你知道这ObservationFilter并不令人满意。