15
15
16
16
package software .amazon .opentelemetry .javaagent .providers ;
17
17
18
+ import io .opentelemetry .api .common .Attributes ;
19
+ import io .opentelemetry .api .common .AttributesBuilder ;
18
20
import io .opentelemetry .api .metrics .MeterProvider ;
19
21
import io .opentelemetry .contrib .awsxray .AlwaysRecordSampler ;
20
22
import io .opentelemetry .contrib .awsxray .ResourceHolder ;
25
27
import io .opentelemetry .sdk .autoconfigure .spi .AutoConfigurationCustomizerProvider ;
26
28
import io .opentelemetry .sdk .autoconfigure .spi .ConfigProperties ;
27
29
import io .opentelemetry .sdk .autoconfigure .spi .ConfigurationException ;
30
+ import io .opentelemetry .sdk .autoconfigure .spi .internal .DefaultConfigProperties ;
28
31
import io .opentelemetry .sdk .metrics .Aggregation ;
32
+ import io .opentelemetry .sdk .metrics .InstrumentSelector ;
29
33
import io .opentelemetry .sdk .metrics .InstrumentType ;
30
34
import io .opentelemetry .sdk .metrics .SdkMeterProvider ;
31
- import io .opentelemetry .sdk .metrics .export .AggregationTemporalitySelector ;
35
+ import io .opentelemetry .sdk .metrics .SdkMeterProviderBuilder ;
36
+ import io .opentelemetry .sdk .metrics .View ;
32
37
import io .opentelemetry .sdk .metrics .export .MetricExporter ;
33
38
import io .opentelemetry .sdk .metrics .export .MetricReader ;
34
39
import io .opentelemetry .sdk .metrics .export .PeriodicMetricReader ;
40
+ import io .opentelemetry .sdk .resources .Resource ;
35
41
import io .opentelemetry .sdk .trace .SdkTracerProviderBuilder ;
36
42
import io .opentelemetry .sdk .trace .SpanProcessor ;
37
43
import io .opentelemetry .sdk .trace .export .SpanExporter ;
38
44
import io .opentelemetry .sdk .trace .samplers .Sampler ;
39
45
import java .time .Duration ;
46
+ import java .util .ArrayList ;
47
+ import java .util .Collections ;
48
+ import java .util .HashMap ;
49
+ import java .util .HashSet ;
50
+ import java .util .List ;
51
+ import java .util .Map ;
52
+ import java .util .Set ;
40
53
import java .util .logging .Level ;
41
54
import java .util .logging .Logger ;
42
55
@@ -61,27 +74,72 @@ public class AwsApplicationSignalsCustomizerProvider
61
74
private static final Logger logger =
62
75
Logger .getLogger (AwsApplicationSignalsCustomizerProvider .class .getName ());
63
76
64
- private static final String SMP_ENABLED_CONFIG = "otel.smp.enabled" ;
65
- private static final String APP_SIGNALS_ENABLED_CONFIG = "otel.aws.app.signals.enabled" ;
77
+ private static final String DEPRECATED_SMP_ENABLED_CONFIG = "otel.smp.enabled" ;
78
+ private static final String DEPRECATED_APP_SIGNALS_ENABLED_CONFIG =
79
+ "otel.aws.app.signals.enabled" ;
66
80
private static final String APPLICATION_SIGNALS_ENABLED_CONFIG =
67
81
"otel.aws.application.signals.enabled" ;
68
- private static final String SMP_EXPORTER_ENDPOINT_CONFIG = "otel.aws.smp.exporter.endpoint" ;
69
- private static final String APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG =
82
+ private static final String APPLICATION_SIGNALS_RUNTIME_ENABLED_CONFIG =
83
+ "otel.aws.application.signals.runtime.enabled" ;
84
+ private static final String DEPRECATED_SMP_EXPORTER_ENDPOINT_CONFIG =
85
+ "otel.aws.smp.exporter.endpoint" ;
86
+ private static final String DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG =
70
87
"otel.aws.app.signals.exporter.endpoint" ;
71
88
private static final String APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG =
72
89
"otel.aws.application.signals.exporter.endpoint" ;
73
90
91
+ private static final String OTEL_JMX_TARGET_SYSTEM_CONFIG = "otel.jmx.target.system" ;
92
+
74
93
public void customize (AutoConfigurationCustomizer autoConfiguration ) {
94
+ autoConfiguration .addPropertiesCustomizer (this ::customizeProperties );
95
+ autoConfiguration .addResourceCustomizer (this ::customizeResource );
75
96
autoConfiguration .addSamplerCustomizer (this ::customizeSampler );
76
97
autoConfiguration .addTracerProviderCustomizer (this ::customizeTracerProviderBuilder );
98
+ autoConfiguration .addMeterProviderCustomizer (this ::customizeMeterProvider );
77
99
autoConfiguration .addSpanExporterCustomizer (this ::customizeSpanExporter );
78
100
}
79
101
80
102
private boolean isApplicationSignalsEnabled (ConfigProperties configProps ) {
81
103
return configProps .getBoolean (
82
104
APPLICATION_SIGNALS_ENABLED_CONFIG ,
83
105
configProps .getBoolean (
84
- APP_SIGNALS_ENABLED_CONFIG , configProps .getBoolean (SMP_ENABLED_CONFIG , false )));
106
+ DEPRECATED_APP_SIGNALS_ENABLED_CONFIG ,
107
+ configProps .getBoolean (DEPRECATED_SMP_ENABLED_CONFIG , false )));
108
+ }
109
+
110
+ private boolean isApplicationSignalsRuntimeEnabled (ConfigProperties configProps ) {
111
+ return false ;
112
+ }
113
+
114
+ private Map <String , String > customizeProperties (ConfigProperties configProps ) {
115
+ if (isApplicationSignalsRuntimeEnabled (configProps )) {
116
+ List <String > list = configProps .getList (OTEL_JMX_TARGET_SYSTEM_CONFIG );
117
+ if (list .contains ("jvm" )) {
118
+ logger .log (Level .INFO , "Found jmx in {0}" , OTEL_JMX_TARGET_SYSTEM_CONFIG );
119
+ return Collections .emptyMap ();
120
+ } else {
121
+ logger .log (Level .INFO , "Configure jmx in {0}" , OTEL_JMX_TARGET_SYSTEM_CONFIG );
122
+ List <String > jmxTargets = new ArrayList <>(list );
123
+ jmxTargets .add ("jvm" );
124
+ Map <String , String > propsOverride = new HashMap <>(1 );
125
+ propsOverride .put (OTEL_JMX_TARGET_SYSTEM_CONFIG , String .join ("," , jmxTargets ));
126
+ return propsOverride ;
127
+ }
128
+ }
129
+ return Collections .emptyMap ();
130
+ }
131
+
132
+ private Resource customizeResource (Resource resource , ConfigProperties configProps ) {
133
+ if (isApplicationSignalsEnabled (configProps )) {
134
+ AttributesBuilder builder = Attributes .builder ();
135
+ AwsResourceAttributeConfigurator .setServiceAttribute (
136
+ resource ,
137
+ builder ,
138
+ () -> logger .log (Level .WARNING , "Service name is undefined, use UnknownService instead" ));
139
+ Resource additionalResource = Resource .create ((builder .build ()));
140
+ return resource .merge (additionalResource );
141
+ }
142
+ return resource ;
85
143
}
86
144
87
145
private Sampler customizeSampler (Sampler sampler , ConfigProperties configProps ) {
@@ -95,20 +153,7 @@ private SdkTracerProviderBuilder customizeTracerProviderBuilder(
95
153
SdkTracerProviderBuilder tracerProviderBuilder , ConfigProperties configProps ) {
96
154
if (isApplicationSignalsEnabled (configProps )) {
97
155
logger .info ("AWS Application Signals enabled" );
98
- Duration exportInterval =
99
- configProps .getDuration ("otel.metric.export.interval" , DEFAULT_METRIC_EXPORT_INTERVAL );
100
- logger .log (
101
- Level .FINE ,
102
- String .format ("AWS Application Signals Metrics export interval: %s" , exportInterval ));
103
- // Cap export interval to 60 seconds. This is currently required for metrics-trace correlation
104
- // to work correctly.
105
- if (exportInterval .compareTo (DEFAULT_METRIC_EXPORT_INTERVAL ) > 0 ) {
106
- exportInterval = DEFAULT_METRIC_EXPORT_INTERVAL ;
107
- logger .log (
108
- Level .INFO ,
109
- String .format (
110
- "AWS Application Signals metrics export interval capped to %s" , exportInterval ));
111
- }
156
+ Duration exportInterval = getMetricExportInterval (configProps );
112
157
// Construct and set local and remote attributes span processor
113
158
tracerProviderBuilder .addSpanProcessor (
114
159
AttributePropagatingSpanProcessorBuilder .create ().build ());
@@ -133,6 +178,67 @@ private SdkTracerProviderBuilder customizeTracerProviderBuilder(
133
178
return tracerProviderBuilder ;
134
179
}
135
180
181
+ private SdkMeterProviderBuilder customizeMeterProvider (
182
+ SdkMeterProviderBuilder sdkMeterProviderBuilder , ConfigProperties configProps ) {
183
+
184
+ if (isApplicationSignalsRuntimeEnabled (configProps )) {
185
+ Set <String > registeredScopeNames = new HashSet <>(1 );
186
+ String jmxRuntimeScopeName = "io.opentelemetry.jmx" ;
187
+ registeredScopeNames .add (jmxRuntimeScopeName );
188
+
189
+ configureMetricFilter (configProps , sdkMeterProviderBuilder , registeredScopeNames );
190
+
191
+ MetricExporter metricsExporter =
192
+ ApplicationSignalsExporterProvider .INSTANCE .createExporter (configProps );
193
+ MetricReader metricReader =
194
+ ScopeBasedPeriodicMetricReader .create (metricsExporter , registeredScopeNames )
195
+ .setInterval (getMetricExportInterval (configProps ))
196
+ .build ();
197
+ sdkMeterProviderBuilder .registerMetricReader (metricReader );
198
+
199
+ logger .info ("AWS Application Signals runtime metric collection enabled" );
200
+ }
201
+ return sdkMeterProviderBuilder ;
202
+ }
203
+
204
+ private static void configureMetricFilter (
205
+ ConfigProperties configProps ,
206
+ SdkMeterProviderBuilder sdkMeterProviderBuilder ,
207
+ Set <String > registeredScopeNames ) {
208
+ Set <String > exporterNames =
209
+ DefaultConfigProperties .getSet (configProps , "otel.metrics.exporter" );
210
+ if (exporterNames .contains ("none" )) {
211
+ for (String scope : registeredScopeNames ) {
212
+ sdkMeterProviderBuilder .registerView (
213
+ InstrumentSelector .builder ().setMeterName (scope ).build (),
214
+ View .builder ().setAggregation (Aggregation .defaultAggregation ()).build ());
215
+
216
+ logger .log (Level .FINE , "Registered scope {0}" , scope );
217
+ }
218
+ sdkMeterProviderBuilder .registerView (
219
+ InstrumentSelector .builder ().setName ("*" ).build (),
220
+ View .builder ().setAggregation (Aggregation .drop ()).build ());
221
+ }
222
+ }
223
+
224
+ private static Duration getMetricExportInterval (ConfigProperties configProps ) {
225
+ Duration exportInterval =
226
+ configProps .getDuration ("otel.metric.export.interval" , DEFAULT_METRIC_EXPORT_INTERVAL );
227
+ logger .log (
228
+ Level .FINE ,
229
+ String .format ("AWS Application Signals Metrics export interval: %s" , exportInterval ));
230
+ // Cap export interval to 60 seconds. This is currently required for metrics-trace correlation
231
+ // to work correctly.
232
+ if (exportInterval .compareTo (DEFAULT_METRIC_EXPORT_INTERVAL ) > 0 ) {
233
+ exportInterval = DEFAULT_METRIC_EXPORT_INTERVAL ;
234
+ logger .log (
235
+ Level .INFO ,
236
+ String .format (
237
+ "AWS Application Signals metrics export interval capped to %s" , exportInterval ));
238
+ }
239
+ return exportInterval ;
240
+ }
241
+
136
242
private SpanExporter customizeSpanExporter (
137
243
SpanExporter spanExporter , ConfigProperties configProps ) {
138
244
if (isApplicationSignalsEnabled (configProps )) {
@@ -159,33 +265,35 @@ public MetricExporter createExporter(ConfigProperties configProps) {
159
265
configProps .getString (
160
266
APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
161
267
configProps .getString (
162
- APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
268
+ DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
163
269
configProps .getString (
164
- SMP_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4316/v1/metrics" )));
270
+ DEPRECATED_SMP_EXPORTER_ENDPOINT_CONFIG ,
271
+ "http://localhost:4316/v1/metrics" )));
165
272
logger .log (
166
273
Level .FINE ,
167
274
String .format (
168
275
"AWS Application Signals export endpoint: %s" , applicationSignalsEndpoint ));
169
276
return OtlpHttpMetricExporter .builder ()
170
277
.setEndpoint (applicationSignalsEndpoint )
171
278
.setDefaultAggregationSelector (this ::getAggregation )
172
- .setAggregationTemporalitySelector (AggregationTemporalitySelector . deltaPreferred ())
279
+ .setAggregationTemporalitySelector (CloudWatchTemporalitySelector . alwaysDelta ())
173
280
.build ();
174
281
} else if (protocol .equals (OtlpConfigUtil .PROTOCOL_GRPC )) {
175
282
applicationSignalsEndpoint =
176
283
configProps .getString (
177
284
APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
178
285
configProps .getString (
179
- APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
180
- configProps .getString (SMP_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4315" )));
286
+ DEPRECATED_APP_SIGNALS_EXPORTER_ENDPOINT_CONFIG ,
287
+ configProps .getString (
288
+ DEPRECATED_SMP_EXPORTER_ENDPOINT_CONFIG , "http://localhost:4315" )));
181
289
logger .log (
182
290
Level .FINE ,
183
291
String .format (
184
292
"AWS Application Signals export endpoint: %s" , applicationSignalsEndpoint ));
185
293
return OtlpGrpcMetricExporter .builder ()
186
294
.setEndpoint (applicationSignalsEndpoint )
187
295
.setDefaultAggregationSelector (this ::getAggregation )
188
- .setAggregationTemporalitySelector (AggregationTemporalitySelector . deltaPreferred ())
296
+ .setAggregationTemporalitySelector (CloudWatchTemporalitySelector . alwaysDelta ())
189
297
.build ();
190
298
}
191
299
throw new ConfigurationException (
0 commit comments