@@ -81,86 +81,90 @@ public VeniceOpenTelemetryMetricsRepository(VeniceMetricsConfig metricsConfig) {
8181 emitOpenTelemetryMetrics = metricsConfig .emitOtelMetrics ();
8282 emitTehutiMetrics = metricsConfig .emitTehutiMetrics ();
8383 metricFormat = metricsConfig .getMetricNamingFormat ();
84+ this .metricPrefix = metricsConfig .getMetricPrefix ();
85+ validateMetricName (getMetricPrefix ());
8486 if (!emitOpenTelemetryMetrics ) {
8587 LOGGER .info ("OpenTelemetry metrics are disabled" );
8688 openTelemetry = null ;
8789 return ;
8890 }
89- this .metricPrefix = metricsConfig .getMetricPrefix ();
90- validateMetricName (getMetricPrefix ());
91+ this .openTelemetry = initializeOpenTelemetry (metricsConfig );
92+ this .meter = openTelemetry .getMeter (transformMetricName (getMetricPrefix (), metricFormat ));
93+ this .recordFailureMetric = MetricEntityStateBase .create (
94+ CommonMetricsEntity .METRIC_RECORD_FAILURE .getMetricEntity (),
95+ this ,
96+ Collections .EMPTY_MAP ,
97+ Attributes .empty ());
98+ }
99+
100+ private OpenTelemetry initializeOpenTelemetry (VeniceMetricsConfig metricsConfig ) {
101+ OpenTelemetry otel ;
91102 if (metricsConfig .useOpenTelemetryInitializedByApplication ()) {
92103 LOGGER .info ("Using globally initialized OpenTelemetry for {}" , metricsConfig .getServiceName ());
93- openTelemetry = GlobalOpenTelemetry .get ();
94- if (openTelemetry == null || openTelemetry .getMeterProvider () == null
95- || openTelemetry .getMeterProvider ().equals (MeterProvider .noop ())) {
96- // Fail fast if no global OpenTelemetry instance is initialized to avoid silent metric loss.
97- // When disabled, each Venice component will initialize its own OpenTelemetry instance,
98- // which can lead to multiple instances in the same application, especially when used as
99- // a library (common for Venice clients) when multiple such libraries initialized.
100- throw new VeniceException (
101- "OpenTelemetry is not initialized globally by the application: disable the configuration or "
102- + "initialize OpenTelemetry in the application before initializing venice" );
104+ otel = GlobalOpenTelemetry .get ();
105+ if (otel == null || otel .getMeterProvider () == null || otel .getMeterProvider ().equals (MeterProvider .noop ())) {
106+ LOGGER .warn (
107+ "Global OpenTelemetry is not initialized properly. Falling back to local initialization for {}" ,
108+ metricsConfig .getServiceName ());
109+ } else {
110+ LOGGER .info ("Successfully obtained globally initialized OpenTelemetry for {}" , metricsConfig .getServiceName ());
111+ return otel ;
103112 }
104- } else {
105- LOGGER .info (
106- "OpenTelemetry initialization for {} started with config: {}" ,
107- metricsConfig .getServiceName (),
108- metricsConfig .toString ());
109- try {
110- SdkMeterProviderBuilder builder = SdkMeterProvider .builder ();
111-
112- if (metricsConfig .exportOtelMetricsToEndpoint ()) {
113- MetricExporter httpExporter = getOtlpHttpMetricExporter (metricsConfig );
114- builder .registerMetricReader (
115- PeriodicMetricReader .builder (httpExporter )
116- .setInterval (metricsConfig .getExportOtelMetricsIntervalInSeconds (), TimeUnit .SECONDS )
117- .build ());
118- }
113+ }
119114
120- if (metricsConfig .exportOtelMetricsToLog ()) {
121- // internal to test: Disabled by default
122- builder .registerMetricReader (
123- PeriodicMetricReader .builder (new LogBasedMetricExporter (metricsConfig ))
124- .setInterval (metricsConfig .getExportOtelMetricsIntervalInSeconds (), TimeUnit .SECONDS )
125- .build ());
126- }
115+ LOGGER .info (
116+ "OpenTelemetry initialization for {} started with config: {}" ,
117+ metricsConfig .getServiceName (),
118+ metricsConfig .toString ());
119+ try {
120+ SdkMeterProviderBuilder builder = SdkMeterProvider .builder ();
121+
122+ if (metricsConfig .exportOtelMetricsToEndpoint ()) {
123+ MetricExporter httpExporter = getOtlpHttpMetricExporter (metricsConfig );
124+ builder .registerMetricReader (
125+ PeriodicMetricReader .builder (httpExporter )
126+ .setInterval (metricsConfig .getExportOtelMetricsIntervalInSeconds (), TimeUnit .SECONDS )
127+ .build ());
128+ }
127129
128- if (metricsConfig .getOtelAdditionalMetricsReader () != null ) {
129- // additional metrics reader apart from the above. For instance,
130- // an in-memory metric reader can be passed in for testing purposes.
131- builder .registerMetricReader (metricsConfig .getOtelAdditionalMetricsReader ());
132- }
130+ if (metricsConfig .exportOtelMetricsToLog ()) {
131+ // internal to test: Disabled by default
132+ builder .registerMetricReader (
133+ PeriodicMetricReader .builder (new LogBasedMetricExporter (metricsConfig ))
134+ .setInterval (metricsConfig .getExportOtelMetricsIntervalInSeconds (), TimeUnit .SECONDS )
135+ .build ());
136+ }
133137
134- if (metricsConfig .useOtelExponentialHistogram ()) {
135- setExponentialHistogramAggregation (builder , metricsConfig );
136- }
138+ if (metricsConfig .getOtelAdditionalMetricsReader () != null ) {
139+ // additional metrics reader apart from the above. For instance,
140+ // an in-memory metric reader can be passed in for testing purposes.
141+ builder .registerMetricReader (metricsConfig .getOtelAdditionalMetricsReader ());
142+ }
137143
138- // Set resource to empty to avoid adding any default resource attributes. The receiver
139- // pipeline can choose to add the respective resource attributes if needed.
140- builder .setResource (Resource .empty ());
141-
142- sdkMeterProvider = builder .build ();
143-
144- // Register MeterProvider with the OpenTelemetry instance
145- openTelemetry = OpenTelemetrySdk .builder ().setMeterProvider (sdkMeterProvider ).build ();
146- LOGGER .info (
147- "OpenTelemetry initialization for {} completed with config: {}" ,
148- metricsConfig .getServiceName (),
149- metricsConfig );
150- } catch (Exception e ) {
151- String err = "OpenTelemetry initialization for " + metricsConfig .getServiceName () + " failed with config: "
152- + metricsConfig ;
153- LOGGER .error (err , e );
154- throw new VeniceException (err , e );
144+ if (metricsConfig .useOtelExponentialHistogram ()) {
145+ setExponentialHistogramAggregation (builder , metricsConfig );
155146 }
147+
148+ // Set resource to empty to avoid adding any default resource attributes. The receiver
149+ // pipeline can choose to add the respective resource attributes if needed.
150+ builder .setResource (Resource .empty ());
151+
152+ sdkMeterProvider = builder .build ();
153+
154+ // Register MeterProvider with the OpenTelemetry instance
155+ otel = OpenTelemetrySdk .builder ().setMeterProvider (sdkMeterProvider ).build ();
156+ LOGGER .info (
157+ "OpenTelemetry initialization for {} completed with config: {}" ,
158+ metricsConfig .getServiceName (),
159+ metricsConfig );
160+ } catch (Exception e ) {
161+ String err = "OpenTelemetry initialization for " + metricsConfig .getServiceName () + " failed with config: "
162+ + metricsConfig ;
163+ LOGGER .error (err , e );
164+ throw new VeniceException (err , e );
156165 }
157166
158- this .meter = openTelemetry .getMeter (transformMetricName (getMetricPrefix (), metricFormat ));
159- this .recordFailureMetric = MetricEntityStateBase .create (
160- CommonMetricsEntity .METRIC_RECORD_FAILURE .getMetricEntity (),
161- this ,
162- Collections .EMPTY_MAP ,
163- Attributes .empty ());
167+ return otel ;
164168 }
165169
166170 /**
0 commit comments