LCOV - code coverage report
Current view: top level - lib/src/resource - resource_detector.dart (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.5 % 38 34
Test Date: 2026-07-11 13:35:19 Functions: - 0 0

            Line data    Source code
       1              : // Copyright The OpenTelemetry Authors
       2              : // SPDX-License-Identifier: Apache-2.0
       3              : 
       4              : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
       5              : 
       6              : import '../environment/environment_service.dart';
       7              : import 'native_detectors.dart';
       8              : import 'resource.dart';
       9              : import 'web_detector.dart';
      10              : 
      11              : // Re-export the platform-conditional native detectors so existing
      12              : // imports of `package:dartastic_opentelemetry/src/resource/resource_detector.dart`
      13              : // continue to find `ProcessResourceDetector` and `HostResourceDetector`.
      14              : export 'native_detectors.dart'
      15              :     show HostResourceDetector, ProcessResourceDetector;
      16              : 
      17              : /// Interface for resource detectors that automatically discover resource information.
      18              : ///
      19              : /// Resource detectors are used to automatically populate resource attributes
      20              : /// based on the environment (operating system, platform, etc.).
      21              : ///
      22              : /// More information:
      23              : /// https://opentelemetry.io/docs/specs/otel/resource/sdk/#detecting-resource-information-from-the-environment
      24              : abstract class ResourceDetector {
      25              :   /// Detects resource information from the environment.
      26              :   ///
      27              :   /// @return A resource containing the detected attributes
      28              :   Future<Resource> detect();
      29              : }
      30              : 
      31              : /// Detects resource information from environment variables.
      32              : ///
      33              : /// This detector looks for the OTEL_RESOURCE_ATTRIBUTES environment variable
      34              : /// and parses its contents into resource attributes.
      35              : ///
      36              : /// More information:
      37              : /// https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration
      38              : class EnvVarResourceDetector implements ResourceDetector {
      39              :   final EnvironmentService _environmentService;
      40              : 
      41              :   /// Creates a new EnvVarResourceDetector with the specified environment service.
      42              :   ///
      43              :   /// If no environment service is provided, the singleton instance will be used.
      44              :   ///
      45              :   /// @param environmentService Optional service for accessing environment variables
      46           53 :   EnvVarResourceDetector([EnvironmentService? environmentService])
      47           52 :       : _environmentService = environmentService ?? EnvironmentService.instance;
      48              : 
      49           53 :   @override
      50              :   Future<Resource> detect() async {
      51              :     if (OTelFactory.otelFactory == null) {
      52            1 :       throw StateError('OTel initialize must be called first.');
      53              :     }
      54              : 
      55              :     //TODO - OTEL_RESOURCE_ATTRIBUTES?
      56          106 :     final resourceAttrs = _environmentService.getValue(
      57              :       'OTEL_RESOURCE_ATTRIBUTES',
      58              :     );
      59            1 :     if (resourceAttrs == null || resourceAttrs.isEmpty) {
      60           53 :       return Resource.empty;
      61              :     }
      62              : 
      63            1 :     final attributes = _parseResourceAttributes(resourceAttrs);
      64            1 :     return ResourceCreate.create(attributes);
      65              :   }
      66              : 
      67              :   /// Parses the OTEL_RESOURCE_ATTRIBUTES environment variable.
      68              :   ///
      69              :   /// The format is a comma-separated list of key=value pairs.
      70              :   /// For example: key1=value1,key2=value2
      71              :   ///
      72              :   /// Commas can be escaped with a backslash, and the values can be
      73              :   /// percent-encoded.
      74              :   ///
      75              :   /// @param envValue The value of the OTEL_RESOURCE_ATTRIBUTES environment variable
      76              :   /// @return Attributes parsed from the environment variable
      77            1 :   Attributes _parseResourceAttributes(String envValue) {
      78            1 :     final attributes = <String, Object>{};
      79              : 
      80              :     // Split on commas, but handle escaped commas
      81            2 :     final parts = envValue.split(RegExp(r'(?<!\\),'));
      82              : 
      83            2 :     for (var part in parts) {
      84              :       // Remove any leading/trailing whitespace
      85            1 :       part = part.trim();
      86              : 
      87              :       // Split on first equals sign
      88            1 :       final keyValue = part.split('=');
      89            2 :       if (keyValue.length != 2) continue;
      90              : 
      91            2 :       final key = keyValue[0].trim();
      92            2 :       var value = keyValue[1].trim();
      93              : 
      94              :       // Handle percent-encoded characters
      95            1 :       value = Uri.decodeComponent(value);
      96              : 
      97              :       // Remove escape characters
      98            1 :       value = value.replaceAll(r'\,', ',');
      99              : 
     100            1 :       attributes[key] = value;
     101              :     }
     102              : 
     103            1 :     return OTelFactory.otelFactory!.attributesFromMap(attributes);
     104              :   }
     105              : }
     106              : 
     107              : /// Composite detector that combines multiple resource detectors.
     108              : ///
     109              : /// This detector runs multiple detectors and merges their results.
     110              : /// This is useful for combining resource information from different sources.
     111              : ///
     112              : /// More information:
     113              : /// https://opentelemetry.io/docs/specs/otel/resource/sdk/#resource-creation
     114              : class CompositeResourceDetector implements ResourceDetector {
     115              :   final List<ResourceDetector> _detectors;
     116              : 
     117              :   /// Creates a new CompositeResourceDetector with the specified detectors.
     118              :   ///
     119              :   /// @param detectors The list of detectors to run
     120           53 :   CompositeResourceDetector(this._detectors);
     121              : 
     122           53 :   @override
     123              :   Future<Resource> detect() async {
     124              :     if (OTelFactory.otelFactory == null) {
     125            1 :       throw StateError('OTel initialize must be called first.');
     126              :     }
     127           53 :     var result = Resource.empty;
     128              : 
     129          106 :     for (final detector in _detectors) {
     130              :       try {
     131           53 :         final resource = await detector.detect();
     132           53 :         result = result.merge(resource);
     133              :       } catch (e) {
     134              :         // Log error but continue with other detectors
     135            9 :         if (OTelLog.isError()) OTelLog.error('Error in resource detector: $e');
     136              :       }
     137              :     }
     138              : 
     139              :     return result;
     140              :   }
     141              : }
     142              : 
     143              : /// Factory for creating platform-appropriate resource detectors.
     144              : ///
     145              : /// This factory creates a composite detector with the appropriate
     146              : /// detectors for the current platform (web or native).
     147              : class PlatformResourceDetector {
     148              :   /// Creates a composite detector with platform-appropriate detectors.
     149              :   ///
     150              :   /// @return A ResourceDetector that combines all appropriate detectors
     151           52 :   static ResourceDetector create() {
     152          104 :     final detectors = <ResourceDetector>[EnvVarResourceDetector()];
     153              : 
     154              :     // For non-web platforms (native)
     155              :     if (!const bool.fromEnvironment('dart.library.js_interop')) {
     156              :       try {
     157          208 :         detectors.addAll([ProcessResourceDetector(), HostResourceDetector()]);
     158              :       } catch (e) {
     159            0 :         if (OTelLog.isError()) {
     160            0 :           OTelLog.error('Error adding native detectors: $e');
     161              :         }
     162              :       }
     163              :     }
     164              :     // For web platforms
     165              :     else {
     166              :       try {
     167            0 :         detectors.add(WebResourceDetector());
     168              :       } catch (e) {
     169            0 :         if (OTelLog.isError()) OTelLog.error('Error adding web detector: $e');
     170              :       }
     171              :     }
     172              : 
     173           52 :     return CompositeResourceDetector(detectors);
     174              :   }
     175              : }
        

Generated by: LCOV version 2.0-1