001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server.tracing;
018
019/**
020 * Handle to one in-flight {@link TracerHook}-managed span.
021 *
022 * <p>
023 * Returned by {@link TracerHook#startSpan(org.apache.juneau.rest.server.RestRequest)}. The framework drives
024 * the {@code setStatusCode} / {@code setError} / {@code close} transitions inside a {@code finally}
025 * block so the span always closes &mdash; including on exception paths.
026 *
027 * <p>
028 * Bridge implementations typically wrap the downstream tracer's native span / scope. The OpenTelemetry
029 * bridge in {@code juneau-rest-server-tracing-otel}, for example, wraps an
030 * {@code io.opentelemetry.api.trace.Span} plus its {@code io.opentelemetry.context.Scope}: setters
031 * translate to span attribute / status writes; {@code close()} ends the span and closes the OTel
032 * scope.
033 *
034 * @since 10.0.0
035 */
036public interface Scope extends AutoCloseable {
037
038   /**
039    * Records the HTTP response status code on the span.
040    *
041    * <p>
042    * Called by the framework after the {@code @RestOp} handler completes &mdash; before
043    * {@link #close()}, and before {@link #setError(Throwable)} if the handler also threw. Bridges
044    * typically translate the status into both a numeric attribute (e.g. OpenTelemetry's
045    * {@code http.response.status_code}) and an overall span status (HTTP {@code 5xx} maps to
046    * span-status {@code ERROR}; other codes map to {@code UNSET} per the OTel HTTP semantic
047    * conventions).
048    *
049    * @param statusCode The HTTP status code (e.g. {@code 200}, {@code 404}, {@code 500}).
050    */
051   void setStatusCode(int statusCode);
052
053   /**
054    * Records the exception (if any) the {@code @RestOp} handler threw on the span.
055    *
056    * <p>
057    * Called by the framework only when the handler threw &mdash; immediately before {@link #close()}.
058    * Bridges typically record the throwable as a span event with the stack trace, set the span status
059    * to {@code ERROR}, and add an {@code exception.type} attribute carrying the exception's
060    * simple-name.
061    *
062    * @param error The exception thrown by the handler. Never <jk>null</jk> when this method is called.
063    */
064   void setError(Throwable error);
065
066   /**
067    * Closes the span.
068    *
069    * <p>
070    * Always called by the framework &mdash; via the standard {@code finally}-block contract on
071    * {@link AutoCloseable} &mdash; whether the handler returned normally or threw. Implementations
072    * <b>must not</b> throw checked exceptions; the close path runs in a {@code finally} where masking
073    * the original handler exception is unsafe. Implementations that need to surface bridge-level
074    * errors should log + swallow instead.
075    */
076   @Override
077   void close();
078
079   /**
080    * Records a JSON-RPC-level error outcome on this span.
081    *
082    * <p>
083    * A dated MCP adapter dispatches every request over HTTP {@code 200}, so an application-level
084    * JSON-RPC error (for example an unknown tool name) never reaches {@link #setStatusCode(int)}
085    * with anything but {@code 200} and never throws into {@link #setError(Throwable)}. This method
086    * gives such a caller a neutral way to observe that outcome on the span &mdash; called from the
087    * request-scoped tracing observation before a JSON-RPC error response is returned, distinct from
088    * both the HTTP status path and the thrown-exception path.
089    *
090    * <p>
091    * Added as a source-compatible default so every existing {@link Scope} implementation keeps
092    * compiling unchanged. The default implementation is a no-op; a bridge that wants to classify
093    * JSON-RPC errors on the span (for example the OpenTelemetry bridge in
094    * {@code juneau-rest-server-tracing-otel}) overrides it.
095    *
096    * @param code The JSON-RPC error code (e.g. {@code -32601}).
097    * @param message The JSON-RPC error message. May be <jk>null</jk>.
098    */
099   default void recordRpcError(int code, String message) {
100      // Intentionally empty; see method-level javadoc.
101   }
102}