/** * Pushes the specified context to the thread-local stack. To pop the context from the stack, call * {@link SafeCloseable#close()}, which can be done using a {@code try-with-resources} block: * <pre>{@code * try (SafeCloseable ignored = ctx.push()) { * ... * } * }</pre> * * <p>The callbacks added by {@link #onEnter(Consumer)} and {@link #onExit(Consumer)} will be invoked * when the context is pushed to and removed from the thread-local stack respectively. * * <p>NOTE: In case of re-entrance, the callbacks will never run. */ default SafeCloseable push() { return push(true); }
/** * Pushes the specified context to the thread-local stack. To pop the context from the stack, call * {@link SafeCloseable#close()}, which can be done using a {@code try-with-resources} block. * * @deprecated Use {@link #push()}. */ @Deprecated static SafeCloseable push(RequestContext ctx) { return ctx.push(true); }
/** * Pushes the specified context to the thread-local stack. To pop the context from the stack, call * {@link SafeCloseable#close()}, which can be done using a {@code try-with-resources} block. * * @deprecated Use {@link #push(boolean)}. */ @Deprecated static SafeCloseable push(RequestContext ctx, boolean runCallbacks) { return ctx.push(runCallbacks); }
/** * Pushes this context to the thread-local stack if there is no current context. If there is and it is not * same with this context (i.e. not reentrance), this method will throw an {@link IllegalStateException}. * To pop the context from the stack, call {@link SafeCloseable#close()}, * which can be done using a {@code try-with-resources} block. */ default SafeCloseable pushIfAbsent() { final RequestContext currentRequestContext = RequestContextThreadLocal.get(); if (currentRequestContext != null && currentRequestContext != this) { throw new IllegalStateException( "Trying to call object wrapped with context " + this + ", but context is currently " + "set to " + currentRequestContext + ". This means the callback was called from " + "unexpected thread or forgetting to close previous context."); } return push(); }
/** * Invokes {@link RequestLogListener#onRequestLog(RequestLog)}. */ public static void invokeOnRequestLog(RequestLogListener listener, RequestLog log) { try (SafeCloseable ignored = log.context().push()) { listener.onRequestLog(log); } catch (Throwable e) { logger.warn("onRequestLog() failed with an exception:", e); } }
@Test public void copy() { try (SafeCloseable requestContextScope = mockRequestContext.push()) { try (Scope traceContextScope = currentTraceContext.newScope(traceContext)) { RequestContextCurrentTraceContext.copy(mockRequestContext, mockRequestContext2); assertThat(attrs1.attrs().next().get()) .isEqualTo(traceContext) .isEqualTo(attrs2.attrs().next().get()); } } }
@Test public void newScope_appliesWhenCurrentRequestContext() { try (SafeCloseable requestContextScope = mockRequestContext.push()) { try (Scope traceContextScope = currentTraceContext.newScope(traceContext)) { assertThat(traceContextScope).hasToString("InitialRequestScope"); assertThat(currentTraceContext.get()).isEqualTo(traceContext); } } }
@Test public void get_returnsNullWhenCurrentRequestContext_hasNoTraceAttribute() { try (SafeCloseable requestContextScope = mockRequestContext.push()) { assertThat(currentTraceContext.get()).isNull(); } }
@Test public void newScope_canClearScope() { try (SafeCloseable requestContextScope = mockRequestContext.push()) { try (Scope traceContextScope = currentTraceContext.newScope(traceContext)) { try (Scope traceContextScope2 = currentTraceContext.newScope(null)) { assertThat(currentTraceContext.get()).isNull(); } assertThat(currentTraceContext.get()).isEqualTo(traceContext); } } }
@Test public void newScope_closeDoesntClearFirstScope() { final TraceContext traceContext2 = TraceContext.newBuilder().traceId(1).spanId(2).build(); try (SafeCloseable requestContextScope = mockRequestContext.push()) { try (Scope traceContextScope = currentTraceContext.newScope(traceContext)) { assertThat(traceContextScope).hasToString("InitialRequestScope"); assertThat(currentTraceContext.get()).isEqualTo(traceContext); try (Scope traceContextScope2 = currentTraceContext.newScope(traceContext2)) { assertThat(traceContextScope2).hasToString("RequestContextTraceContextScope"); assertThat(currentTraceContext.get()).isEqualTo(traceContext2); } assertThat(currentTraceContext.get()).isEqualTo(traceContext); } // the first scope is attached to the request context and cleared when that's destroyed assertThat(currentTraceContext.get()).isEqualTo(traceContext); } }
@Test public void newScope_notOnEventLoop() { final TraceContext traceContext2 = TraceContext.newBuilder().traceId(1).spanId(2).build(); try (SafeCloseable requestContextScope = mockRequestContext.push()) { try (Scope traceContextScope = currentTraceContext.newScope(traceContext)) { assertThat(traceContextScope).hasToString("InitialRequestScope"); assertThat(currentTraceContext.get()).isEqualTo(traceContext); when(eventLoop.inEventLoop()).thenReturn(false); try (Scope traceContextScope2 = currentTraceContext.newScope(traceContext2)) { assertThat(traceContextScope2).hasToString("ThreadLocalScope"); assertThat(currentTraceContext.get()).isEqualTo(traceContext2); } when(eventLoop.inEventLoop()).thenReturn(true); assertThat(currentTraceContext.get()).isEqualTo(traceContext); } // the first scope is attached to the request context and cleared when that's destroyed assertThat(currentTraceContext.get()).isEqualTo(traceContext); } }