[clang-tools-extra] Fix a link in ReleaseNotes.rst
[llvm-project.git] / clang-tools-extra / clangd / support / Trace.h
blob52ee2ae617da6098c8013313de0a6be2db8accc5
1 //===--- Trace.h - Performance tracing facilities ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Supports writing performance traces describing clangd's behavior.
10 // Traces are consumed by implementations of the EventTracer interface.
13 // All APIs are no-ops unless a Session is active (created by ClangdMain).
15 //===----------------------------------------------------------------------===//
17 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_TRACE_H_
18 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_TRACE_H_
20 #include "support/Context.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Support/JSON.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include <chrono>
26 #include <string>
27 #include <vector>
29 namespace clang {
30 namespace clangd {
31 namespace trace {
33 /// Represents measurements of clangd events, e.g. operation latency. Those
34 /// measurements are recorded per-label, defaulting to an empty one for metrics
35 /// that don't care about it. This enables aggregation of measurements across
36 /// labels. For example a metric tracking accesses to a cache can have labels
37 /// named hit and miss.
38 struct Metric {
39 enum MetricType {
40 /// A number whose value is meaningful, and may vary over time.
41 /// Each measurement replaces the current value.
42 Value,
44 /// An aggregate number whose rate of change over time is meaningful.
45 /// Each measurement is an increment for the counter.
46 Counter,
48 /// A distribution of values with a meaningful mean and count.
49 /// Each measured value is a sample for the distribution.
50 /// The distribution is assumed not to vary, samples are aggregated over
51 /// time.
52 Distribution,
54 constexpr Metric(llvm::StringLiteral Name, MetricType Type,
55 llvm::StringLiteral LabelName = llvm::StringLiteral(""))
56 : Name(Name), Type(Type), LabelName(LabelName) {}
58 /// Records a measurement for this metric to active tracer.
59 void record(double Value, llvm::StringRef Label = "") const;
61 /// Uniquely identifies the metric. Should use snake_case identifiers, can use
62 /// dots for hierarchy if needed. e.g. method_latency, foo.bar.
63 const llvm::StringLiteral Name;
64 const MetricType Type;
65 /// Indicates what measurement labels represent, e.g. "operation_name" for a
66 /// metric tracking latencies. If non empty all measurements must also have a
67 /// non-empty label.
68 const llvm::StringLiteral LabelName;
71 /// A consumer of trace events and measurements. The events are produced by
72 /// Spans and trace::log, the measurements are produced by Metrics::record.
73 /// Implementations of this interface must be thread-safe.
74 class EventTracer {
75 public:
76 virtual ~EventTracer() = default;
78 /// Called when event that has a duration starts. \p Name describes the event.
79 /// Returns a derived context that will be destroyed when the event ends.
80 /// Usually implementations will store an object in the returned context
81 /// whose destructor records the end of the event.
82 /// The tracer may capture event details provided in SPAN_ATTACH() calls.
83 /// In this case it should call AttachDetails(), and pass in an empty Object
84 /// to hold them. This Object should be owned by the context, and the data
85 /// will be complete by the time the context is destroyed.
86 virtual Context
87 beginSpan(llvm::StringRef Name,
88 llvm::function_ref<void(llvm::json::Object *)> AttachDetails);
89 // Called when a Span is destroyed (it may still be active on other threads).
90 // beginSpan() and endSpan() will always form a proper stack on each thread.
91 // The Context returned by beginSpan is active, but Args is not ready.
92 // Tracers should not override this unless they need to observe strict
93 // per-thread nesting. Instead they should observe context destruction.
94 virtual void endSpan() {}
96 /// Called for instant events.
97 virtual void instant(llvm::StringRef Name, llvm::json::Object &&Args) {}
99 /// Called whenever a metrics records a measurement.
100 virtual void record(const Metric &Metric, double Value,
101 llvm::StringRef Label) {}
104 /// Sets up a global EventTracer that consumes events produced by Span and
105 /// trace::log. Only one TracingSession can be active at a time and it should be
106 /// set up before calling any clangd-specific functions.
107 class Session {
108 public:
109 Session(EventTracer &Tracer);
110 ~Session();
113 /// Create an instance of EventTracer that produces an output in the Trace Event
114 /// format supported by Chrome's trace viewer (chrome://tracing).
116 /// FIXME: Metrics are not recorded, some could become counter events.
118 /// The format is documented here:
119 /// https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview
120 std::unique_ptr<EventTracer> createJSONTracer(llvm::raw_ostream &OS,
121 bool Pretty = false);
123 /// Create an instance of EventTracer that outputs metric measurements as CSV.
125 /// Trace spans and instant events are ignored.
126 std::unique_ptr<EventTracer> createCSVMetricTracer(llvm::raw_ostream &OS);
128 /// Records a single instant event, associated with the current thread.
129 void log(const llvm::Twine &Name);
131 /// Returns true if there is an active tracer.
132 bool enabled();
134 /// Records an event whose duration is the lifetime of the Span object.
135 /// This lifetime is extended when the span's context is reused.
137 /// This is the main public interface for producing tracing events.
139 /// Arbitrary JSON metadata can be attached while this span is active:
140 /// SPAN_ATTACH(MySpan, "Payload", SomeJSONExpr);
142 /// SomeJSONExpr is evaluated and copied only if actually needed.
143 class Span {
144 public:
145 Span(llvm::Twine Name);
146 /// Records span's duration in seconds to \p LatencyMetric with \p Name as the
147 /// label.
148 Span(llvm::Twine Name, const Metric &LatencyMetric);
149 ~Span();
151 /// Mutable metadata, if this span is interested.
152 /// Prefer to use SPAN_ATTACH rather than accessing this directly.
153 /// The lifetime of Args is the whole event, even if the Span dies.
154 llvm::json::Object *const Args;
156 private:
157 // Awkward constructor works around constant initialization.
158 Span(std::pair<Context, llvm::json::Object *>);
159 WithContext RestoreCtx;
162 /// Attach a key-value pair to a Span event.
163 /// This is not threadsafe when used with the same Span.
164 #define SPAN_ATTACH(S, Name, Expr) \
165 do { \
166 if (auto *Args = (S).Args) \
167 (*Args)[Name] = Expr; \
168 } while (0)
170 } // namespace trace
171 } // namespace clangd
172 } // namespace clang
174 #endif