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
019import java.util.*;
020
021import org.apache.juneau.http.tracing.TraceContextCarrier;
022import org.apache.juneau.rest.server.*;
023
024/**
025 * SPI for recognizing a non-HTTP trace-context carrier inside a resolved {@code @RestOp} invocation.
026 *
027 * <p>
028 * {@code RestOpInvoker} resolves every operation argument (path/query/body parameters, parsed request
029 * beans, etc.) before it opens a {@code TracerHook} span. A registered {@code TraceContextExtractor}
030 * bean gets a look at those resolved arguments &mdash; not just the raw {@link RestRequest} &mdash; so
031 * it can recognize a domain-specific carrier (for example a parsed JSON-RPC/MCP request's nested
032 * {@code params._meta} object) and hand back a {@link TraceContextCarrier} plus a {@link TraceOperation}
033 * before the span is created. Neither this interface nor its default implementation depends on MCP,
034 * JSON-RPC, or OpenTelemetry.
035 *
036 * <p>
037 * Extraction only happens when a non-no-op {@code TracerHook} is active; a resource with no
038 * registered {@code TracerHook} bean never resolves a {@code TraceContextExtractor} either, preserving
039 * the existing zero-allocation no-op fast path.
040 *
041 * <h5 class='section'>See Also:</h5><ul>
042 *    <li class='jc'>{@link TraceContextCarrier}
043 *    <li class='jc'>{@link TraceOperation}
044 *    <li class='jc'>{@link TracerHook}
045 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerObservability">Observability — Micrometer + OpenTelemetry</a>
046 * </ul>
047 *
048 * @since 10.0.0
049 */
050public interface TraceContextExtractor {
051
052   /**
053    * Attempts to recognize a non-HTTP trace-context carrier among the resolved operation arguments.
054    *
055    * @param request The in-flight {@link RestRequest}. Never <jk>null</jk>.
056    * @param resolvedArguments The fully-resolved {@code @RestOp} handler arguments, in declaration
057    *    order. Never <jk>null</jk>; may be empty.
058    * @return The recognized {@link TraceContextCarrier}, or {@link Optional#empty()} if this
059    *    extractor found nothing to extract from the resolved arguments (the bridge then falls back to
060    *    HTTP headers only). Never <jk>null</jk>.
061    */
062   Optional<TraceContextCarrier> extract(RestRequest request, Object[] resolvedArguments);
063
064   /**
065    * Derives the {@link TraceOperation} a bridge should name/attribute its span with.
066    *
067    * <p>
068    * The default implementation returns {@link TraceOperation#DEFAULT} &mdash; an extractor that
069    * overrides only {@link #extract} still satisfies {@code TracerHook.startSpan}'s three-argument
070    * overload, and the bridge keeps its own HTTP-derived span name/attributes.
071    *
072    * @param request The in-flight {@link RestRequest}. Never <jk>null</jk>.
073    * @param resolvedArguments The fully-resolved {@code @RestOp} handler arguments, in declaration
074    *    order. Never <jk>null</jk>; may be empty.
075    * @return The derived {@link TraceOperation}. Never <jk>null</jk>.
076    */
077   default TraceOperation operation(RestRequest request, Object[] resolvedArguments) {
078      return TraceOperation.DEFAULT;
079   }
080}