18
18
import io .micrometer .common .lang .Nullable ;
19
19
import io .micrometer .common .util .internal .logging .InternalLogger ;
20
20
import io .micrometer .common .util .internal .logging .InternalLoggerFactory ;
21
- import io .micrometer .core .instrument .Gauge ;
22
- import io .micrometer .core .instrument .*;
23
21
import io .micrometer .core .instrument .Timer ;
22
+ import io .micrometer .core .instrument .*;
24
23
import io .micrometer .core .instrument .config .NamingConvention ;
25
24
import io .micrometer .core .instrument .distribution .*;
26
- import io .micrometer .core .instrument .distribution .Histogram ;
27
25
import io .micrometer .core .instrument .distribution .pause .PauseDetector ;
28
26
import io .micrometer .core .instrument .internal .DefaultGauge ;
29
27
import io .micrometer .core .instrument .internal .DefaultLongTaskTimer ;
36
34
import io .micrometer .core .instrument .util .MeterPartition ;
37
35
import io .micrometer .core .instrument .util .NamedThreadFactory ;
38
36
import io .micrometer .core .instrument .util .TimeUtils ;
39
- import io .micrometer .core .ipc .http .HttpSender ;
40
37
import io .micrometer .core .ipc .http .HttpUrlConnectionSender ;
41
38
import io .micrometer .registry .otlp .internal .CumulativeBase2ExponentialHistogram ;
42
39
import io .micrometer .registry .otlp .internal .DeltaBase2ExponentialHistogram ;
43
40
import io .opentelemetry .proto .collector .metrics .v1 .ExportMetricsServiceRequest ;
44
41
import io .opentelemetry .proto .common .v1 .AnyValue ;
45
42
import io .opentelemetry .proto .common .v1 .KeyValue ;
46
- import io .opentelemetry .proto .metrics .v1 .*;
43
+ import io .opentelemetry .proto .metrics .v1 .ResourceMetrics ;
44
+ import io .opentelemetry .proto .metrics .v1 .ScopeMetrics ;
47
45
import io .opentelemetry .proto .resource .v1 .Resource ;
48
46
49
47
import java .time .Duration ;
56
54
import java .util .function .ToLongFunction ;
57
55
58
56
/**
59
- * Publishes meters in OTLP (OpenTelemetry Protocol) format. HTTP with Protobuf encoding
60
- * is the only option currently supported.
57
+ * Publishes meters in OTLP (OpenTelemetry Protocol) format.
61
58
*
62
59
* @author Tommy Ludwig
63
60
* @author Lenin Jaganathan
@@ -83,16 +80,14 @@ public class OtlpMeterRegistry extends PushMeterRegistry {
83
80
84
81
private final OtlpConfig config ;
85
82
86
- private final HttpSender httpSender ;
83
+ private final OltpMetricsSender metricsSender ;
87
84
88
85
private final Resource resource ;
89
86
90
87
private final AggregationTemporality aggregationTemporality ;
91
88
92
89
private final TimeUnit baseTimeUnit ;
93
90
94
- private final String userAgentHeader ;
95
-
96
91
// Time when the last scheduled rollOver has started. Applicable only for delta
97
92
// flavour.
98
93
private volatile long lastMeterRolloverStartTime = -1 ;
@@ -109,27 +104,32 @@ public OtlpMeterRegistry(OtlpConfig config, Clock clock) {
109
104
}
110
105
111
106
/**
112
- * Create an {@code OtlpMeterRegistry} instance.
107
+ * Create an {@code OtlpMeterRegistry} instance with an HTTP metrics sender .
113
108
* @param config config
114
109
* @param clock clock
115
110
* @param threadFactory thread factory
116
111
* @since 1.14.0
117
112
*/
118
113
public OtlpMeterRegistry (OtlpConfig config , Clock clock , ThreadFactory threadFactory ) {
119
- this (config , clock , threadFactory , new HttpUrlConnectionSender ());
114
+ this (config , clock , threadFactory , new OtlpHttpMetricsSender ( new HttpUrlConnectionSender (), config ));
120
115
}
121
116
122
- // VisibleForTesting
123
- // not public until we decide what we want to expose in public API
124
- // HttpSender may not be a good idea if we will support a non-HTTP transport
125
- OtlpMeterRegistry (OtlpConfig config , Clock clock , ThreadFactory threadFactory , HttpSender httpSender ) {
117
+ /**
118
+ * Create an {@code OtlpMeterRegistry} instance.
119
+ * @param config config
120
+ * @param clock clock
121
+ * @param threadFactory thread factory
122
+ * @param metricsSender metrics sender
123
+ * @since 1.14.0
124
+ */
125
+ public OtlpMeterRegistry (OtlpConfig config , Clock clock , ThreadFactory threadFactory ,
126
+ OltpMetricsSender metricsSender ) {
126
127
super (config , clock );
127
128
this .config = config ;
128
129
this .baseTimeUnit = config .baseTimeUnit ();
129
- this .httpSender = httpSender ;
130
+ this .metricsSender = metricsSender ;
130
131
this .resource = Resource .newBuilder ().addAllAttributes (getResourceAttributes ()).build ();
131
132
this .aggregationTemporality = config .aggregationTemporality ();
132
- this .userAgentHeader = getUserAgentHeader ();
133
133
config ().namingConvention (NamingConvention .dot );
134
134
start (threadFactory );
135
135
}
@@ -178,34 +178,15 @@ protected void publish() {
178
178
.build ())
179
179
.build ())
180
180
.build ();
181
- HttpSender .Request .Builder httpRequest = this .httpSender .post (this .config .url ())
182
- .withHeader ("User-Agent" , this .userAgentHeader )
183
- .withContent ("application/x-protobuf" , request .toByteArray ());
184
- this .config .headers ().forEach (httpRequest ::withHeader );
185
- HttpSender .Response response = httpRequest .send ();
186
- if (!response .isSuccessful ()) {
187
- logger .warn (
188
- "Failed to publish metrics (context: {}). Server responded with HTTP status code {} and body {}" ,
189
- getConfigurationContext (), response .code (), response .body ());
190
- }
181
+
182
+ metricsSender .send (request );
191
183
}
192
184
catch (Throwable e ) {
193
- logger .warn (String .format ("Failed to publish metrics to OTLP receiver (context: %s)" ,
194
- getConfigurationContext ()), e );
185
+ logger .warn ("Failed to publish metrics to OTLP receiver" , e );
195
186
}
196
187
}
197
188
}
198
189
199
- /**
200
- * Get the configuration context.
201
- * @return A message containing enough information for the log reader to figure out
202
- * what configuration details may have contributed to the failure.
203
- */
204
- private String getConfigurationContext () {
205
- // While other values may contribute to failures, these two are most common
206
- return "url=" + config .url () + ", resource-attributes=" + config .resourceAttributes ();
207
- }
208
-
209
190
@ Override
210
191
protected <T > Gauge newGauge (Meter .Id id , @ Nullable T obj , ToDoubleFunction <T > valueFunction ) {
211
192
return new DefaultGauge <>(id , obj , valueFunction );
@@ -390,12 +371,12 @@ Iterable<KeyValue> getResourceAttributes() {
390
371
}
391
372
392
373
static Histogram getHistogram (Clock clock , DistributionStatisticConfig distributionStatisticConfig ,
393
- OtlpConfig otlpConfig ) {
374
+ OtlpConfig otlpConfig ) {
394
375
return getHistogram (clock , distributionStatisticConfig , otlpConfig , null );
395
376
}
396
377
397
378
static Histogram getHistogram (final Clock clock , final DistributionStatisticConfig distributionStatisticConfig ,
398
- final OtlpConfig otlpConfig , @ Nullable final TimeUnit baseTimeUnit ) {
379
+ final OtlpConfig otlpConfig , @ Nullable final TimeUnit baseTimeUnit ) {
399
380
// While publishing to OTLP, we export either Histogram datapoint (Explicit
400
381
// ExponentialBuckets
401
382
// or Exponential) / Summary
@@ -411,14 +392,14 @@ static Histogram getHistogram(final Clock clock, final DistributionStatisticConf
411
392
}
412
393
413
394
return otlpConfig .aggregationTemporality () == AggregationTemporality .DELTA
414
- ? new DeltaBase2ExponentialHistogram (otlpConfig .maxScale (), otlpConfig .maxBucketCount (),
415
- minimumExpectedValue , baseTimeUnit , clock , otlpConfig .step ().toMillis ())
416
- : new CumulativeBase2ExponentialHistogram (otlpConfig .maxScale (), otlpConfig .maxBucketCount (),
417
- minimumExpectedValue , baseTimeUnit );
395
+ ? new DeltaBase2ExponentialHistogram (otlpConfig .maxScale (), otlpConfig .maxBucketCount (),
396
+ minimumExpectedValue , baseTimeUnit , clock , otlpConfig .step ().toMillis ())
397
+ : new CumulativeBase2ExponentialHistogram (otlpConfig .maxScale (), otlpConfig .maxBucketCount (),
398
+ minimumExpectedValue , baseTimeUnit );
418
399
}
419
400
420
401
Histogram explicitBucketHistogram = getExplicitBucketHistogram (clock , distributionStatisticConfig ,
421
- otlpConfig .aggregationTemporality (), otlpConfig .step ().toMillis ());
402
+ otlpConfig .aggregationTemporality (), otlpConfig .step ().toMillis ());
422
403
if (explicitBucketHistogram != null ) {
423
404
return explicitBucketHistogram ;
424
405
}
@@ -431,22 +412,22 @@ static Histogram getHistogram(final Clock clock, final DistributionStatisticConf
431
412
}
432
413
433
414
static HistogramFlavor histogramFlavor (HistogramFlavor preferredHistogramFlavor ,
434
- DistributionStatisticConfig distributionStatisticConfig ) {
415
+ DistributionStatisticConfig distributionStatisticConfig ) {
435
416
436
417
final double [] serviceLevelObjectiveBoundaries = distributionStatisticConfig
437
418
.getServiceLevelObjectiveBoundaries ();
438
419
if (distributionStatisticConfig .isPublishingHistogram ()
439
- && preferredHistogramFlavor == HistogramFlavor .BASE2_EXPONENTIAL_BUCKET_HISTOGRAM
440
- && (serviceLevelObjectiveBoundaries == null || serviceLevelObjectiveBoundaries .length == 0 )) {
420
+ && preferredHistogramFlavor == HistogramFlavor .BASE2_EXPONENTIAL_BUCKET_HISTOGRAM
421
+ && (serviceLevelObjectiveBoundaries == null || serviceLevelObjectiveBoundaries .length == 0 )) {
441
422
return HistogramFlavor .BASE2_EXPONENTIAL_BUCKET_HISTOGRAM ;
442
423
}
443
424
return HistogramFlavor .EXPLICIT_BUCKET_HISTOGRAM ;
444
425
}
445
426
446
427
@ Nullable
447
428
private static Histogram getExplicitBucketHistogram (final Clock clock ,
448
- final DistributionStatisticConfig distributionStatisticConfig ,
449
- final AggregationTemporality aggregationTemporality , final long stepMillis ) {
429
+ final DistributionStatisticConfig distributionStatisticConfig ,
430
+ final AggregationTemporality aggregationTemporality , final long stepMillis ) {
450
431
451
432
double [] sloWithPositiveInf = getSloWithPositiveInf (distributionStatisticConfig );
452
433
if (AggregationTemporality .isCumulative (aggregationTemporality )) {
@@ -461,11 +442,11 @@ private static Histogram getExplicitBucketHistogram(final Clock clock,
461
442
}
462
443
if (AggregationTemporality .isDelta (aggregationTemporality ) && stepMillis > 0 ) {
463
444
return new OtlpStepBucketHistogram (clock , stepMillis ,
464
- DistributionStatisticConfig .builder ()
465
- .serviceLevelObjectives (sloWithPositiveInf )
466
- .build ()
467
- .merge (distributionStatisticConfig ),
468
- true , false );
445
+ DistributionStatisticConfig .builder ()
446
+ .serviceLevelObjectives (sloWithPositiveInf )
447
+ .build ()
448
+ .merge (distributionStatisticConfig ),
449
+ true , false );
469
450
}
470
451
471
452
return null ;
@@ -492,11 +473,4 @@ static double[] getSloWithPositiveInf(DistributionStatisticConfig distributionSt
492
473
return sloWithPositiveInf ;
493
474
}
494
475
495
- private String getUserAgentHeader () {
496
- if (this .getClass ().getPackage ().getImplementationVersion () == null ) {
497
- return "Micrometer-OTLP-Exporter-Java" ;
498
- }
499
- return "Micrometer-OTLP-Exporter-Java/" + this .getClass ().getPackage ().getImplementationVersion ();
500
- }
501
-
502
476
}
0 commit comments