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 : /// Aggregation defines how measurements for a metric are aggregated.
7 : enum AggregationType {
8 : /// Sum aggregation accumulates the sum of measurements.
9 : sum,
10 :
11 : /// LastValue aggregation stores the last reported value.
12 : lastValue,
13 :
14 : /// Histogram aggregation computes statistics over measurements.
15 : histogram,
16 :
17 : /// Drop aggregation discards all measurements.
18 : drop,
19 :
20 : /// Default aggregation selects the appropriate aggregation based on instrument type.
21 : defaultAggregation,
22 : }
23 :
24 : /// View allows for customizing how metrics are collected and exported.
25 : ///
26 : /// A View can:
27 : /// - Filter which instruments are processed
28 : /// - Customize aggregation
29 : /// - Specify which attributes to include
30 : /// - Rename metrics
31 : class View {
32 : /// The name to use for the metric stream.
33 : /// If null, the original instrument name is used.
34 : final String? name;
35 :
36 : /// The description to use for the metric.
37 : /// If null, the original instrument description is used.
38 : final String? description;
39 :
40 : /// The instrument name pattern to match.
41 : /// Supports * as a wildcard.
42 : final String instrumentNamePattern;
43 :
44 : /// The instrument type to match.
45 : /// If null, all instrument types are matched.
46 : final Type? instrumentType;
47 :
48 : /// The meter name to match.
49 : /// If null, all meter names are matched.
50 : final String? meterName;
51 :
52 : /// The aggregation type to use.
53 : final AggregationType aggregationType;
54 :
55 : /// The attributes to include.
56 : /// If null, all attributes are included.
57 : final List<String>? attributeKeys;
58 :
59 : /// Creates a new View.
60 : ///
61 : /// [instrumentNamePattern] The pattern to match instrument names against.
62 : /// Use * as a wildcard to match multiple instruments.
63 3 : View({
64 : this.name,
65 : this.description,
66 : required this.instrumentNamePattern,
67 : this.instrumentType,
68 : this.meterName,
69 : this.aggregationType = AggregationType.defaultAggregation,
70 : this.attributeKeys,
71 : });
72 :
73 : /// Creates a view that matches all instruments.
74 1 : factory View.all({
75 : String? name,
76 : String? description,
77 : AggregationType aggregationType = AggregationType.defaultAggregation,
78 : List<String>? attributeKeys,
79 : }) {
80 1 : return View(
81 : name: name,
82 : description: description,
83 : instrumentNamePattern: '*',
84 : aggregationType: aggregationType,
85 : attributeKeys: attributeKeys,
86 : );
87 : }
88 :
89 : /// Checks if this view matches the given instrument.
90 : ///
91 : /// The [instrument] parameter accepts any instrument type (APICounter,
92 : /// APIHistogram, APIGauge, etc.) as well as their SDK implementations.
93 : /// All API instrument classes expose a `meter` getter, but they don't
94 : /// share a common base class — hence the `dynamic` parameter.
95 1 : bool matches(String instrumentName, dynamic instrument) {
96 : // Check instrument name pattern
97 2 : if (!_matchesPattern(instrumentName, instrumentNamePattern)) {
98 : return false;
99 : }
100 :
101 : // Check instrument type if specified
102 1 : if (instrumentType != null) {
103 3 : if (instrumentType == APICounter && instrument is! APICounter) {
104 : return false;
105 2 : } else if (instrumentType == APIUpDownCounter &&
106 1 : instrument is! APIUpDownCounter) {
107 : return false;
108 2 : } else if (instrumentType == APIHistogram &&
109 1 : instrument is! APIHistogram) {
110 : return false;
111 3 : } else if (instrumentType == APIGauge && instrument is! APIGauge) {
112 : return false;
113 2 : } else if (instrumentType == APIObservableCounter &&
114 1 : instrument is! APIObservableCounter) {
115 : return false;
116 2 : } else if (instrumentType == APIObservableUpDownCounter &&
117 1 : instrument is! APIObservableUpDownCounter) {
118 : return false;
119 2 : } else if (instrumentType == APIObservableGauge &&
120 1 : instrument is! APIObservableGauge) {
121 : return false;
122 : }
123 : }
124 :
125 : // Check meter name if specified. All instrument classes expose a
126 : // `meter` getter even without a common base type.
127 : // ignore: avoid_dynamic_calls
128 5 : if (meterName != null && meterName != instrument.meter.name) {
129 : return false;
130 : }
131 :
132 : return true;
133 : }
134 :
135 1 : bool _matchesPattern(String name, String pattern) {
136 1 : if (pattern == '*') {
137 : return true;
138 : }
139 :
140 : // Simple pattern matching for * wildcards
141 1 : if (pattern.contains('*')) {
142 3 : final regex = RegExp('^${pattern.replaceAll('*', '.*')}\$');
143 1 : return regex.hasMatch(name);
144 : }
145 :
146 1 : return name == pattern;
147 : }
148 : }
|