| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.cloudera.htrace; |
| |
| import java.security.SecureRandom; |
| import java.util.Random; |
| import java.util.concurrent.Callable; |
| |
| import org.cloudera.htrace.impl.MilliSpan; |
| import org.cloudera.htrace.impl.TrueIfTracingSampler; |
| import org.cloudera.htrace.wrappers.TraceCallable; |
| import org.cloudera.htrace.wrappers.TraceRunnable; |
| |
| /** |
| * The primary way to interact with the library. Provides methods to start |
| * spans, as well as set necessary tracing information. |
| */ |
| public class Trace { |
| private final static Random random = new SecureRandom(); |
| |
| /** |
| * Starts and returns a new span as the child of the current span if the |
| * default sampler (TrueIfTracingSampler) returns true, otherwise returns the |
| * NullSpan. |
| * |
| * @param description |
| * Description of the span to be created. |
| * @return |
| */ |
| public static TraceScope startSpan(String description) { |
| return startSpan(description, TrueIfTracingSampler.INSTANCE); |
| } |
| |
| /** |
| * Starts and returns a new span as the child of the parameter 'parent'. This |
| * will always return a new span, even if tracing wasn't previously enabled for |
| * this thread. |
| * |
| * @param description |
| * Description of the span to be created. |
| * @param parent |
| * The parent that should be used to create the child span that is to |
| * be returned. |
| * @return |
| */ |
| public static TraceScope startSpan(String description, Span parent) { |
| return continueSpan(parent.child(description)); |
| } |
| |
| public static TraceScope startSpan(String description, TraceInfo tinfo) { |
| if (tinfo == null) return continueSpan(null); |
| Span newSpan = new MilliSpan(description, tinfo.traceId, tinfo.spanId, |
| random.nextLong(), Tracer.getProcessId()); |
| return continueSpan(newSpan); |
| } |
| |
| public static <T> TraceScope startSpan(String description, Sampler<T> s) { |
| return startSpan(description, s, null); |
| } |
| |
| public static <T> TraceScope startSpan(String description, Sampler<T> s, T info) { |
| Span span = null; |
| if (isTracing() || s.next(info)) { |
| span = Tracer.getInstance().createNew(description); |
| } |
| return continueSpan(span); |
| } |
| |
| /** |
| * Pick up an existing span from another thread. |
| */ |
| public static TraceScope continueSpan(Span s) { |
| // Return an empty TraceScope that does nothing on |
| // close |
| if (s == null) return new TraceScope(null, null); |
| return Tracer.getInstance().continueSpan(s); |
| } |
| |
| /** |
| * Stop any spans that are currently active, as well |
| * as their parents. This can be used within threadpools, |
| * etc where you should clean up after anyone who might |
| * have accidentally leaked spans. |
| */ |
| public static void clearTraceStack() { |
| Tracer.getInstance().clearTraceStack(); |
| } |
| |
| /** |
| * Set the processId to be used for all Spans created by this Tracer. |
| * |
| * @see Span.java |
| * @param processId |
| */ |
| public static void setProcessId(String processId) { |
| Tracer.processId = processId; |
| } |
| |
| /** |
| * Removes the given SpanReceiver from the list of SpanReceivers. |
| * |
| * @param rcvr |
| */ |
| public static void removeReceiver(SpanReceiver rcvr) { |
| Tracer.getInstance().removeReceiver(rcvr); |
| } |
| |
| /** |
| * Adds the given SpanReceiver to the current Tracer instance's list of |
| * SpanReceivers. |
| * |
| * @param rcvr |
| */ |
| public static void addReceiver(SpanReceiver rcvr) { |
| Tracer.getInstance().addReceiver(rcvr); |
| } |
| |
| /** |
| * Adds a data annotation to the current span if tracing is currently on. |
| */ |
| public static void addKVAnnotation(byte[] key, byte[] value) { |
| currentSpan().addKVAnnotation(key, value); |
| } |
| |
| /** |
| * Annotate the current span with the given message. |
| */ |
| public static void addTimelineAnnotation(String msg) { |
| currentSpan().addTimelineAnnotation(msg); |
| } |
| |
| /** |
| * Returns true if the current thread is a part of a trace, false otherwise. |
| * |
| * @return |
| */ |
| public static boolean isTracing() { |
| return Tracer.getInstance().isTracing(); |
| } |
| |
| /** |
| * If we are tracing, return the current span, else null |
| * |
| * @return Span representing the current trace, or null if not tracing. |
| */ |
| public static Span currentSpan() { |
| return Tracer.getInstance().currentTrace(); |
| } |
| |
| /** |
| * Wrap the callable in a TraceCallable, if tracing. |
| * |
| * @param callable |
| * @return The callable provided, wrapped if tracing, 'callable' if not. |
| */ |
| public static <V> Callable<V> wrap(Callable<V> callable) { |
| if (isTracing()) { |
| return new TraceCallable<V>(Trace.currentSpan(), callable); |
| } else { |
| return callable; |
| } |
| } |
| |
| /** |
| * Wrap the runnable in a TraceRunnable, if tracing |
| * |
| * @param runnable |
| * @return The runnable provided, wrapped if tracing, 'runnable' if not. |
| */ |
| public static Runnable wrap(Runnable runnable) { |
| if (isTracing()) { |
| return new TraceRunnable(Trace.currentSpan(), runnable); |
| } else { |
| return runnable; |
| } |
| } |
| } |