Skip to content

Commit

Permalink
Tracing: added OpenTelemetry implementation
Browse files Browse the repository at this point in the history
Added TracingInfo and TracingInfoFactory implementations in separate
driver-opentelemetry module.
  • Loading branch information
wprzytula committed Aug 31, 2022
1 parent 6a10cf3 commit be290dc
Show file tree
Hide file tree
Showing 4 changed files with 464 additions and 0 deletions.
149 changes: 149 additions & 0 deletions driver-opentelemetry/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
<!--
Copyright DataStax, Inc.
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.
-->
<!--
Copyright (C) 2021 ScyllaDB
Modified by ScyllaDB
-->
<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/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.scylladb</groupId>
<artifactId>scylla-driver-parent</artifactId>
<version>3.11.2.1-SNAPSHOT</version>
</parent>

<artifactId>scylla-driver-opentelemetry</artifactId>
<name>Java Driver for Scylla and Apache Cassandra - OpenTelemetry integration</name>
<description>An extension of Java Driver for Scylla and Apache Cassandra by adding
functionality of creating traces and spans in OpenTelemetry format.
</description>

<dependencyManagement>

<dependencies>

<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>

</dependencies>

</dependencyManagement>

<dependencies>

<!-- driver dependencies -->

<dependency>
<groupId>com.scylladb</groupId>
<artifactId>scylla-driver-core</artifactId>
</dependency>

<!-- OpenTelemetry -->

<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-api</artifactId>
<version>1.9.1</version>
</dependency>

<!-- tests -->

<dependency>
<groupId>com.scylladb</groupId>
<artifactId>scylla-driver-core</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-sdk</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<scope>test</scope>
</dependency>

</dependencies>

<build>
<plugins>

<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<!-- Disable check-jdk6 check for this submodule. -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.15</version>
<executions>
<execution>
<id>check-jdk6</id>
<phase>process-classes</phase>
<goals>
<goal>check</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
<execution>
<id>check-jdk8</id>
<goals>
<goal>check</goal>
</goals>
<configuration>
<skip>true</skip>
</configuration>
</execution>
</executions>
</plugin>

</plugins>

</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
/*
* Copyright (C) 2021 ScyllaDB
*
* 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.datastax.driver.opentelemetry;

import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.policies.LoadBalancingPolicy;
import com.datastax.driver.core.policies.RetryPolicy;
import com.datastax.driver.core.policies.SpeculativeExecutionPolicy;
import com.datastax.driver.core.tracing.PrecisionLevel;
import com.datastax.driver.core.tracing.TracingInfo;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import java.net.InetAddress;

public class OpenTelemetryTracingInfo implements TracingInfo {
private Span span;
private final Tracer tracer;
private final Context context;
private boolean tracingStarted;
private final PrecisionLevel precision;

protected OpenTelemetryTracingInfo(Tracer tracer, Context context, PrecisionLevel precision) {
this.tracer = tracer;
this.context = context;
this.precision = precision;
this.tracingStarted = false;
}

public Tracer getTracer() {
return tracer;
}

public Context getContext() {
return context.with(span);
}

private void assertStarted() {
assert tracingStarted : "TracingInfo.setStartTime must be called before any other method";
}

public PrecisionLevel getPrecision() {
return precision;
}

@Override
public void setNameAndStartTime(String name) {
assert !tracingStarted : "TracingInfo.setStartTime may only be called once.";
tracingStarted = true;
span = tracer.spanBuilder(name).setParent(context).startSpan();
}

@Override
public void setConsistencyLevel(ConsistencyLevel consistency) {
assertStarted();
span.setAttribute("db.scylla.consistency_level", consistency.toString());
}

public void setStatement(String statement) {
assertStarted();
if (currentPrecisionLevelIsAtLeast(PrecisionLevel.FULL)) {
span.setAttribute("db.scylla.statement", statement);
}
}

public void setHostname(String hostname) {
assertStarted();
if (currentPrecisionLevelIsAtLeast(PrecisionLevel.FULL)) {
span.setAttribute("net.peer.name", hostname);
}
}

@Override
public void setStatementType(String statementType) {
assertStarted();
span.setAttribute("db.scylla.statement_type", statementType);
}

@Override
public void setRetryPolicy(RetryPolicy retryPolicy) {
assertStarted();
span.setAttribute("db.scylla.retry_policy", retryPolicy.getClass().getSimpleName());
}

@Override
public void setLoadBalancingPolicy(LoadBalancingPolicy loadBalancingPolicy) {
assertStarted();
span.setAttribute(
"db.scylla.load_balancing_policy", loadBalancingPolicy.getClass().getSimpleName());
}

@Override
public void setSpeculativeExecutionPolicy(SpeculativeExecutionPolicy speculativeExecutionPolicy) {
assertStarted();
span.setAttribute(
"db.scylla.speculative_execution_policy",
speculativeExecutionPolicy.getClass().getSimpleName());
}

@Override
public void setBatchSize(int batchSize) {
assertStarted();
span.setAttribute("db.scylla.batch_size", String.valueOf(batchSize));
}

@Override
public void setAttemptCount(int attemptCount) {
assertStarted();
span.setAttribute("db.scylla.attempt_count", String.valueOf(attemptCount));
}

@Override
public void setShardID(int shardID) {
assertStarted();
span.setAttribute("db.scylla.shard_id", String.valueOf(shardID));
}

@Override
public void setPeerName(String peerName) {
assertStarted();
span.setAttribute("net.peer.name", peerName);
}

@Override
public void setPeerIP(InetAddress peerIP) {
assertStarted();
span.setAttribute("net.peer.ip", peerIP.getHostAddress());
}

@Override
public void setPeerPort(int peerPort) {
assertStarted();
span.setAttribute("net.peer.port", String.valueOf(peerPort));
}

@Override
public void setFetchSize(int fetchSize) {
assertStarted();
span.setAttribute("db.scylla.fetch_size", Integer.toString(fetchSize));
}

@Override
public void setHasMorePages(boolean hasMorePages) {
assertStarted();
span.setAttribute("db.scylla.has_more_pages", Boolean.toString(hasMorePages));
}

@Override
public void setRowsCount(int rowsCount) {
assertStarted();
span.setAttribute("db.scylla.rows_count", Integer.toString(rowsCount));
}

@Override
public void setStatement(String statement, int limit) {
assertStarted();
if (currentPrecisionLevelIsAtLeast(PrecisionLevel.FULL)) {
if (statement.length() > limit) statement = statement.substring(0, limit);
span.setAttribute("db.scylla.statement", statement);
}
}

@Override
public void setKeyspace(String keyspace) {
assertStarted();
span.setAttribute("db.scylla.keyspace", keyspace);
}

@Override
public void setPartitionKey(String partitionKey) {
assertStarted();
span.setAttribute("db.scylla.partition_key", partitionKey);
}

@Override
public void setTable(String table) {
assertStarted();
span.setAttribute("db.scylla.table", table);
}

@Override
public void setOperationType(String operationType) {
assertStarted();
span.setAttribute("db.operation", operationType);
}

@Override
public void setReplicas(String replicas) {
assertStarted();
span.setAttribute("db.scylla.replicas", replicas);
}

private io.opentelemetry.api.trace.StatusCode mapStatusCode(StatusCode code) {
switch (code) {
case OK:
return io.opentelemetry.api.trace.StatusCode.OK;
case ERROR:
return io.opentelemetry.api.trace.StatusCode.ERROR;
}
return null;
}

@Override
public void recordException(Exception exception) {
assertStarted();
span.recordException(exception);
}

@Override
public void setStatus(StatusCode code, String description) {
assertStarted();
span.setStatus(mapStatusCode(code), description);
}

@Override
public void setStatus(StatusCode code) {
assertStarted();
span.setStatus(mapStatusCode(code));
}

@Override
public void tracingFinished() {
assertStarted();
span.end();
}

private boolean currentPrecisionLevelIsAtLeast(PrecisionLevel requiredLevel) {
return requiredLevel.compareTo(precision) <= 0;
}
}
Loading

0 comments on commit be290dc

Please sign in to comment.