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 org.apache.juneau.rest.server.*;
020
021/**
022 * Default {@link TracerHook} implementation that opens no spans and records nothing.
023 *
024 * <p>
025 * Used whenever no consumer-provided {@code TracerHook} bean is reachable from the
026 * {@code RestContext}'s bean store. Ensures the {@link TracerHook} contract is always satisfied
027 * &mdash; the framework can call {@link #startSpan(RestRequest)} unconditionally without a
028 * null-check, and the returned {@link NoOpScope} satisfies the close-in-finally contract with
029 * zero allocations.
030 *
031 * <p>
032 * Both {@link #INSTANCE} and {@link NoOpScope#INSTANCE} are process-wide singletons; the
033 * {@link #startSpan(RestRequest)} method returns the same scope reference for every call and JIT-inlines
034 * the no-op setters / close to empty method bodies.
035 *
036 * @since 10.0.0
037 */
038@SuppressWarnings({
039   "java:S6548" // Intentional process-wide no-op singleton; the Singleton pattern is required to satisfy the TracerHook SPI contract with zero allocation.
040})
041public final class NoOpTracerHook implements TracerHook {
042
043   /** Process-wide singleton instance. */
044   public static final NoOpTracerHook INSTANCE = new NoOpTracerHook();
045
046   private NoOpTracerHook() {}
047
048   @Override /* TracerHook */
049   public Scope startSpan(RestRequest request) {
050      return NoOpScope.INSTANCE;
051   }
052
053   /**
054    * No-op {@link Scope} returned by {@link NoOpTracerHook}.
055    *
056    * <p>
057    * Drops every status, error, and close transition on the floor. Public so user code that wants to
058    * fall back to the no-op behaviour from a custom {@link TracerHook} (for example, when the
059    * incoming trace context is unparseable) can return {@link #INSTANCE} instead of implementing a
060    * private equivalent.
061    */
062   @SuppressWarnings({
063      "resource" // Singleton; intentionally held for the process lifetime.
064   })
065   public static final class NoOpScope implements Scope {
066
067      /** Process-wide singleton instance. */
068      public static final NoOpScope INSTANCE = new NoOpScope();
069
070      private NoOpScope() {}
071
072      @Override /* Scope */
073      public void setStatusCode(int statusCode) {
074         // Intentionally empty.
075      }
076
077      @Override /* Scope */
078      public void setError(Throwable error) {
079         // Intentionally empty.
080      }
081
082      @Override /* Scope */
083      public void close() {
084         // Intentionally empty.
085      }
086   }
087}