Skip to content

Commit

Permalink
Adding the Otel Implementation (#2687)
Browse files Browse the repository at this point in the history
OpenTelemetry implementation for Athenz Metrics interface

Signed-off-by: salladi <sahiti.alladi@yahooinc.com>
  • Loading branch information
salladi30 authored Aug 16, 2024
1 parent fea1fe6 commit ab717de
Show file tree
Hide file tree
Showing 5 changed files with 456 additions and 6 deletions.
53 changes: 47 additions & 6 deletions libs/java/server_common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,50 @@
<aws.secretmanager.version>2.0.2</aws.secretmanager.version>
<uuid.version>5.1.0</uuid.version>
<hamcrest.json.version>0.3</hamcrest.json.version>
<opentelemetry.version>1.40.0</opentelemetry.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>${opentelemetry.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-otlp</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-common</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-metrics</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
Expand Down Expand Up @@ -94,7 +135,7 @@
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>${uuid.version}</version>
</dependency>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>athenz-auth-core</artifactId>
Expand Down Expand Up @@ -278,11 +319,11 @@
<artifactId>athenz-zms-core</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>com.yahoo.athenz</groupId>
<artifactId>athenz-zms-java-client</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>com.yahoo.athenz</groupId>
<artifactId>athenz-zms-java-client</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* Copyright The Athenz Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.athenz.common.metrics.impl;

import com.yahoo.athenz.common.metrics.Metric;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.metrics.LongCounter;
import io.opentelemetry.api.metrics.Meter;
import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;

public class OpenTelemetryMetric implements Metric {
final Meter meter;
final Tracer tracer;

private static final String REQUEST_DOMAIN_NAME = "requestDomainName";
private static final String PRINCIPAL_DOMAIN_NAME = "principalDomainName";
private static final String HTTP_METHOD_NAME = "httpMethodName";
private static final String HTTP_STATUS = "httpStatus";
private static final String API_NAME = "apiName";

public OpenTelemetryMetric(OpenTelemetry openTelemetry) {
meter = openTelemetry.getMeter("meter");
tracer = openTelemetry.getTracer("tracer");
}

@Override
public void increment(String metric) {
LongCounter counter = meter.counterBuilder(metric).build();
counter.add(1);
}

@Override
public void increment(String metric, String requestDomainName) {
increment(metric, requestDomainName, 1);
}

@Override
public void increment(String metric, String requestDomainName, int count) {
LongCounter counter = meter.counterBuilder(metric).build();
Attributes attributes = Attributes.builder()
.put(REQUEST_DOMAIN_NAME, requestDomainName)
.build();
counter.add(count, attributes);
}

@Override
public void increment(String metric, String requestDomainName, String principalDomainName) {
increment(metric, requestDomainName, principalDomainName, 1);
}

@Override
public void increment(String metric, String requestDomainName, String principalDomainName, String httpMethod, int httpStatus, String apiName) {
LongCounter counter = meter.counterBuilder(metric).build();
Attributes attributes = Attributes.builder()
.put(REQUEST_DOMAIN_NAME, requestDomainName)
.put(PRINCIPAL_DOMAIN_NAME, principalDomainName)
.put(HTTP_METHOD_NAME, httpMethod)
.put(HTTP_STATUS, Integer.toString(httpStatus))
.put(API_NAME, apiName)
.build();
counter.add(1, attributes);
}

@Override
public void increment(String metric, String requestDomainName, String principalDomainName, int count) {
LongCounter counter = meter.counterBuilder(metric).build();
Attributes attributes = Attributes.builder()
.put(REQUEST_DOMAIN_NAME, requestDomainName)
.put(PRINCIPAL_DOMAIN_NAME, principalDomainName)
.build();
counter.add(count, attributes);
}

@Override
public Object startTiming(String metric, String requestDomainName) {
Span span = tracer.spanBuilder(metric).startSpan();
Context context = Context.current().with(span);
return new Timer(context, System.currentTimeMillis(), span);
}

@Override
public void stopTiming(Object timerMetric) {
//not necessary method
}

@Override
public void stopTiming(Object timerMetric, String requestDomainName, String principalDomainName) {
stopTiming(timerMetric, requestDomainName, principalDomainName, null, -1, null);
}

@Override
public void stopTiming(Object timerMetric, String requestDomainName, String principalDomainName,
String httpMethod, int httpStatus, String apiName) {
Timer timer = (Timer) timerMetric;
long duration = System.currentTimeMillis() - timer.start;
Span span = timer.getSpan();
span.setAttribute("duration", duration);
span.setAttribute(REQUEST_DOMAIN_NAME, requestDomainName);
span.setAttribute(PRINCIPAL_DOMAIN_NAME, principalDomainName);

if (httpMethod != null) {
span.setAttribute(HTTP_METHOD_NAME, httpMethod);
}
if (httpStatus != -1) {
span.setAttribute(HTTP_STATUS, Integer.toString(httpStatus));
}
if (apiName != null) {
span.setAttribute(API_NAME, apiName);
}
span.end();
}

@Override
public void flush() {
//doesn't require flushing
}

@Override
public void quit() {
//don't need to quit anything
}

static class Timer {
private final Context context;
private final long start;
private final Span span;
public Timer(Context context, long start, Span span) {
this.context = context;
this.start = start;
this.span = span;
}
public Span getSpan() {
return span;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright The Athenz Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.yahoo.athenz.common.metrics.impl;

import com.yahoo.athenz.common.metrics.Metric;
import com.yahoo.athenz.common.metrics.MetricFactory;
import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;

/*
In order to use the otlp exporters you need to configure the environment variables.
You need to set the endpoint (OTEL_EXPORTER_OTLP_ENDPOINT) which is defaulted to
"http:://localhost:4317" and the attributes (OTEL_RESOURCE_ATTRIBUTES) which is defaulted
to "service.name=my-service." AutoConfiguredOpenTelemetrySdk automatically reads the
configuration and sets up the exporter.
*/

public class OpenTelemetryMetricFactory implements MetricFactory {
@Override
public Metric create() {
OpenTelemetry openTelemetry = initialize();
return new OpenTelemetryMetric(openTelemetry);
}

public OpenTelemetry initialize() {
return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright The Athenz Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.yahoo.athenz.common.metrics.impl;

import static org.testng.Assert.*;
import com.yahoo.athenz.common.metrics.Metric;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
public class OpenTelemetryMetricFactoryTest {
private OpenTelemetryMetricFactory factory;

@BeforeMethod
public void setUp() {
factory = new OpenTelemetryMetricFactory();
}

@Test
public void testCreate() {
Metric metric = factory.create();
assertNotNull(metric);
assertTrue(metric instanceof OpenTelemetryMetric);
}
}
Loading

0 comments on commit ab717de

Please sign in to comment.