/* * Copyright 2015-present Facebook, Inc. * * Licensed 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 com.facebook.buck.event.api; import java.util.Collections; import java.util.Map; /** * Allows annotation processors and other compiler plug-ins to output tracing information to Buck's * trace files (when being run in-process in Buck). These methods do nothing if called within * another build system. */ public final class BuckTracing { /** * Buck can technically be invoked recursively within the same process, so we can't assume a * single process-wide implementation of {@link BuckTracingInterface}. */ private static final InheritableThreadLocal<BuckTracingInterface> curThreadTracingInterface = new InheritableThreadLocal<>(); private final String pluginName; private final TraceSection traceSection = new TraceSection(); /** * Gets an instance of {@link BuckTracing} for tracing in the given plugin. All {@link * BuckTracing} instances are backed by the same trace buffer, so {@link #begin(String, Map)} and * {@link #end(Map)}} calls on a given thread must nest across all instances. */ public static BuckTracing getInstance(String pluginName) { return new BuckTracing(pluginName); } private BuckTracing(String pluginName) { this.pluginName = pluginName; } public TraceSection traceSection(final String eventName) { begin(eventName); return traceSection; } /** * Records the beginning of a traced section, and returns an object that can be used within a * try-with-resources block to automatically end the section. The section will appear in the trace * labeled with eventName. */ public TraceSection traceSection(final String eventName, final Map<String, String> args) { begin(eventName, args); return traceSection; } /** * Records the beginning of a traced section. The section will appear in the trace labeled with * eventName. * * <p>For best results, this call should be immediately before a try block, and a corresponding * call to {@link #end(Map)} should be in the finally block. Consider using {@link * #traceSection(String)} in a try-with-resources block instead. */ public void begin(final String eventName) { begin(eventName, Collections.emptyMap()); } /** * Records the beginning of a traced section. The section will appear in the trace labeled with * eventName, and the supplied arguments will be visible when the section is selected. * * <p>For best results, this call should be immediately before a try block, and a corresponding * call to {@link #end(Map)} should be in the finally block. Consider using {@link * #traceSection(String, Map)} in a try-with-resources block instead. */ public void begin(final String eventName, final Map<String, String> args) { final BuckTracingInterface tracingInterface = curThreadTracingInterface.get(); if (tracingInterface == null) { return; } tracingInterface.begin(pluginName, eventName, args); } /** * Records the end of the traced section started by the most recent call to {@link #begin(String, * Map)}, on <em>any</em> {@link BuckTracing} object, on the current thread. * * <p>For best results, this call should be in a finally block, with the corresponding {@link * #begin(String, Map)} call immediately before the try. */ public void end() { end(Collections.emptyMap()); } /** * Records the end of the traced section started by the most recent call to {@link #begin(String, * Map)}, on <em>any</em> {@link BuckTracing} object, on the current thread. Arguments supplied * here will be added to those supplied to {@link #begin(String, Map)}; conflicting entries will * be overwritten. * * <p>For best results, this call should be in a finally block, with the corresponding {@link * #begin(String, Map)} call immediately before the try. */ public void end(final Map<String, String> args) { final BuckTracingInterface tracingInterface = curThreadTracingInterface.get(); if (tracingInterface == null) { return; } tracingInterface.end(args); } /** * Used by Buck to connect this class to its tracing mechanism. There is no need to call this * method manually. */ public static void setCurrentThreadTracingInterfaceFromJsr199Javac( final BuckTracingInterface buckTracingInterface) { curThreadTracingInterface.set(buckTracingInterface); } /** * Used by Buck to disconnect this class from its tracing mechanism. There is no need to call this * method manually. */ public static void clearCurrentThreadTracingInterfaceFromJsr199Javac() { curThreadTracingInterface.set(null); } /** * An {@link AutoCloseable} that can be used in a try-with-resources block to ensure a trace * section is ended properly when exited. */ public class TraceSection implements AutoCloseable { @Override public void close() { // We're just going to use the same instance of this thing over and over again, so don't // bother doing any kind of duplicate-close checking. end(); } } }