// Path: wingtips-core/src/main/java/com/nike/wingtips/lifecyclelistener/SpanLifecycleListener.java
// public interface SpanLifecycleListener {
// 
//     /**
//      * This will be called when the given {@link Span} is created/started, and will be called whether or not the span is sampled.
//      */
//     void spanStarted(Span span);
// 
//     /**
//      * This will be called when the given {@link Span} is determined to be sampleable - if this is called for a given span it will be called
//      * immediately after {@link #spanStarted(Span)} is called.
//      */
//     void spanSampled(Span span);
// 
//     /**
//      * This will be called when the given {@link Span} is completed, and will be called whether or not the span is sampled.
//      */
//     void spanCompleted(Span span);
// 
// }
// 
// Path: wingtips-core/src/main/java/com/nike/wingtips/sampling/SampleAllTheThingsStrategy.java
// public class SampleAllTheThingsStrategy implements RootSpanSamplingStrategy {
// 
//     @Override
//     public boolean isNextRootSpanSampleable() {
//         return true;
//     }
// }


import com.nike.wingtips.Span.SpanPurpose;
import com.nike.wingtips.http.HttpRequestTracingUtils;
import com.nike.wingtips.lifecyclelistener.SpanLifecycleListener;
import com.nike.wingtips.sampling.RootSpanSamplingStrategy;
import com.nike.wingtips.sampling.SampleAllTheThingsStrategy;
import com.nike.wingtips.util.TracerManagedSpanStatus;
import com.nike.wingtips.util.TracingState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.nike.wingtips.http.HttpRequestTracingUtils.CHILD_OF_SPAN_FROM_HEADERS_WHERE_CALLER_DID_NOT_SEND_SPAN_ID_TAG_KEY;
                    return span.getParentSpanId();
                case FULL_SPAN_JSON:
                    return span.toJSON();
                default:
                    throw new IllegalStateException("Unhandled SpanFieldForLoggerMdc type: " + this);
            }
        }
    }

    private static final String VALID_WINGTIPS_SPAN_LOGGER_NAME = "VALID_WINGTIPS_SPANS";
    private static final String INVALID_WINGTIPS_SPAN_LOGGER_NAME = "INVALID_WINGTIPS_SPANS";

    private static final Logger classLogger = LoggerFactory.getLogger(Tracer.class);
    private static final Logger validSpanLogger = LoggerFactory.getLogger(VALID_WINGTIPS_SPAN_LOGGER_NAME);
    private static final Logger invalidSpanLogger = LoggerFactory.getLogger(INVALID_WINGTIPS_SPAN_LOGGER_NAME);

    /**
     * ThreadLocal that keeps track of the stack of {@link Span} objects associated with the thread. This is treated as a LIFO stack.
     */
    private static final ThreadLocal<Deque<Span>> currentSpanStackThreadLocal = new ThreadLocal<>();

    /**
     * The singleton instance for this class.
     */
    private static final Tracer INSTANCE = new Tracer();


    /**
     * The sampling strategy this instance will use. Default to sampling everything. Never allow this field to be set to null.
     */
// Path: wingtips-core/src/main/java/com/nike/wingtips/lifecyclelistener/SpanLifecycleListener.java
// public interface SpanLifecycleListener {
// 
//     /**
//      * This will be called when the given {@link Span} is created/started, and will be called whether or not the span is sampled.
//      */
//     void spanStarted(Span span);
// 
//     /**
//      * This will be called when the given {@link Span} is determined to be sampleable - if this is called for a given span it will be called
//      * immediately after {@link #spanStarted(Span)} is called.
//      */
//     void spanSampled(Span span);
// 
//     /**
//      * This will be called when the given {@link Span} is completed, and will be called whether or not the span is sampled.
//      */
//     void spanCompleted(Span span);
// 
// }
// 
// Path: wingtips-core/src/main/java/com/nike/wingtips/sampling/SampleAllTheThingsStrategy.java
// public class SampleAllTheThingsStrategy implements RootSpanSamplingStrategy {
// 
//     @Override
//     public boolean isNextRootSpanSampleable() {
//         return true;
//     }
// }


// Path: wingtips-core/src/main/java/com/nike/wingtips/Tracer.java
import com.nike.wingtips.Span.SpanPurpose;
import com.nike.wingtips.http.HttpRequestTracingUtils;
import com.nike.wingtips.lifecyclelistener.SpanLifecycleListener;
import com.nike.wingtips.sampling.RootSpanSamplingStrategy;
import com.nike.wingtips.sampling.SampleAllTheThingsStrategy;
import com.nike.wingtips.util.TracerManagedSpanStatus;
import com.nike.wingtips.util.TracingState;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import static com.nike.wingtips.http.HttpRequestTracingUtils.CHILD_OF_SPAN_FROM_HEADERS_WHERE_CALLER_DID_NOT_SEND_SPAN_ID_TAG_KEY;

                    return span.getParentSpanId();
                case FULL_SPAN_JSON:
                    return span.toJSON();
                default:
                    throw new IllegalStateException("Unhandled SpanFieldForLoggerMdc type: " + this);
            }
        }
    }

    private static final String VALID_WINGTIPS_SPAN_LOGGER_NAME = "VALID_WINGTIPS_SPANS";
    private static final String INVALID_WINGTIPS_SPAN_LOGGER_NAME = "INVALID_WINGTIPS_SPANS";

    private static final Logger classLogger = LoggerFactory.getLogger(Tracer.class);
    private static final Logger validSpanLogger = LoggerFactory.getLogger(VALID_WINGTIPS_SPAN_LOGGER_NAME);
    private static final Logger invalidSpanLogger = LoggerFactory.getLogger(INVALID_WINGTIPS_SPAN_LOGGER_NAME);

    /**
     * ThreadLocal that keeps track of the stack of {@link Span} objects associated with the thread. This is treated as a LIFO stack.
     */
    private static final ThreadLocal<Deque<Span>> currentSpanStackThreadLocal = new ThreadLocal<>();

    /**
     * The singleton instance for this class.
     */
    private static final Tracer INSTANCE = new Tracer();


    /**
     * The sampling strategy this instance will use. Default to sampling everything. Never allow this field to be set to null.
     */
    private RootSpanSamplingStrategy rootSpanSamplingStrategy = new SampleAllTheThingsStrategy();