Skip to content

Commit

Permalink
Move around where we configure the metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
matt-richardson committed Nov 27, 2024
1 parent 8875b99 commit 4b60ace
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 52 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.octopus.teamcity.opentelemetry.server.endpoints;

import com.octopus.teamcity.opentelemetry.server.SetProjectConfigurationSettingsRequest;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.trace.SpanProcessor;
import jetbrains.buildServer.serverSide.SBuild;
Expand All @@ -13,7 +14,7 @@
public interface IOTELEndpointHandler {
ModelAndView getBuildOverviewModelAndView(SBuild build, Map<String, String> params, String traceId);

SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params);
SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params, MeterProvider meterProvider);
@Nullable
MetricExporter buildMetricsExporter(String endpoint, Map<String, String> params);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.octopus.teamcity.opentelemetry.server.*;
import com.octopus.teamcity.opentelemetry.server.endpoints.IOTELEndpointHandler;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
Expand Down Expand Up @@ -36,7 +37,7 @@ public ModelAndView getBuildOverviewModelAndView(SBuild build, Map<String, Strin
}

@Override
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params) {
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params, MeterProvider meterProvider) {
Map<String, String> headers = new HashMap<>();
params.forEach((k, v) -> {
if (k.startsWith(PROPERTY_KEY_HEADERS)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.octopus.teamcity.opentelemetry.server.*;
import com.octopus.teamcity.opentelemetry.server.endpoints.IOTELEndpointHandler;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.otlp.metrics.OtlpGrpcMetricExporter;
import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
Expand Down Expand Up @@ -56,12 +55,12 @@ public ModelAndView getBuildOverviewModelAndView(SBuild build, Map<String, Strin
}

@Override
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params) {
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params, MeterProvider meterProvider) {
Map<String, String> headers = new HashMap<>();
//todo: add a setting to say "use classic" or "use environments"
headers.put("x-honeycomb-dataset", params.get(PROPERTY_KEY_HONEYCOMB_DATASET));
headers.put("x-honeycomb-team", EncryptUtil.unscramble(params.get(PROPERTY_KEY_HONEYCOMB_APIKEY)));
return buildGrpcSpanProcessor(headers, endpoint);
return buildGrpcSpanProcessor(headers, endpoint, meterProvider);
}

@Override
Expand All @@ -77,15 +76,16 @@ public MetricExporter buildMetricsExporter(String endpoint, Map<String, String>
return null;
}

private SpanProcessor buildGrpcSpanProcessor(Map<String, String> headers, String exporterEndpoint) {
private SpanProcessor buildGrpcSpanProcessor(Map<String, String> headers, String exporterEndpoint, MeterProvider meterProvider) {
var spanExporterBuilder = OtlpGrpcSpanExporter.builder();
headers.forEach(spanExporterBuilder::addHeader);
var spanExporter = spanExporterBuilder
.setEndpoint(exporterEndpoint)
.setMeterProvider(meterProvider)
.build();

return BatchSpanProcessor.builder(spanExporter)
.setMeterProvider(GlobalOpenTelemetry.getMeterProvider())
.setMeterProvider(meterProvider)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.octopus.teamcity.opentelemetry.server.SetProjectConfigurationSettingsRequest;
import com.octopus.teamcity.opentelemetry.server.endpoints.IOTELEndpointHandler;
import io.opentelemetry.api.metrics.MeterProvider;
import io.opentelemetry.exporter.zipkin.ZipkinSpanExporter;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.trace.SpanProcessor;
Expand Down Expand Up @@ -36,7 +37,7 @@ public ModelAndView getBuildOverviewModelAndView(SBuild build, Map<String, Strin
}

@Override
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params) {
public SpanProcessor buildSpanProcessor(String endpoint, Map<String, String> params, MeterProvider meterProvider) {
return buildZipkinSpanProcessor(endpoint);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.octopus.teamcity.opentelemetry.server.helpers;

import com.octopus.teamcity.opentelemetry.common.PluginConstants;
import com.octopus.teamcity.opentelemetry.server.endpoints.OTELEndpointFactory;
import io.opentelemetry.sdk.trace.SpanProcessor;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.semconv.resource.attributes.ResourceAttributes;
import jetbrains.buildServer.serverSide.BuildPromotion;
import jetbrains.buildServer.serverSide.ProjectManager;
import org.apache.log4j.Logger;
Expand Down Expand Up @@ -45,11 +48,13 @@ public OTELHelper getOTELHelper(BuildPromotion build) {
var endpoint = params.get(PROPERTY_KEY_ENDPOINT);

var otelHandler = otelEndpointFactory.getOTELEndpointHandler(params.get(PROPERTY_KEY_SERVICE));
var spanProcessor = otelHandler.buildSpanProcessor(endpoint, params);
var metricsExporter = otelHandler.buildMetricsExporter(endpoint, params);
var serviceNameResource = Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, PluginConstants.SERVICE_NAME));
var meterProvider = OTELMetrics.getOTELMeterProvider(metricsExporter, serviceNameResource);
var spanProcessor = otelHandler.buildSpanProcessor(endpoint, params, meterProvider);

long startTime = System.nanoTime();
var otelHelper = new OTELHelperImpl(spanProcessor, metricsExporter, String.valueOf(buildId));
var otelHelper = new OTELHelperImpl(spanProcessor, String.valueOf(buildId));
long endTime = System.nanoTime();

long duration = (endTime - startTime);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.exporter.logging.LoggingMetricExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.resources.Resource;
import io.opentelemetry.sdk.trace.SdkTracerProvider;
import io.opentelemetry.sdk.trace.SpanProcessor;
Expand All @@ -23,10 +19,8 @@
import org.jetbrains.annotations.NotNull;

import javax.annotation.Nullable;
import java.time.Duration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class OTELHelperImpl implements OTELHelper {
static Logger LOG = Logger.getLogger(OTELHelperImpl.class.getName());
Expand All @@ -35,17 +29,13 @@ public class OTELHelperImpl implements OTELHelper {
private final ConcurrentHashMap<String, Span> spanMap;
private final SdkTracerProvider sdkTracerProvider;
private final String helperName;
private static final AtomicBoolean metricsConfigured = new AtomicBoolean(false);

public OTELHelperImpl(
@NotNull SpanProcessor spanProcessor,
@Nullable MetricExporter metricExporter,
@NotNull String helperName) {
this.helperName = helperName;
var serviceNameResource = Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, PluginConstants.SERVICE_NAME));

configureMetricsExport(metricExporter, serviceNameResource);

this.sdkTracerProvider = SdkTracerProvider.builder()
.setResource(Resource.getDefault().merge(serviceNameResource))
.addSpanProcessor(spanProcessor)
Expand All @@ -58,35 +48,6 @@ public OTELHelperImpl(
this.spanMap = new ConcurrentHashMap<>();
}

public static void configureMetricsExport(@Nullable MetricExporter metricExporter, Resource serviceNameResource) {
if (metricsConfigured.get()) return;
metricsConfigured.set(true);

var loggingMetricExporter = LoggingMetricExporter.create();
var consoleLogMetricReader = PeriodicMetricReader.builder(loggingMetricExporter)
.setInterval(Duration.ofSeconds(10))
.build();
var meterProviderBuilder = SdkMeterProvider.builder()
.setResource(Resource.getDefault().merge(serviceNameResource))
.registerMetricReader(consoleLogMetricReader);
if (metricExporter != null) {
var providedMetricExporterBuilder = PeriodicMetricReader.builder(metricExporter)
.setInterval(Duration.ofSeconds(10))
.build();
meterProviderBuilder
.registerMetricReader(providedMetricExporterBuilder);
}
var sdkMeterProvider = meterProviderBuilder.build();
var globalOpenTelemetry = OpenTelemetrySdk.builder()
.setMeterProvider(sdkMeterProvider)
.build();

GlobalOpenTelemetry.set(globalOpenTelemetry);

// Shutdown hooks to close resources properly
Runtime.getRuntime().addShutdownHook(new Thread(sdkMeterProvider::close));
}

@Override
public boolean isReady() {
return this.openTelemetry != null && this.tracer != null && this.spanMap != null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.octopus.teamcity.opentelemetry.server.helpers;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.exporter.logging.LoggingMetricExporter;
import io.opentelemetry.sdk.OpenTelemetrySdk;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;
import io.opentelemetry.sdk.metrics.export.MetricExporter;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;
import io.opentelemetry.sdk.resources.Resource;

import javax.annotation.Nullable;
import java.time.Duration;
import java.util.concurrent.atomic.AtomicBoolean;

public class OTELMetrics {

private static final AtomicBoolean metricsConfigured = new AtomicBoolean(false);
private static SdkMeterProvider sdkMeterProvider;

public static SdkMeterProvider getOTELMeterProvider(@Nullable MetricExporter metricExporter, Resource serviceNameResource) {
if (metricsConfigured.get()) return sdkMeterProvider;
metricsConfigured.set(true);

var loggingMetricExporter = LoggingMetricExporter.create();
var consoleLogMetricReader = PeriodicMetricReader.builder(loggingMetricExporter)
.setInterval(Duration.ofSeconds(10))
.build();
var meterProviderBuilder = SdkMeterProvider.builder()
.setResource(Resource.getDefault().merge(serviceNameResource))
.registerMetricReader(consoleLogMetricReader);
if (metricExporter != null) {
var providedMetricExporterBuilder = PeriodicMetricReader.builder(metricExporter)
.setInterval(Duration.ofSeconds(10))
.build();
meterProviderBuilder
.registerMetricReader(providedMetricExporterBuilder);
}
sdkMeterProvider = meterProviderBuilder.build();
var globalOpenTelemetry = OpenTelemetrySdk.builder()
.setMeterProvider(sdkMeterProvider)
.build();

GlobalOpenTelemetry.set(globalOpenTelemetry);

// Shutdown hooks to close resources properly
Runtime.getRuntime().addShutdownHook(new Thread(sdkMeterProvider::close));
return sdkMeterProvider;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class OTELHelperTest {
@BeforeEach
void setUp() {
GlobalOpenTelemetry.resetForTest();
this.otelHelper = new OTELHelperImpl(mock(SpanProcessor.class, RETURNS_DEEP_STUBS), null, "helperNamr");
this.otelHelper = new OTELHelperImpl(mock(SpanProcessor.class, RETURNS_DEEP_STUBS), "helperNamr");
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class TeamCityBuildListenerTest {
@BeforeEach
void setUp(@Mock EventDispatcher<BuildServerListener> buildServerListenerEventDispatcher) {
GlobalOpenTelemetry.resetForTest();
this.otelHelper = new OTELHelperImpl(mock(SpanProcessor.class, RETURNS_DEEP_STUBS), null, "helper");
this.otelHelper = new OTELHelperImpl(mock(SpanProcessor.class, RETURNS_DEEP_STUBS), "helper");
this.factory = mock(OTELHelperFactory.class, RETURNS_DEEP_STUBS);

var buildStorageManager = mock(BuildStorageManager.class, RETURNS_DEEP_STUBS);
Expand Down

0 comments on commit 4b60ace

Please sign in to comment.