From 51a60cd67fd933a94f8b8c9e293542cc7355cd15 Mon Sep 17 00:00:00 2001 From: wusheng Date: Sun, 19 Feb 2017 00:19:49 +0800 Subject: [PATCH] Add log event, and a sample to trace db.preparedStatement. --- skywalking-commons/skywalking-trace/pom.xml | 8 +- .../java/com/a/eye/skywalking/trace/Span.java | 121 ++++++++++++------ .../com/a/eye/skywalking/trace/tag/Tags.java | 14 +- .../skywalking/context/ContextManager.java | 2 +- .../plugin/jdbc/PreparedStatementTracing.java | 55 ++++---- 5 files changed, 125 insertions(+), 75 deletions(-) diff --git a/skywalking-commons/skywalking-trace/pom.xml b/skywalking-commons/skywalking-trace/pom.xml index 98b1dfb70..f640eae31 100644 --- a/skywalking-commons/skywalking-trace/pom.xml +++ b/skywalking-commons/skywalking-trace/pom.xml @@ -11,5 +11,11 @@ skywalking-trace - + + + com.a.eye + skywalking-logging-api + ${project.version} + + diff --git a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/Span.java b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/Span.java index 8db7f1e6f..5261d59ff 100644 --- a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/Span.java +++ b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/Span.java @@ -1,5 +1,7 @@ package com.a.eye.skywalking.trace; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -10,19 +12,19 @@ import java.util.Map; * Span is a concept from OpenTracing Spec, also from Google Dapper Paper. * Traces in OpenTracing are defined implicitly by their Spans. * - * [Span A] ←←←(the root span) - * | - * +------+------+ - * | | - * [Span B] [Span C] ←←←(Span C is a `ChildOf` Span A) - * | | - * [Span D] +---+-------+ - * | | - * [Span E] [Span F] >>> [Span G] >>> [Span H] - * ↑ - * ↑ - * ↑ - * (Span G `FollowsFrom` Span F) + * [Span A] ←←←(the root span) + * | + * +------+------+ + * | | + * [Span B] [Span C] ←←←(Span C is a `ChildOf` Span A) + * | | + * [Span D] +---+-------+ + * | | + * [Span E] [Span F] >>> [Span G] >>> [Span H] + * ↑ + * ↑ + * ↑ + * (Span G `FollowsFrom` Span F) * * Created by wusheng on 2017/2/17. */ @@ -53,7 +55,7 @@ public class Span { * * {@see https://github.com/opentracing/specification/blob/master/specification.md#set-a-span-tag} */ - private final Map tags; + private final Map tags; /** * Log is a concept from OpenTracing spec. @@ -67,16 +69,16 @@ public class Span { * This span must belong a {@link TraceSegment}, also is a part of Distributed Trace. * * @param spanId given by the creator, and must be unique id in the {@link TraceSegment} - * @param parentSpanId given by the creator, and must be an existed span id in the {@link TraceSegment}. - * Value -1 means no parent span if this {@link TraceSegment}. + * @param parentSpanId given by the creator, and must be an existed span id in the {@link TraceSegment}. Value -1 + * means no parent span if this {@link TraceSegment}. * @param operationName {@link #operationName} */ - private Span(int spanId, int parentSpanId, String operationName){ + private Span(int spanId, int parentSpanId, String operationName) { this.spanId = spanId; this.parentSpanId = parentSpanId; this.startTime = System.currentTimeMillis(); this.operationName = operationName; - this.tags = new HashMap(); + this.tags = new HashMap(); this.logs = new ArrayList(); } @@ -87,7 +89,7 @@ public class Span { * @param spanId given by the creator, and must be unique id in the {@link TraceSegment} * @param operationName {@link #operationName} */ - public Span(int spanId, String operationName){ + public Span(int spanId, String operationName) { this(spanId, -1, operationName); } @@ -98,7 +100,7 @@ public class Span { * @param parentSpan {@link Span} * @param operationName {@link #operationName} */ - public Span(int spanId, Span parentSpan, String operationName){ + public Span(int spanId, Span parentSpan, String operationName) { this(spanId, parentSpan.spanId, operationName); } @@ -108,7 +110,7 @@ public class Span { * * @param owner of the Span. */ - public void finish(TraceSegment owner){ + public void finish(TraceSegment owner) { this.endTime = System.currentTimeMillis(); owner.archive(this); } @@ -136,7 +138,7 @@ public class Span { * * @return */ - public final Map getTags() { + public final Map getTags() { return Collections.unmodifiableMap(tags); } @@ -146,13 +148,12 @@ public class Span { * @param key the given tag key. * @return tag value. */ - public Object getTag(String key){ + public Object getTag(String key) { return tags.get(key); } /** - * This method is from opentracing-java. - * {@see https://github.com/opentracing/opentracing-java/blob/release-0.20.9/opentracing-api/src/main/java/io/opentracing/Span.java#L91} + * This method is from opentracing-java. {@see https://github.com/opentracing/opentracing-java/blob/release-0.20.9/opentracing-api/src/main/java/io/opentracing/Span.java#L91} * * Log key:value pairs to the Span with the current walltime timestamp. * @@ -161,40 +162,82 @@ public class Span { * *

A contrived example (using Guava, which is not required): *

{@code
-        span.log(
-            ImmutableMap.Builder()
-            .put("event", "soft error")
-            .put("type", "cache timeout")
-            .put("waited.millis", 1500)
-            .build());
-        }
+ * span.log( + * ImmutableMap.Builder() + * .put("event", "soft error") + * .put("type", "cache timeout") + * .put("waited.millis", 1500) + * .build()); + * } * * @param fields key:value log fields. Tracer implementations should support String, numeric, and boolean values; - * some may also support arbitrary Objects. + * some may also support arbitrary Objects. * @return the Span, for chaining * @see Span#log(String) */ - public Span log(Map fields){ + public Span log(Map fields) { logs.add(new LogData(System.currentTimeMillis(), fields)); return this; } /** - * This method is from opentracing-java. - * {@see https://github.com/opentracing/opentracing-java/blob/release-0.20.9/opentracing-api/src/main/java/io/opentracing/Span.java#L120} + * Record an exception event of the current walltime timestamp. + * + * @param t any subclass of {@link Throwable}, which occurs in this span. + * @return the Span, for chaining + */ + public Span log(Throwable t) { + Map exceptionFields = new HashMap(); + exceptionFields.put("error.kind", t.getClass().getName()); + exceptionFields.put("message", t.getMessage()); + exceptionFields.put("stack", ThrowableTransformer.INSTANCE.convert2String(t, 4000)); + + logs.add(new LogData(System.currentTimeMillis(), exceptionFields)); + + return this; + } + + private enum ThrowableTransformer { + INSTANCE; + + private String convert2String(Throwable e, int maxLength) { + ByteArrayOutputStream buf = null; + StringBuilder expMessage = new StringBuilder(); + try { + buf = new ByteArrayOutputStream(); + Throwable causeException = e; + while (expMessage.length() < maxLength && causeException != null) { + causeException.printStackTrace(new java.io.PrintWriter(buf, true)); + expMessage.append(buf.toString()); + causeException = causeException.getCause(); + } + + } finally { + try { + buf.close(); + } catch (IOException ioe) { + } + } + + return (maxLength > expMessage.length() ? expMessage : expMessage.substring(0, maxLength)).toString(); + } + } + + /** + * This method is from opentracing-java. {@see https://github.com/opentracing/opentracing-java/blob/release-0.20.9/opentracing-api/src/main/java/io/opentracing/Span.java#L120} * * Record an event at the current walltime timestamp. * * Shorthand for * *
{@code
-        span.log(Collections.singletonMap("event", event));
-        }
+ * span.log(Collections.singletonMap("event", event)); + * } * * @param event the event value; often a stable identifier for a moment in the Span lifecycle * @return the Span, for chaining */ - public Span log(String event){ + public Span log(String event) { log(Collections.singletonMap("event", event)); return this; } diff --git a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java index a0171e9f2..36909d46d 100644 --- a/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java +++ b/skywalking-commons/skywalking-trace/src/main/java/com/a/eye/skywalking/trace/tag/Tags.java @@ -1,5 +1,7 @@ package com.a.eye.skywalking.trace.tag; +import com.a.eye.skywalking.trace.Span; + /** * The span tags are supported by sky-walking engine. * As default, all tags will be stored, but these ones have particular meanings. @@ -21,10 +23,16 @@ public final class Tags { public static final IntTag HTTP_STATUS = new IntTag("http.status_code"); /** - * SPAN_KIND hints at the relationship between spans. - * e.g. cl = client; se = server. + * SPAN_KIND represents the kind of span. + * e.g. db=database, */ - public static final StringTag SPAN_KIND = new StringTag("span.kind"); + public static final class SPAN_KIND{ + private static StringTag SPAN_KIND_TAG = new StringTag("span.kind"); + + public static void asDBAccess(Span span){ + SPAN_KIND_TAG.set(span, "db"); + } + } /** * COMPONENT is a low-cardinality identifier of the module, library, or package that is instrumented. diff --git a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/context/ContextManager.java b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/context/ContextManager.java index 9c6e8f054..7c89f0cae 100644 --- a/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/context/ContextManager.java +++ b/skywalking-sniffer/skywalking-api/src/main/java/com/a/eye/skywalking/context/ContextManager.java @@ -30,7 +30,7 @@ public enum ContextManager implements TracerContextListener { private static ThreadLocal CONTEXT = new ThreadLocal<>(); - public TracerContext get() { + private TracerContext get() { TracerContext segment = CONTEXT.get(); if (segment == null) { segment = new TracerContext(); diff --git a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java index ec57bb8e5..464ea055d 100644 --- a/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java +++ b/skywalking-sniffer/skywalking-sdk-plugin/jdbc-plugin/src/main/java/com/a/eye/skywalking/plugin/jdbc/PreparedStatementTracing.java @@ -1,43 +1,36 @@ package com.a.eye.skywalking.plugin.jdbc; -import com.a.eye.skywalking.model.Identification; -import com.a.eye.skywalking.invoke.monitor.RPCClientInvokeMonitor; -import com.a.eye.skywalking.plugin.jdbc.define.JDBCBuriedPointType; - +import com.a.eye.skywalking.context.ContextManager; +import com.a.eye.skywalking.trace.Span; +import com.a.eye.skywalking.trace.tag.Tags; import java.sql.SQLException; /** * 连接级追踪,用于追踪用于Connection的操作追踪 - * - * @author wusheng * + * @author wusheng */ public class PreparedStatementTracing { - private static RPCClientInvokeMonitor rpcClientInvokeMonitor = new RPCClientInvokeMonitor(); - public static R execute(java.sql.PreparedStatement realStatement, - String connectInfo, String method, String sql, Executable exec) - throws SQLException { - try { - rpcClientInvokeMonitor.beforeInvoke(Identification - .newBuilder() - .viewPoint(connectInfo) - .businessKey( - "preaparedStatement." - + method - + (sql == null || sql.length() == 0 ? "" - : ":" + sql)).spanType(JDBCBuriedPointType.INSTANCE).build()); - return exec.exe(realStatement, sql); - } catch (SQLException e) { - rpcClientInvokeMonitor.occurException(e); - throw e; - } finally { - rpcClientInvokeMonitor.afterInvoke(); - } - } + public static R execute(java.sql.PreparedStatement realStatement, + String connectInfo, String method, String sql, Executable exec) + throws SQLException { + Span span = ContextManager.INSTANCE.createSpan("JDBC/PreparedStatement/" + method); + try { + Tags.SPAN_KIND.asDBAccess(span); + Tags.DB_URL.set(span, connectInfo); + Tags.DB_SQL.set(span, sql); + return exec.exe(realStatement, sql); + } catch (SQLException e) { + span.log(e); + throw e; + } finally { + ContextManager.INSTANCE.stopSpan(span); + } + } - public interface Executable { - public R exe(java.sql.PreparedStatement realConnection, String sql) - throws SQLException; - } + public interface Executable { + R exe(java.sql.PreparedStatement realConnection, String sql) + throws SQLException; + } }