Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter Telemetry based on span.events via Telemetry Processors #272

Merged
merged 14 commits into from
Mar 13, 2024
Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Use OpenTelemetry Java Agent Extensions to filter telemetry based on span events

This is a sample app demonstrating how to add a custom dimension to telemetry based on span events.
And then use telemetry processor to filter telemetry based on the new custom dimension.

## Build the extension artifact

To build the extension artifact, from this directory:

`cd ../extensions/CustomSpanExporter`
`../../../../mvnw package`

To run the application with the extension and Java agent, from this directory:

`cd ../../TelemetryFilteredBaseOnSpanEvents`

```
../../../mvnw package
export APPLICATIONINSIGHTS_CONNECTION_STRING=<Copy connection string from Application Insights Resource Overview>"
export APPLICATIONINSIGHTS_SELF_DIAGNOSTICS_LEVEL=debug

java -javaagent:target/agent/applicationinsights-agent.jar -Dotel.javaagent.extensions=../extensions/CustomSpanExporter/target/CustomSpanExporter-1.0-SNAPSHOT.jar -jar target/app.jar
```

Verify there is a log entry that starts with something as follows:
`{"ver":1,"name":"RemoteDependency","time":`

After it's finished running, go to Application Insights portal logs blade, query the following:

```kusto
dependencies
| where name == 'mySpan'
```

Verify that there are 3 custom dimensions in the result:
`controlledError`:`true`, // this is added by the java agent telemetry processor
`myCustomAttributeKey`: `myCustomAttributeValue`, // this is added by the application when creating the span
`myCustomAttributeKey2`: `myCustomAttributeValue2`. // this is added by the CustomSpanExporter extension
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.16</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.example</groupId>
<artifactId>TelemetryFilteredBaseOnSpanEvents</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<java.version>1.8</java.version>
<applicationinsights.agent.version>3.5.0</applicationinsights.agent.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.35.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-semconv</artifactId>
<version>1.30.1-alpha</version>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
<version>1.35.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry.instrumentation</groupId>
<artifactId>opentelemetry-instrumentation-api</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>io.opentelemetry.javaagent</groupId>
<artifactId>opentelemetry-javaagent-extension-api</artifactId>
<version>2.1.0-alpha</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>applicationinsights-agent</artifactId>
<version>${applicationinsights.agent.version}</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<finalName>app</finalName>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>copy-agent</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.microsoft.azure</groupId>
<artifactId>applicationinsights-agent</artifactId>
<version>${applicationinsights.agent.version}</version>
<outputDirectory>${project.build.directory}/agent</outputDirectory>
<destFileName>applicationinsights-agent.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>copy-resources</id>
<goals>
<goal>copy-resources</goal>
</goals>
</execution>
</executions>
<configuration>
<outputDirectory>${project.build.directory}/agent/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<include>applicationinsights.json</include>
</resource>
</resources>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.example;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Scope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);

public static void main(String[] args) throws InterruptedException {
Tracer tracer = GlobalOpenTelemetry.getTracer("TelemetryFilteredBaseOnSpanEvents", "1.0-SNAPSHOT");
Span span = tracer.spanBuilder("mySpan").startSpan(); // create a span
span.addEvent("Status code 404"); // add an event to the span
span.setAttribute("myCustomAttributeKey", "myCustomAttributeValue");
try (Scope scope = span.makeCurrent()) {
logger.debug("Hello world!");
Thread.sleep(10000);
} finally {
span.end(); // end the span
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"sampling": {
"percentage": 100
},
"preview": {
"processors": [
{
"type": "attribute",
"include": {
"matchType": "strict",
"attributes": [
{
"key": "myCustomAttributeKey",
"value": "myCustomAttributeValue",
"type": "string"
}
]
},
"actions": [
{
"action": "insert",
"key": "controlledError",
"value": true
}
]
}
]
trask marked this conversation as resolved.
Show resolved Hide resolved
},
"selfDiagnostics": {
"level": "DEBUG"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
<artifactItem>
<groupId>com.microsoft.azure</groupId>
<artifactId>applicationinsights-agent</artifactId>
<version>3.4.14</version>
<version>3.4.19</version>
<outputDirectory>${project.build.directory}/agent</outputDirectory>
<destFileName>applicationinsights-agent.jar</destFileName>
</artifactItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>extensions</artifactId>
<groupId>com.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>CustomSpanExporter</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-common</artifactId>
<version>1.35.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-trace</artifactId>
<version>1.35.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk-extension-autoconfigure-spi</artifactId>
<version>1.35.0</version>
</dependency>
<dependency>
<groupId>com.google.auto.service</groupId>
<artifactId>auto-service-annotations</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.example;

import com.google.auto.service.AutoService;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;

/**
* This is one of the main entry points for Instrumentation Agent's customizations. It allows
* configuring the {@link AutoConfigurationCustomizer}. See the {@link
* #customize(AutoConfigurationCustomizer)} method below.
*
* @see AutoConfigurationCustomizerProvider
*/
@AutoService(AutoConfigurationCustomizerProvider.class)
public class DemoAutoConfigurationCustomizerProvider implements AutoConfigurationCustomizerProvider {

@Override
public void customize(AutoConfigurationCustomizer autoConfiguration) {

autoConfiguration.addSpanExporterCustomizer((spanExporter, configProperties) -> {
return new DemoSpanExporter(spanExporter);
});

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.example;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.trace.data.DelegatingSpanData;
import io.opentelemetry.sdk.trace.data.SpanData;

public class DemoSpanData extends DelegatingSpanData {
private final Attributes attributes;

public DemoSpanData(SpanData delegate, Attributes attributes) {
super(delegate);
this.attributes = attributes;
}

@Override
public Attributes getAttributes() {
return attributes;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.example;

import io.opentelemetry.api.common.Attributes;
import io.opentelemetry.sdk.common.CompletableResultCode;
import io.opentelemetry.sdk.trace.data.EventData;
import io.opentelemetry.sdk.trace.data.SpanData;
import io.opentelemetry.sdk.trace.export.SpanExporter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class DemoSpanExporter implements SpanExporter {

private static final String MY_CUSTOM_ATTRIBUTE_KEY_2 = "myCustomAttributeKey2";
private static final String MY_CUSTOM_ATTRIBUTE_VALUE_2 = "myCustomAttributeValue2";

public final SpanExporter delegate;

public DemoSpanExporter(SpanExporter delegate) {
this.delegate = delegate;
}

@Override
public CompletableResultCode export(Collection<SpanData> collection) {
List<SpanData> copiedList = new ArrayList<>();
for(SpanData spanData : collection) {
List<EventData> events = spanData.getEvents();
if (events != null && !events.isEmpty()) {
for (EventData eventData : events) {
if (eventData.getName().trim().contains("Status code 404")) {
Attributes attributes = Attributes.builder()
.putAll(spanData.getAttributes())
.put(MY_CUSTOM_ATTRIBUTE_KEY_2, MY_CUSTOM_ATTRIBUTE_VALUE_2)
.build();
SpanData customSpanData = new DemoSpanData(spanData, attributes);
copiedList.add(customSpanData);
} else {
copiedList.add(spanData);
}
}
}
}
return delegate.export(copiedList);
}

@Override
public CompletableResultCode flush() {
return CompletableResultCode.ofSuccess();
}

@Override
public CompletableResultCode shutdown() {
return CompletableResultCode.ofSuccess();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
com.example.DemoAutoConfigurationCustomizerProvider
Loading