Skip to content

Commit

Permalink
[pinpoint-apm#9631] Record SpanEventException in SpanRecorder.recordE…
Browse files Browse the repository at this point in the history
…xception()
  • Loading branch information
intr3p1d committed Mar 15, 2023
1 parent 55778b4 commit 5593883
Show file tree
Hide file tree
Showing 28 changed files with 1,021 additions and 51 deletions.
2 changes: 1 addition & 1 deletion grpc/grpc-idl
Submodule grpc-idl updated 1 files
+22 −0 proto/v1/Span.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.navercorp.pinpoint.bootstrap.context.scope.TraceScope;
import com.navercorp.pinpoint.common.annotations.VisibleForTesting;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.context.exception.ExceptionRecordingContext;
import com.navercorp.pinpoint.profiler.context.id.TraceRoot;
import com.navercorp.pinpoint.profiler.context.recorder.WrappedSpanEventRecorder;
import com.navercorp.pinpoint.profiler.context.scope.DefaultTraceScopePool;
Expand All @@ -46,6 +47,8 @@ public class AsyncChildTrace implements Trace {
private final SpanRecorder spanRecorder;
private final WrappedSpanEventRecorder wrappedSpanEventRecorder;

private final ExceptionRecordingContext exceptionRecordingContext;

private boolean closed = false;
// lazy initialize
private DefaultTraceScopePool scopePool;
Expand All @@ -54,14 +57,17 @@ public class AsyncChildTrace implements Trace {
private final LocalAsyncId localAsyncId;

public AsyncChildTrace(final TraceRoot traceRoot, CallStack<SpanEvent> callStack, Storage storage,
SpanRecorder spanRecorder, WrappedSpanEventRecorder wrappedSpanEventRecorder, final LocalAsyncId localAsyncId) {
SpanRecorder spanRecorder, WrappedSpanEventRecorder wrappedSpanEventRecorder,
ExceptionRecordingContext exceptionRecordingContext,
final LocalAsyncId localAsyncId) {

this.traceRoot = Objects.requireNonNull(traceRoot, "traceRoot");
this.callStack = Objects.requireNonNull(callStack, "callStack");
this.storage = Objects.requireNonNull(storage, "storage");

this.spanRecorder = Objects.requireNonNull(spanRecorder, "spanRecorder");
this.wrappedSpanEventRecorder = Objects.requireNonNull(wrappedSpanEventRecorder, "wrappedSpanEventRecorder");
this.exceptionRecordingContext = Objects.requireNonNull(exceptionRecordingContext, "exceptionRecordingContext");

this.localAsyncId = Objects.requireNonNull(localAsyncId, "localAsyncId");
traceBlockBegin(ASYNC_BEGIN_STACK_ID);
Expand All @@ -73,7 +79,7 @@ private TraceRoot getTraceRoot() {
}

private SpanEventRecorder wrappedSpanEventRecorder(WrappedSpanEventRecorder wrappedSpanEventRecorder, SpanEvent spanEvent) {
wrappedSpanEventRecorder.setWrapped(spanEvent);
wrappedSpanEventRecorder.setWrapped(spanEvent, this.exceptionRecordingContext);
return wrappedSpanEventRecorder;
}

Expand Down Expand Up @@ -149,7 +155,7 @@ public void traceBlockEnd(int stackId) {
logSpan(spanEvent);
// state restore
final SpanEvent previous = callStack.peek();
wrappedSpanEventRecorder.setWrapped(previous);
wrappedSpanEventRecorder(wrappedSpanEventRecorder, previous);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.navercorp.pinpoint.bootstrap.context.AsyncState;
import com.navercorp.pinpoint.bootstrap.context.SpanRecorder;
import com.navercorp.pinpoint.profiler.context.exception.ExceptionRecordingContext;
import com.navercorp.pinpoint.profiler.context.recorder.WrappedSpanEventRecorder;
import com.navercorp.pinpoint.profiler.context.storage.Storage;

Expand All @@ -15,8 +16,9 @@ public AsyncDefaultTrace(Span span,
Storage storage,
SpanRecorder spanRecorder,
WrappedSpanEventRecorder wrappedSpanEventRecorder,
ExceptionRecordingContext exceptionRecordingContext,
AsyncState asyncState) {
super(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, CloseListener.EMPTY);
super(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, exceptionRecordingContext, CloseListener.EMPTY);
this.asyncState = Objects.requireNonNull(asyncState, "asyncState");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.navercorp.pinpoint.common.annotations.InterfaceAudience;
import com.navercorp.pinpoint.profiler.context.active.ActiveTraceHandle;
import com.navercorp.pinpoint.profiler.context.active.ActiveTraceRepository;
import com.navercorp.pinpoint.profiler.context.exception.ExceptionRecordingContext;
import com.navercorp.pinpoint.profiler.context.id.ListenableAsyncState;
import com.navercorp.pinpoint.profiler.context.id.LocalTraceRoot;
import com.navercorp.pinpoint.profiler.context.id.LoggingAsyncState;
Expand Down Expand Up @@ -131,8 +132,9 @@ public Trace continueAsyncContextTraceObject(TraceRoot traceRoot, LocalAsyncId l

final SpanRecorder spanRecorder = recorderFactory.newTraceRootSpanRecorder(traceRoot);
final WrappedSpanEventRecorder wrappedSpanEventRecorder = recorderFactory.newWrappedSpanEventRecorder(traceRoot);
final ExceptionRecordingContext exceptionRecordingContext = ExceptionRecordingContext.newContext();

return new AsyncChildTrace(traceRoot, callStack, storage, spanRecorder, wrappedSpanEventRecorder, localAsyncId);
return new AsyncChildTrace(traceRoot, callStack, storage, spanRecorder, wrappedSpanEventRecorder, exceptionRecordingContext, localAsyncId);
}

@Override
Expand Down Expand Up @@ -197,10 +199,11 @@ private DefaultTrace newDefaultTrace(TraceRoot traceRoot) {

final SpanRecorder spanRecorder = recorderFactory.newSpanRecorder(span);
final WrappedSpanEventRecorder wrappedSpanEventRecorder = recorderFactory.newWrappedSpanEventRecorder(traceRoot);
final ExceptionRecordingContext exceptionRecordingContext = ExceptionRecordingContext.newContext();

final ActiveTraceHandle handle = registerActiveTrace(traceRoot);
final CloseListener closeListener = new DefaultCloseListener(traceRoot, handle, uriStatStorage);
return new DefaultTrace(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, closeListener);
return new DefaultTrace(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, exceptionRecordingContext, closeListener);
}

private AsyncDefaultTrace newAsyncDefaultTrace(TraceRoot traceRoot) {
Expand All @@ -215,8 +218,9 @@ private AsyncDefaultTrace newAsyncDefaultTrace(TraceRoot traceRoot) {

final SpanRecorder spanRecorder = recorderFactory.newSpanRecorder(span);
final WrappedSpanEventRecorder wrappedSpanEventRecorder = recorderFactory.newWrappedSpanEventRecorder(traceRoot, asyncState);
final ExceptionRecordingContext exceptionRecordingContext = ExceptionRecordingContext.newContext();

return new AsyncDefaultTrace(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, asyncState);
return new AsyncDefaultTrace(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, exceptionRecordingContext, asyncState);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.navercorp.pinpoint.bootstrap.context.scope.TraceScope;
import com.navercorp.pinpoint.common.annotations.VisibleForTesting;
import com.navercorp.pinpoint.exception.PinpointException;
import com.navercorp.pinpoint.profiler.context.exception.ExceptionRecordingContext;
import com.navercorp.pinpoint.profiler.context.id.TraceRoot;
import com.navercorp.pinpoint.profiler.context.recorder.WrappedSpanEventRecorder;
import com.navercorp.pinpoint.profiler.context.scope.DefaultTraceScopePool;
Expand All @@ -49,6 +50,8 @@ public class DefaultTrace implements Trace {
private final SpanRecorder spanRecorder;
private final WrappedSpanEventRecorder wrappedSpanEventRecorder;

private final ExceptionRecordingContext exceptionRecordingContext;

private boolean closed = false;
// lazy initialize
private DefaultTraceScopePool scopePool;
Expand All @@ -58,13 +61,15 @@ public class DefaultTrace implements Trace {
private final CloseListener closeListener;

public DefaultTrace(Span span, CallStack<SpanEvent> callStack, Storage storage,
SpanRecorder spanRecorder, WrappedSpanEventRecorder wrappedSpanEventRecorder) {
this(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, CloseListener.EMPTY);
SpanRecorder spanRecorder, WrappedSpanEventRecorder wrappedSpanEventRecorder,
ExceptionRecordingContext exceptionRecordingContext) {
this(span, callStack, storage, spanRecorder, wrappedSpanEventRecorder, exceptionRecordingContext, CloseListener.EMPTY);
}

public DefaultTrace(Span span, CallStack<SpanEvent> callStack, Storage storage,
SpanRecorder spanRecorder,
WrappedSpanEventRecorder wrappedSpanEventRecorder,
ExceptionRecordingContext exceptionRecordingContext,
CloseListener closeListener) {

this.span = Objects.requireNonNull(span, "span");
Expand All @@ -73,6 +78,7 @@ public DefaultTrace(Span span, CallStack<SpanEvent> callStack, Storage storage,

this.spanRecorder = Objects.requireNonNull(spanRecorder, "spanRecorder");
this.wrappedSpanEventRecorder = Objects.requireNonNull(wrappedSpanEventRecorder, "wrappedSpanEventRecorder");
this.exceptionRecordingContext = Objects.requireNonNull(exceptionRecordingContext, "exceptionRecordingContext");

this.closeListener = closeListener;

Expand All @@ -89,7 +95,7 @@ private TraceRoot getTraceRoot() {
}

private SpanEventRecorder wrappedSpanEventRecorder(WrappedSpanEventRecorder wrappedSpanEventRecorder, SpanEvent spanEvent) {
wrappedSpanEventRecorder.setWrapped(spanEvent);
wrappedSpanEventRecorder.setWrapped(spanEvent, this.exceptionRecordingContext);
return wrappedSpanEventRecorder;
}

Expand Down Expand Up @@ -165,7 +171,7 @@ public void traceBlockEnd(int stackId) {
logSpan(spanEvent);
// state restore
final SpanEvent previous = callStack.peek();
wrappedSpanEventRecorder.setWrapped(previous);
wrappedSpanEventRecorder(wrappedSpanEventRecorder, previous);
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ public class Span extends DefaultFrameAttachment implements SpanType {

private IntStringValue exceptionInfo; // optional


public Span(final TraceRoot traceRoot) {
this.traceRoot = Objects.requireNonNull(traceRoot, "traceRoot");
}
Expand Down Expand Up @@ -159,7 +158,7 @@ public void markAfterTime() {
}

public void markAfterTime(long currentTime) {
final int after = (int)(currentTime - this.getStartTime());
final int after = (int) (currentTime - this.getStartTime());
this.setElapsedTime(after);
}

Expand All @@ -175,7 +174,6 @@ public void setExceptionInfo(int exceptionClassId, String exceptionMessage) {
this.setExceptionInfo(exceptionInfo);
}


public boolean isTimeRecording() {
return timeRecording;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.navercorp.pinpoint.profiler.context;

import com.navercorp.pinpoint.common.util.IntStringValue;
import com.navercorp.pinpoint.profiler.context.exception.SpanEventException;

import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -49,6 +50,7 @@ public class SpanEvent extends DefaultFrameAttachment {

private int apiId; // optional
private IntStringValue exceptionInfo; // optional
private SpanEventException flushedException; // optional

private AsyncId asyncIdObject;

Expand All @@ -66,6 +68,14 @@ public void setExceptionInfo(int exceptionClassId, String exceptionMessage) {
this.exceptionInfo = new IntStringValue(exceptionClassId, exceptionMessage);
}

public SpanEventException getFlushedException() {
return flushedException;
}

public void setFlushedException(SpanEventException flushedException) {
this.flushedException = flushedException;
}

public void markStartTime() {
setStartTime(System.currentTimeMillis());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright 2023 NAVER Corp.
*
* 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.navercorp.pinpoint.profiler.context.exception;

import com.google.inject.Inject;

import java.util.concurrent.atomic.AtomicLong;

/**
* @author intr3p1d
*/
public class AtomicExceptionIdGenerator implements ExceptionIdGenerator {

public static final long INITIAL_EXCEPTION_ID = 1L;

private final AtomicLong errorId = new AtomicLong(INITIAL_EXCEPTION_ID);

@Inject
public AtomicExceptionIdGenerator() {
}

@Override
public long getCurrentExceptionId() {
return this.errorId.get();
}

@Override
public long nextExceptionId() {
return this.errorId.getAndIncrement();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2023 NAVER Corp.
*
* 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.navercorp.pinpoint.profiler.context.exception;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.Objects;

/**
* @author intr3p1d
*/
public class DefaultExceptionRecordingService implements ExceptionRecordingService {

private static final Logger logger = LogManager.getLogger(DefaultExceptionRecordingService.class);

private static final boolean IS_DEBUG = logger.isDebugEnabled();

private final ExceptionIdGenerator exceptionIdGenerator;

public DefaultExceptionRecordingService(ExceptionIdGenerator exceptionIdGenerator) {
this.exceptionIdGenerator = exceptionIdGenerator;
}

@Override
public SpanEventException recordException(ExceptionRecordingContext context, Throwable current, long startTime) {
Objects.requireNonNull(context);

ExceptionRecordingState state = ExceptionRecordingState.stateOf(context.getPrevious(), current);
SpanEventException spanEventException = state.apply(context, current, startTime, exceptionIdGenerator);

logException(spanEventException);

return spanEventException;
}

private void logException(SpanEventException spanEventException) {
if (IS_DEBUG && spanEventException != null) {
logger.debug(spanEventException);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2023 NAVER Corp.
*
* 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.navercorp.pinpoint.profiler.context.exception;

/**
* @author intr3p1d
*/
public interface ExceptionIdGenerator {
long getCurrentExceptionId();
long nextExceptionId();
}
Loading

0 comments on commit 5593883

Please sign in to comment.