diff --git a/docs/sdk/configuration.md b/docs/sdk/configuration.md index 421dfb0a6..7c7ce7690 100644 --- a/docs/sdk/configuration.md +++ b/docs/sdk/configuration.md @@ -50,7 +50,17 @@ If not specified, SDK defaults the service name to `unknown_service:scala`. | otel.resource.attributes | OTEL\\_RESOURCE\\_ATTRIBUTES | Specify resource attributes in the following format: `key1=val1,key2=val2,key3=val3`. | | otel.service.name | OTEL\\_SERVICE\\_NAME | Specify logical service name. Takes precedence over `service.name` defined with `otel.resource.attributes`. | | otel.experimental.resource.disabled-keys | OTEL\\_EXPERIMENTAL\\_RESOURCE\\_DISABLED\\_KEYS | Specify resource attribute keys that are filtered. | -| otel.otel4s.resource.detectors | OTEL\\_OTEL4S\\_RESOURCE\\_DETECTORS | Specify resource detectors to use. Defaults to `host,os,process_runtime`. | +| otel.otel4s.resource.detectors.enabled | OTEL\\_OTEL4S\\_RESOURCE\\_DETECTORS\\_ENABLED | Specify resource detectors to use. Defaults to `host,os,process,process_runtime`. | +| otel.otel4s.resource.detectors.disabled | OTEL\\_OTEL4S\\_RESOURCE\\_DETECTORS\\_DISABLED | Specify resource detectors to disable. | + +### Telemetry resource detectors + +`TelemetryResourceDetector` adds environment-aware attributes to the telemetry resource. +For example, `HostDetector` will add `host.arch` and `host.name` attributes. +By default, the following resource detectors are enabled: `host`, `os`, `process`, `process_runtime`. + +To disable all detectors, set `-Dotel.otel4s.resource.detectors.enabled=none`. +To disable some detectors, use `-Dotel.otel4s.resource.detectors.disabled=host,os,process`. ## Metrics diff --git a/sdk/all/src/test/scala/org/typelevel/otel4s/sdk/OpenTelemetrySdkSuite.scala b/sdk/all/src/test/scala/org/typelevel/otel4s/sdk/OpenTelemetrySdkSuite.scala index f6ceabd54..9e9974c54 100644 --- a/sdk/all/src/test/scala/org/typelevel/otel4s/sdk/OpenTelemetrySdkSuite.scala +++ b/sdk/all/src/test/scala/org/typelevel/otel4s/sdk/OpenTelemetrySdkSuite.scala @@ -69,7 +69,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("withConfig - use the given config") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "none" ) @@ -125,7 +125,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addTracerProviderCustomizer - customize tracer provider") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "none" ) @@ -147,7 +147,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addResourceCustomizer - customize a resource") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "none" ) @@ -176,7 +176,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addSpanExporterConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "custom-1,custom-2", "otel.metrics.exporter" -> "none" ) @@ -217,7 +217,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addSamplerConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "none", "otel.traces.sampler" -> "custom-sampler", @@ -252,7 +252,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addTextMapPropagatorConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "none", "otel.propagators" -> "tracecontext,custom-1,custom-2,baggage", @@ -297,7 +297,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addMeterProviderCustomizer - customize meter provider") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "console" ) @@ -331,7 +331,7 @@ class OpenTelemetrySdkSuite extends CatsEffectSuite { test("addMeterExporterConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.metrics.exporter" -> "custom-1,custom-2" ) diff --git a/sdk/common/shared/src/main/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigure.scala b/sdk/common/shared/src/main/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigure.scala index 9b0b3c803..f11bf9dab 100644 --- a/sdk/common/shared/src/main/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigure.scala +++ b/sdk/common/shared/src/main/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigure.scala @@ -40,7 +40,8 @@ import java.nio.charset.StandardCharsets * | otel.resource.attributes | OTEL_RESOURCE_ATTRIBUTES | Specify resource attributes in the following format: key1=val1,key2=val2,key3=val3 | * | otel.service.name | OTEL_SERVICE_NAME | Specify logical service name. Takes precedence over `service.name` defined with `otel.resource.attributes` | * | otel.experimental.resource.disabled-keys | OTEL_EXPERIMENTAL_RESOURCE_DISABLED_KEYS | Specify resource attribute keys that are filtered. | - * | otel.otel4s.resource.detectors | OTEL_OTEL4S_RESOURCE_DETECTORS | Specify resource detectors to use. Defaults to `host,os,process,process_runtime`. | + * | otel.otel4s.resource.detectors.enabled | OTEL_OTEL4S_RESOURCE_DETECTORS_ENABLED | Specify resource detectors to use. Defaults to `host,os,process,process_runtime`. | + * | otel.otel4s.resource.detectors.disabled | OTEL_OTEL4S_RESOURCE_DETECTORS_DISABLED | Specify resource detectors to disable. | * }}} * * @see @@ -75,7 +76,12 @@ private final class TelemetryResourceAutoConfigure[F[_]: Sync: Console]( Sync[F].fromEither(fromEnv(config, disabledKeys)) ) - detectedResource <- fromDetectors(config, disabledKeys) + disabledDetectors <- Resource.eval( + Sync[F].fromEither( + config.getOrElse(ConfigKeys.DetectorsDisabled, Set.empty[String]) + ) + ) + detectedResource <- fromDetectors(config, disabledKeys, disabledDetectors) } yield detectedResource.fold(envResource)(_.mergeUnsafe(envResource)) private def fromEnv( @@ -122,7 +128,8 @@ private final class TelemetryResourceAutoConfigure[F[_]: Sync: Console]( private def fromDetectors( config: Config, - disabledKeys: Set[String] + disabledKeys: Set[String], + disabledDetectors: Set[String] ): Resource[F, Option[TelemetryResource]] = { def removeDisabledAttributes(resource: TelemetryResource) = @@ -148,18 +155,18 @@ private final class TelemetryResourceAutoConfigure[F[_]: Sync: Console]( case None => Sync[F].raiseError( ConfigurationError.unrecognized( - ConfigKeys.Detectors.name, + ConfigKeys.DetectorsEnabled.name, name, detectors.map(_.name) + Const.NoneDetector ) ) } - config.getOrElse(ConfigKeys.Detectors, Defaults.Detectors) match { + config.getOrElse(ConfigKeys.DetectorsEnabled, Defaults.Detectors) match { case Right(n) if n.contains(Const.NoneDetector) && n.sizeIs > 1 => Resource.raiseError( ConfigurationError( - s"[${ConfigKeys.Detectors}] contains '${Const.NoneDetector}' along with other detectors" + s"[${ConfigKeys.DetectorsEnabled}] contains '${Const.NoneDetector}' along with other detectors" ): Throwable ) @@ -168,7 +175,9 @@ private final class TelemetryResourceAutoConfigure[F[_]: Sync: Console]( case Right(names) => Resource.eval( - names.toList + names + .diff(disabledDetectors) + .toList .flatTraverse(detector => detect(detector).map(_.toList)) .map(resources => resources.reduceOption(_ mergeUnsafe _)) ) @@ -192,10 +201,19 @@ private[sdk] object TelemetryResourceAutoConfigure { val ServiceName: Config.Key[String] = Config.Key("otel.service.name") - val Detectors: Config.Key[Set[String]] = - Config.Key("otel.otel4s.resource.detectors") + val DetectorsEnabled: Config.Key[Set[String]] = + Config.Key("otel.otel4s.resource.detectors.enabled") + + val DetectorsDisabled: Config.Key[Set[String]] = + Config.Key("otel.otel4s.resource.detectors.disabled") - val All: Set[Config.Key[_]] = Set(DisabledKeys, Attributes, ServiceName) + val All: Set[Config.Key[_]] = Set( + DisabledKeys, + Attributes, + ServiceName, + DetectorsEnabled, + DetectorsDisabled + ) } private object Const { @@ -220,7 +238,8 @@ private[sdk] object TelemetryResourceAutoConfigure { * | otel.resource.attributes | OTEL_RESOURCE_ATTRIBUTES | Specify resource attributes in the following format: key1=val1,key2=val2,key3=val3 | * | otel.service.name | OTEL_SERVICE_NAME | Specify logical service name. Takes precedence over `service.name` defined with `otel.resource.attributes` | * | otel.experimental.resource.disabled-keys | OTEL_EXPERIMENTAL_RESOURCE_DISABLED_KEYS | Specify resource attribute keys that are filtered. | - * | otel.otel4s.resource.detectors | OTEL_OTEL4S_RESOURCE_DETECTORS | Specify resource detectors to use. Defaults to `host,os,process,process_runtime`. | + * | otel.otel4s.resource.detectors.enabled | OTEL_OTEL4S_RESOURCE_DETECTORS_ENABLED | Specify resource detectors to use. Defaults to `host,os,process,process_runtime`. | + * | otel.otel4s.resource.detectors.disabled | OTEL_OTEL4S_RESOURCE_DETECTORS_DISABLED | Specify resource detectors to disable. | * }}} * * @see diff --git a/sdk/common/shared/src/test/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigureSuite.scala b/sdk/common/shared/src/test/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigureSuite.scala index 27229b88e..d8c992e12 100644 --- a/sdk/common/shared/src/test/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigureSuite.scala +++ b/sdk/common/shared/src/test/scala/org/typelevel/otel4s/sdk/autoconfigure/TelemetryResourceAutoConfigureSuite.scala @@ -26,7 +26,7 @@ import org.typelevel.otel4s.sdk.resource.TelemetryResourceDetector class TelemetryResourceAutoConfigureSuite extends CatsEffectSuite { test("load from an empty config - use default as a fallback") { - val props = Map("otel.otel4s.resource.detectors" -> "none") + val props = Map("otel.otel4s.resource.detectors.enabled" -> "none") val config = Config.ofProps(props) TelemetryResourceAutoConfigure[IO](Set.empty) @@ -41,7 +41,7 @@ class TelemetryResourceAutoConfigureSuite extends CatsEffectSuite { "otel.service.name" -> "some-service", "otel.resource.attributes" -> "key1=val1,key2=val2,key3=val3", "otel.experimental.resource.disabled-keys" -> "key1,val3,test,key3", - "otel.otel4s.resource.detectors" -> "none" + "otel.otel4s.resource.detectors.enabled" -> "none" ) val config = Config.ofProps(props) @@ -112,7 +112,7 @@ class TelemetryResourceAutoConfigureSuite extends CatsEffectSuite { } test("use extra detectors") { - val props = Map("otel.otel4s.resource.detectors" -> "custom") + val props = Map("otel.otel4s.resource.detectors.enabled" -> "custom") val config = Config(props, Map.empty, Map.empty) val customResource = @@ -134,4 +134,28 @@ class TelemetryResourceAutoConfigureSuite extends CatsEffectSuite { ) } } + + test("do not load disabled detectors") { + val props = Map( + "otel.otel4s.resource.detectors.disabled" -> "host,process,process_runtime" + ) + val config = Config.ofProps(props) + + TelemetryResourceAutoConfigure[IO](Set.empty) + .configure(config) + .use { resource => + val service = Set("service.name") + val os = Set("os.type", "os.description") + + val telemetry = Set( + "telemetry.sdk.language", + "telemetry.sdk.name", + "telemetry.sdk.version" + ) + + val all = os ++ service ++ telemetry + + IO(assertEquals(resource.attributes.map(_.key.name).toSet, all)) + } + } } diff --git a/sdk/metrics/src/test/scala/org/typelevel/otel4s/sdk/metrics/SdkMetricsSuite.scala b/sdk/metrics/src/test/scala/org/typelevel/otel4s/sdk/metrics/SdkMetricsSuite.scala index 8629d7c5c..cf8b3b982 100644 --- a/sdk/metrics/src/test/scala/org/typelevel/otel4s/sdk/metrics/SdkMetricsSuite.scala +++ b/sdk/metrics/src/test/scala/org/typelevel/otel4s/sdk/metrics/SdkMetricsSuite.scala @@ -47,7 +47,7 @@ class SdkMetricsSuite extends CatsEffectSuite { test("withConfig - use the given config") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.metrics.exporter" -> "console" ) ) @@ -128,7 +128,7 @@ class SdkMetricsSuite extends CatsEffectSuite { test("addResourceCustomizer - customize a resource") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.metrics.exporter" -> "console" ) ) @@ -156,7 +156,7 @@ class SdkMetricsSuite extends CatsEffectSuite { test("addExporterConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.metrics.exporter" -> "custom-1,custom-2" ) ) diff --git a/sdk/trace/src/test/scala/org/typelevel/otel4s/sdk/trace/SdkTracesSuite.scala b/sdk/trace/src/test/scala/org/typelevel/otel4s/sdk/trace/SdkTracesSuite.scala index c1723e7a2..0c68fd50c 100644 --- a/sdk/trace/src/test/scala/org/typelevel/otel4s/sdk/trace/SdkTracesSuite.scala +++ b/sdk/trace/src/test/scala/org/typelevel/otel4s/sdk/trace/SdkTracesSuite.scala @@ -59,7 +59,7 @@ class SdkTracesSuite extends CatsEffectSuite { test("withConfig - use the given config") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none" ) ) @@ -137,7 +137,7 @@ class SdkTracesSuite extends CatsEffectSuite { test("addResourceCustomizer - customize a resource") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none" ) ) @@ -165,7 +165,7 @@ class SdkTracesSuite extends CatsEffectSuite { test("addExporterConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "custom-1,custom-2" ) ) @@ -205,7 +205,7 @@ class SdkTracesSuite extends CatsEffectSuite { test("addSamplerConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.traces.sampler" -> "custom-sampler", ) @@ -239,7 +239,7 @@ class SdkTracesSuite extends CatsEffectSuite { test("addTextMapPropagatorConfigurer - support external configurers") { val config = Config.ofProps( Map( - "otel.otel4s.resource.detectors" -> "none", + "otel.otel4s.resource.detectors.enabled" -> "none", "otel.traces.exporter" -> "none", "otel.propagators" -> "tracecontext,custom-1,custom-2,baggage", )