Skip to content

Commit

Permalink
NH-93561: use instrumenter to add sw span
Browse files Browse the repository at this point in the history
  • Loading branch information
cleverchuk committed Oct 17, 2024
1 parent a91703f commit 6550ae5
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,12 @@

import com.solarwinds.joboe.config.ConfigManager;
import com.solarwinds.joboe.config.ConfigProperty;
import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanBuilder;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.api.trace.Tracer;
import io.opentelemetry.context.Context;
import io.opentelemetry.context.Scope;
import io.opentelemetry.javaagent.bootstrap.CallDepth;
import io.opentelemetry.javaagent.extension.instrumentation.TypeInstrumentation;
import io.opentelemetry.javaagent.extension.instrumentation.TypeTransformer;
import io.opentelemetry.semconv.SemanticAttributes;
import java.sql.Statement;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.matcher.ElementMatcher;
Expand Down Expand Up @@ -91,24 +88,45 @@ public void transform(TypeTransformer transformer) {
public static class PrepareAdvice {

@Advice.OnMethodEnter(suppress = Throwable.class)
public static void injectComment(@Advice.Argument(value = 0, readOnly = false) String sql) {
if (sql.contains("traceparent")) {
public static void injectComment(
@Advice.Argument(value = 0, readOnly = false) String sql,
@Advice.Local("swoCallDepth") CallDepth callDepth,
@Advice.Local("swoSqlContext") String swoSql,
@Advice.Local("swoContext") Context context,
@Advice.Local("swoScope") Scope scope) {
callDepth = CallDepth.forClass(Statement.class);
if (callDepth.getAndIncrement() > 0) {
return;
}

Tracer tracer = GlobalOpenTelemetry.getTracer("com.solarwinds.jdbc", "1.0");
SpanBuilder spanBuilder =
tracer
.spanBuilder("sw.jdbc.context")
.setAttribute(SemanticAttributes.DB_STATEMENT, sql)
.setSpanKind(SpanKind.CLIENT);

Span span = spanBuilder.startSpan();
try (Scope scope = span.makeCurrent()) {
sql = TraceContextInjector.inject(currentContext(), sql);
StatementTracer.writeStackTraceSpec(currentContext());
} finally {
span.end();
Context parentContext = currentContext();
if (sql == null || !JdbcInstrumenter.getInstance().shouldStart(parentContext, sql)) {
return;
}

context = JdbcInstrumenter.getInstance().start(parentContext, sql);
scope = context.makeCurrent();

sql = TraceContextInjector.inject(currentContext(), sql);
StatementTracer.writeStackTraceSpec(currentContext());
swoSql = sql;
}

@Advice.OnMethodExit(onThrowable = Throwable.class, suppress = Throwable.class)
public static void stopSpan(
@Advice.Thrown Throwable throwable,
@Advice.Local("swoCallDepth") CallDepth callDepth,
@Advice.Local("swoSqlContext") String swoSql,
@Advice.Local("swoContext") Context context,
@Advice.Local("swoScope") Scope scope) {

if (callDepth == null || callDepth.decrementAndGet() > 0) {
return;
}

if (scope != null) {
scope.close();
JdbcInstrumenter.getInstance().end(context, swoSql, null, throwable);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.solarwinds.opentelemetry.instrumentation;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;

public final class JdbcInstrumenter {
private static final Instrumenter<String, Void> INSTANCE =
Instrumenter.<String, Void>builder(
GlobalOpenTelemetry.get(), "com.solarwinds.jdbc", (sql) -> "sw.jdbc.context")
.addAttributesExtractor(new SqlAttributeExtractor())
.buildInstrumenter();

public static Instrumenter<String, Void> getInstance() {
return INSTANCE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* © SolarWinds Worldwide, LLC. All rights reserved.
*
* 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.solarwinds.opentelemetry.instrumentation;

import io.opentelemetry.api.common.AttributesBuilder;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.semconv.SemanticAttributes;
import javax.annotation.Nullable;

public class SqlAttributeExtractor implements AttributesExtractor<String, Void> {
@Override
public void onStart(AttributesBuilder attributes, Context parentContext, String sql) {
attributes.put(SemanticAttributes.DB_STATEMENT, sql);
}

@Override
public void onEnd(
AttributesBuilder attributes,
Context context,
String sql,
@Nullable Void v,
@Nullable Throwable error) {}
}

0 comments on commit 6550ae5

Please sign in to comment.