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 '../../otel.dart';
7 :
8 : /// Exemplar is a sample data point that may be used to annotate aggregated
9 : /// metric data points.
10 : ///
11 : /// Exemplars allow correlation between aggregated metric data and the
12 : /// original API calls where measurements were recorded.
13 : class Exemplar {
14 : /// The attributes for this exemplar, typically including trace and span IDs.
15 : final Attributes attributes;
16 :
17 : /// The filtered attributes for this exemplar.
18 : /// These are attributes that were on the original measurement but
19 : /// not included in the aggregation.
20 : final Attributes filteredAttributes;
21 :
22 : /// The timestamp when this exemplar was recorded.
23 : final DateTime timestamp;
24 :
25 : /// The value of this exemplar.
26 : final num value;
27 :
28 : /// The trace ID associated with this exemplar.
29 : final TraceId? traceId;
30 :
31 : /// The span ID associated with this exemplar.
32 : final SpanId? spanId;
33 :
34 : /// Creates a new Exemplar instance.
35 6 : Exemplar({
36 : required this.attributes,
37 : required this.filteredAttributes,
38 : required this.timestamp,
39 : required this.value,
40 : this.traceId,
41 : this.spanId,
42 : });
43 :
44 : /// Creates an exemplar from a measurement.
45 1 : factory Exemplar.fromMeasurement({
46 : required Measurement measurement,
47 : required DateTime timestamp,
48 : required Attributes aggregationAttributes,
49 : SpanId? spanId,
50 : TraceId? traceId,
51 : }) {
52 : // Determine which attributes are filtered out
53 1 : final filteredAttrs = _filterAttributes(
54 1 : measurement.attributes ?? OTelFactory.otelFactory!.attributes(),
55 : aggregationAttributes,
56 : );
57 :
58 1 : return Exemplar(
59 : attributes: aggregationAttributes,
60 : filteredAttributes: filteredAttrs,
61 : timestamp: timestamp,
62 1 : value: measurement.value,
63 : traceId: traceId,
64 : spanId: spanId,
65 : );
66 : }
67 :
68 : /// Filters attributes to get those that are not included in the aggregation.
69 1 : static Attributes _filterAttributes(
70 : Attributes measurementAttrs,
71 : Attributes aggregationAttrs,
72 : ) {
73 1 : final result = <Attribute<Object>>[];
74 :
75 : // Get the attribute keys that are in the measurement but not in the aggregation
76 2 : final aggregationKeys = aggregationAttrs.keys.toSet();
77 2 : for (final attr in measurementAttrs.toList()) {
78 2 : if (!aggregationKeys.contains(attr.key)) {
79 1 : result.add(attr);
80 : }
81 : }
82 :
83 1 : return OTel.attributesFromList(result);
84 : }
85 : }
|