diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f4e334..f2c4e8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [1.1.0-beta.12-wip] +### Changed +- **Internal attribute keys now come from the generated registry enums** + (`Service.*`, `ExceptionAttributes.*`, `Otel.*`) instead of string + literals, across resource creation, exception recording, the + `package:logging` bridge, the OTLP span/log transformers, the sampler, + and the env resource-attribute parsing. A mistyped key is now a compile + error — the same hardening applied to the resource detector after #90. + No wire change: `Enum.key` resolves to the identical registry string. + ### Fixed - **`host.arch` no longer reports the hostname** (#90). The IO resource detector copy-pasted `Platform.localHostname` into `host.arch`; it now diff --git a/lib/src/environment/otel_env.dart b/lib/src/environment/otel_env.dart index 87a66e7..9074cc3 100644 --- a/lib/src/environment/otel_env.dart +++ b/lib/src/environment/otel_env.dart @@ -304,9 +304,9 @@ class OTelEnv { final key = pair.substring(0, equalIndex).trim(); final value = pair.substring(equalIndex + 1).trim(); - if (key == 'service.name') { + if (key == Service.serviceName.key) { config['serviceName'] = value; - } else if (key == 'service.version') { + } else if (key == Service.serviceVersion.key) { config['serviceVersion'] = value; } } diff --git a/lib/src/logs/bridge/dart_log_bridge.dart b/lib/src/logs/bridge/dart_log_bridge.dart index d131f83..5a0ba53 100644 --- a/lib/src/logs/bridge/dart_log_bridge.dart +++ b/lib/src/logs/bridge/dart_log_bridge.dart @@ -181,13 +181,13 @@ class DartLogBridge { } if (error != null) { attributes.add(OTelAPI.attributeString( - 'exception.type', error.runtimeType.toString())); - attributes - .add(OTelAPI.attributeString('exception.message', error.toString())); + ExceptionAttributes.exceptionType.key, error.runtimeType.toString())); + attributes.add(OTelAPI.attributeString( + ExceptionAttributes.exceptionMessage.key, error.toString())); } if (stackTrace != null) { attributes.add(OTelAPI.attributeString( - 'exception.stacktrace', stackTrace.toString())); + ExceptionAttributes.exceptionStacktrace.key, stackTrace.toString())); } // Emit the log diff --git a/lib/src/logs/export/console_log_record_exporter.dart b/lib/src/logs/export/console_log_record_exporter.dart index 836486a..939d029 100644 --- a/lib/src/logs/export/console_log_record_exporter.dart +++ b/lib/src/logs/export/console_log_record_exporter.dart @@ -78,7 +78,7 @@ class ConsoleLogRecordExporter implements LogRecordExporter { // Format resource if (logRecord.resource != null) { final serviceName = - _getResourceAttribute(logRecord.resource!, 'service.name'); + _getResourceAttribute(logRecord.resource!, Service.serviceName.key); if (serviceName != null) { buffer.write(' service=$serviceName'); } diff --git a/lib/src/logs/export/otlp/log_record_transformer.dart b/lib/src/logs/export/otlp/log_record_transformer.dart index a528e91..ee72d09 100644 --- a/lib/src/logs/export/otlp/log_record_transformer.dart +++ b/lib/src/logs/export/otlp/log_record_transformer.dart @@ -45,7 +45,7 @@ class OtlpLogRecordTransformer { if (OTelLog.isDebug()) { OTelLog.debug('LogRecordTransformer: Extracting resource attributes:'); resourceAttrs.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); @@ -103,7 +103,7 @@ class OtlpLogRecordTransformer { /// Get service name from resource attributes. static String _getResourceServiceName(Attributes attributes) { for (final attr in attributes.toList()) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { return attr.value.toString(); } } diff --git a/lib/src/logs/logger_provider.dart b/lib/src/logs/logger_provider.dart index a774f00..6e8529b 100644 --- a/lib/src/logs/logger_provider.dart +++ b/lib/src/logs/logger_provider.dart @@ -181,7 +181,7 @@ class LoggerProvider implements APILoggerProvider { if (resource != null) { OTelLog.debug('Resource attributes:'); resource!.attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); diff --git a/lib/src/otel.dart b/lib/src/otel.dart index bb93fd3..74700d5 100644 --- a/lib/src/otel.dart +++ b/lib/src/otel.dart @@ -276,8 +276,8 @@ class OTel { } final serviceResourceAttributes = { - 'service.name': serviceName, - 'service.version': serviceVersion, + Service.serviceName.key: serviceName, + Service.serviceVersion.key: serviceVersion, }; // Create initial resource with service attributes var baseResource = OTel.resource( @@ -295,7 +295,7 @@ class OTel { if (OTelLog.isDebug()) { OTelLog.debug('Resource after platform merge:'); mergedResource.attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); @@ -309,7 +309,7 @@ class OTel { if (OTelLog.isDebug()) { OTelLog.debug('Resource after user attributes merge:'); mergedResource.attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); @@ -574,7 +574,7 @@ class OTel { OTelLog.debug('OTel.tracerProvider: Setting resource from default'); if (defaultResource != null) { defaultResource!.attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); diff --git a/lib/src/resource/resource.dart b/lib/src/resource/resource.dart index 2b28160..ee36720 100644 --- a/lib/src/resource/resource.dart +++ b/lib/src/resource/resource.dart @@ -95,7 +95,7 @@ class Resource { if (OTelLog.isDebug()) { OTelLog.debug('Resource merge result attributes:'); result._attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); diff --git a/lib/src/trace/export/otlp/span_transformer.dart b/lib/src/trace/export/otlp/span_transformer.dart index a848f65..c3718e7 100644 --- a/lib/src/trace/export/otlp/span_transformer.dart +++ b/lib/src/trace/export/otlp/span_transformer.dart @@ -40,7 +40,7 @@ class OtlpSpanTransformer { if (OTelLog.isDebug()) { OTelLog.debug('Extracting resource attributes for export:'); resourceAttrs.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); @@ -49,7 +49,7 @@ class OtlpSpanTransformer { if (OTelLog.isDebug()) { OTelLog.debug('Extracting resource attributes for export:'); resourceAttrs.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } }); @@ -104,7 +104,7 @@ class OtlpSpanTransformer { /// Get service name from resource attributes static String _getResourceServiceName(Attributes attributes) { for (final attr in attributes.toList()) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { return attr.value.toString(); } } diff --git a/lib/src/trace/sampling/counting_sampler.dart b/lib/src/trace/sampling/counting_sampler.dart index 9149fe3..6b76fd2 100644 --- a/lib/src/trace/sampling/counting_sampler.dart +++ b/lib/src/trace/sampling/counting_sampler.dart @@ -135,8 +135,8 @@ class ErrorSamplingCondition extends SamplingCondition { if (attributes == null) return false; // Check for error status - final statusCode = attributes.getString('otel.status_code'); - final statusMessage = attributes.getString('otel.status_description'); + final statusCode = attributes.getString(Otel.otelStatusCode.key); + final statusMessage = attributes.getString(Otel.otelStatusDescription.key); return statusCode == 'ERROR' || (statusMessage != null && statusMessage.isNotEmpty); diff --git a/lib/src/trace/tracer.dart b/lib/src/trace/tracer.dart index a52bde4..1980d03 100644 --- a/lib/src/trace/tracer.dart +++ b/lib/src/trace/tracer.dart @@ -514,8 +514,8 @@ class Tracer implements APITracer { error, stackTrace: sanitized.stackTrace, attributes: OTel.attributesFromMap({ - 'exception.type': sanitized.type, - 'exception.message': sanitized.message, + ExceptionAttributes.exceptionType.key: sanitized.type, + ExceptionAttributes.exceptionMessage.key: sanitized.message, }), ); } diff --git a/lib/src/trace/tracer_provider.dart b/lib/src/trace/tracer_provider.dart index c39fdec..88b4e59 100644 --- a/lib/src/trace/tracer_provider.dart +++ b/lib/src/trace/tracer_provider.dart @@ -227,7 +227,7 @@ class TracerProvider implements APITracerProvider { if (resource != null) { OTelLog.debug('Resource attributes:'); resource!.attributes.toList().forEach((attr) { - if (attr.key == 'service.name') { + if (attr.key == Service.serviceName.key) { OTelLog.debug(' ${attr.key}: ${attr.value}'); } });