Line data Source code
1 : // Copyright The OpenTelemetry Authors
2 : // SPDX-License-Identifier: Apache-2.0
3 :
4 : library;
5 :
6 : import 'package:dartastic_opentelemetry_api/dartastic_opentelemetry_api.dart';
7 : import 'package:meta/meta.dart';
8 :
9 : import '../otel.dart';
10 :
11 : part 'resource_create.dart';
12 :
13 : /// Represents a resource, which captures identifying information about the entities
14 : /// for which signals (stats, traces, and logs) are reported.
15 : ///
16 : /// A Resource is an immutable collection of attributes that provide information
17 : /// about the entity producing telemetry. Resources are a core concept of OpenTelemetry's
18 : /// identity model.
19 : ///
20 : /// More information:
21 : /// https://opentelemetry.io/docs/specs/otel/resource/sdk/
22 : @immutable
23 : class Resource {
24 : final Attributes _attributes;
25 : final String? _schemaUrl;
26 :
27 : /// An empty resource with no attributes.
28 : ///
29 : /// This is a convenience constant for when no resource attributes are needed.
30 765 : static final Resource empty = Resource._(OTel.attributesFromMap({}));
31 :
32 : /// Gets the attributes describing this resource.
33 288 : Attributes get attributes => _attributes;
34 :
35 : /// Gets the schema URL for this resource's attributes, if any.
36 4 : String? get schemaUrl => _schemaUrl;
37 :
38 : /// Private constructor for creating Resource instances.
39 : ///
40 : /// Resources should be created through the [OTel.resource] method
41 : /// or [ResourceCreate.create] method, not directly.
42 153 : Resource._(Attributes attributes, [String? schemaUrl])
43 : : _attributes = attributes,
44 : _schemaUrl = schemaUrl;
45 :
46 : /// Merges this resource with another resource.
47 : ///
48 : /// The resulting resource contains the combined attributes of both resources.
49 : /// If there are attributes with the same key, the attributes from the other
50 : /// resource will take precedence.
51 : ///
52 : /// For schema URLs, the following rules apply:
53 : /// - If one schema URL is empty, use the non-empty one
54 : /// - If both schema URLs are the same, use that schema URL
55 : /// - If both schema URLs are different and non-empty, use the other resource's schema URL
56 : ///
57 : /// @param other The resource to merge with this resource
58 : /// @return A new resource with the merged attributes
59 153 : Resource merge(Resource other) {
60 153 : final mergedMap = <String, Object>{};
61 :
62 : // Add current attributes
63 519 : _attributes.toMap().forEach((key, value) {
64 120 : mergedMap[key] = value.value;
65 : });
66 :
67 : // Add other resource's attributes (they take precedence)
68 612 : other._attributes.toMap().forEach((key, value) {
69 306 : mergedMap[key] = value.value;
70 : });
71 :
72 : // Handle schema URL merging according to spec
73 : String? mergedSchemaUrl;
74 155 : if (_schemaUrl == null || _schemaUrl!.isEmpty) {
75 153 : mergedSchemaUrl = other._schemaUrl;
76 3 : } else if (other._schemaUrl == null || other._schemaUrl!.isEmpty) {
77 1 : mergedSchemaUrl = _schemaUrl;
78 3 : } else if (_schemaUrl == other._schemaUrl) {
79 1 : mergedSchemaUrl = _schemaUrl;
80 : } else {
81 : // Schema URLs are different and non-empty - this is a merging error
82 : // The spec says the result is implementation-specific
83 : // We'll choose to use the updating resource's schema URL
84 1 : mergedSchemaUrl = other._schemaUrl;
85 : }
86 :
87 153 : final result = Resource._(
88 153 : OTel.attributesFromMap(mergedMap),
89 : mergedSchemaUrl,
90 : );
91 :
92 153 : if (OTelLog.isDebug()) {
93 134 : OTelLog.debug('Resource merge result attributes:');
94 536 : result._attributes.toList().forEach((attr) {
95 402 : if (attr.key == Service.serviceName.key) {
96 536 : OTelLog.debug(' ${attr.key}: ${attr.value}');
97 : }
98 : });
99 : }
100 :
101 : return result;
102 : }
103 : }
|