/** * Use this to ensure the trace context propagates to children. * * <p>Ex. * <pre>{@code * // Ensure the trace context propagates to children * ctx.onChild(RequestContextCurrentTraceContext::copy); * }</pre> */ public static void copy(RequestContext src, RequestContext dst) { dst.attr(TRACE_CONTEXT_KEY).set(src.attr(TRACE_CONTEXT_KEY).get()); }
/** * Stores the {@link ByteBuf} backing {@link Message} to be released later using * {@link #releaseBuffer(Object, RequestContext)}. */ public static void storeBuffer(ByteBuf buf, Object message, RequestContext ctx) { IdentityHashMap<Object, ByteBuf> buffers = ctx.attr(BUFFERS).get(); if (buffers == null) { buffers = new IdentityHashMap<>(); ctx.attr(BUFFERS).set(buffers); } buffers.put(message, buf); }
/** * Releases the {@link ByteBuf} backing the provided {@link Message}. */ public static void releaseBuffer(Object message, RequestContext ctx) { final IdentityHashMap<Object, ByteBuf> buffers = ctx.attr(BUFFERS).get(); checkState(buffers != null, "Releasing buffer even though storeBuffer has not been called."); final ByteBuf removed = buffers.remove(message); if (removed == null) { throw new IllegalArgumentException("The provided message does not have a stored buffer."); } removed.release(); }
@Nullable @Override Object getMessage0(RequestLog log) { final Attribute<?> value = log.context().attr(key); return value != null ? stringifer.apply(value.get()) : null; } }
@Override public <V> Attribute<V> attr(AttributeKey<V> key) { return delegate().attr(key); }
/** Armeria code should always have a request context available, and this won't work without it. */ @Nullable private static Attribute<TraceContext> getTraceContextAttributeOrWarnOnce() { final RequestContext ctx = getRequestContextOrWarnOnce(); if (ctx == null) { return null; } return ctx.attr(TRACE_CONTEXT_KEY); }
private static Scope createScopeForRequestThread(RequestContext ctx, @Nullable TraceContext currentSpan) { final Attribute<TraceContext> traceContextAttribute = ctx.attr(TRACE_CONTEXT_KEY); final TraceContext previous = traceContextAttribute.getAndSet(currentSpan); // Don't remove the outer-most context (client or server request) if (previous == null) { return INITIAL_REQUEST_SCOPE; } // Removes sub-spans (i.e. local spans) from the current context when Brave's scope does. // If an asynchronous sub-span, it may still complete later. class RequestContextTraceContextScope implements Scope { @Override public void close() { // re-lookup the attribute to avoid holding a reference to the request if this scope is leaked getTraceContextAttributeOrWarnOnce().set(previous); } @Override public String toString() { return "RequestContextTraceContextScope"; } } return new RequestContextTraceContextScope(); }
@Override @Nullable public TraceContext get() { final RequestContext ctx = getRequestContextOrWarnOnce(); if (ctx == null) { return null; } if (ctx.eventLoop().inEventLoop()) { return ctx.attr(TRACE_CONTEXT_KEY).get(); } else { final TraceContext threadLocalContext = THREAD_LOCAL_CONTEXT.get(); if (threadLocalContext != null) { return threadLocalContext; } // First span on a non-request thread will use the request's TraceContext as a parent. return ctx.attr(TRACE_CONTEXT_KEY).get(); } }
private static State state(RequestContext ctx) { final Attribute<State> attr = ctx.attr(STATE); final State state = attr.get(); if (state == null) { final State newState = new State(); final State oldState = attr.setIfAbsent(newState); if (oldState != null) { return oldState; } else { return newState; } } return state; }
private void exportAttributes(Map<String, String> out, RequestContext ctx) { if (attrs == null) { return; } for (ExportEntry<AttributeKey<?>> e : attrs) { final AttributeKey<?> attrKey = e.key; final String mdcKey = e.mdcKey; if (ctx.hasAttr(attrKey)) { final Object value = ctx.attr(attrKey).get(); if (value != null) { out.put(mdcKey, e.stringify(value)); } } } }
public static void setup(RequestContext ctx, MeterIdPrefixFunction meterIdPrefixFunction) { if (ctx.hasAttr(ATTR_REQUEST_METRICS_SET)) { return; } ctx.attr(ATTR_REQUEST_METRICS_SET).set(true); ctx.log().addListener(log -> onRequest(log, meterIdPrefixFunction), RequestLogAvailability.REQUEST_HEADERS, RequestLogAvailability.REQUEST_CONTENT); }
@Override public void onNext(SimpleRequest value) { final RequestContext ctx = RequestContext.current(); final Attribute<Integer> attr = ctx.attr(CHECK_REQUEST_CONTEXT_COUNT); attr.set(attr.get() + 1); }
@Before public void setup() { when(mockRequestContext.eventLoop()).thenReturn(eventLoop); when(mockRequestContext2.eventLoop()).thenReturn(eventLoop); when(eventLoop.inEventLoop()).thenReturn(true); when(mockRequestContext.attr(isA(AttributeKey.class))).thenAnswer( (Answer<Attribute>) invocation -> attrs1.attr(invocation.getArgument(0))); when(mockRequestContext2.attr(isA(AttributeKey.class))).thenAnswer( (Answer<Attribute>) invocation -> attrs2.attr(invocation.getArgument(0))); }
@Override public StreamObserver<SimpleRequest> checkRequestContext( StreamObserver<SimpleResponse> responseObserver) { final RequestContext ctx = RequestContext.current(); ctx.attr(CHECK_REQUEST_CONTEXT_COUNT).set(0); return new StreamObserver<SimpleRequest>() { @Override public void onNext(SimpleRequest value) { final RequestContext ctx = RequestContext.current(); final Attribute<Integer> attr = ctx.attr(CHECK_REQUEST_CONTEXT_COUNT); attr.set(attr.get() + 1); } @Override public void onError(Throwable t) {} @Override public void onCompleted() { final RequestContext ctx = RequestContext.current(); final int count = ctx.attr(CHECK_REQUEST_CONTEXT_COUNT).get(); responseObserver.onNext( SimpleResponse.newBuilder() .setPayload( Payload.newBuilder() .setBody( ByteString.copyFromUtf8( Integer.toString(count)))) .build()); responseObserver.onCompleted(); } }; }
@Override public void onNext(SimpleResponse value) { try { final RequestContext ctx = RequestContext.current(); assertThat(value).isEqualTo(goldenResponse); final ByteBuf buf = ctx.attr(GrpcUnsafeBufferUtil.BUFFERS).get().get(value); assertThat(buf.refCnt()).isNotZero(); GrpcUnsafeBufferUtil.releaseBuffer(value, ctx); assertThat(buf.refCnt()).isZero(); } catch (Throwable t) { resultQueue.add(t); } }
@Override public void onCompleted() { final RequestContext ctx = RequestContext.current(); final int count = ctx.attr(CHECK_REQUEST_CONTEXT_COUNT).get(); responseObserver.onNext( SimpleResponse.newBuilder() .setPayload( Payload.newBuilder() .setBody( ByteString.copyFromUtf8( Integer.toString(count)))) .build()); responseObserver.onCompleted(); } };
/** * Stores the {@link ByteBuf} backing {@link Message} to be released later using * {@link #releaseBuffer(Object, RequestContext)}. */ public static void storeBuffer(ByteBuf buf, Object message, RequestContext ctx) { IdentityHashMap<Object, ByteBuf> buffers = ctx.attr(BUFFERS).get(); if (buffers == null) { buffers = new IdentityHashMap<>(); ctx.attr(BUFFERS).set(buffers); } buffers.put(message, buf); }
/** * Releases the {@link ByteBuf} backing the provided {@link Message}. */ public static void releaseBuffer(Object message, RequestContext ctx) { final IdentityHashMap<Object, ByteBuf> buffers = ctx.attr(BUFFERS).get(); checkState(buffers != null, "Releasing buffer even though storeBuffer has not been called."); final ByteBuf removed = buffers.remove(message); if (removed == null) { throw new IllegalArgumentException("The provided message does not have a stored buffer."); } removed.release(); }
private static State state(RequestContext ctx) { final Attribute<State> attr = ctx.attr(STATE); final State state = attr.get(); if (state == null) { final State newState = new State(); final State oldState = attr.setIfAbsent(newState); if (oldState != null) { return oldState; } else { return newState; } } return state; }
private static State state(RequestContext ctx) { final Attribute<State> attr = ctx.attr(STATE); final State state = attr.get(); if (state == null) { final State newState = new State(); final State oldState = attr.setIfAbsent(newState); if (oldState != null) { return oldState; } else { return newState; } } return state; }