sammccall created this revision. sammccall added a reviewer: kadircet. Herald added subscribers: cfe-commits, usaxena95, arphaman. Herald added a project: clang. sammccall requested review of this revision. Herald added subscribers: MaskRay, ilya-biryukov.
The tracer is now expected to allocate+free the args itself. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D89135 Files: clang-tools-extra/clangd/support/Trace.cpp clang-tools-extra/clangd/support/Trace.h clang-tools-extra/clangd/unittests/support/TraceTests.cpp
Index: clang-tools-extra/clangd/unittests/support/TraceTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/support/TraceTests.cpp +++ clang-tools-extra/clangd/unittests/support/TraceTests.cpp @@ -186,6 +186,11 @@ StartsWith("d,dist,\"a\nb\",1"), "")); } +TEST_F(CSVMetricsTracerTest, IgnoresArgs) { + trace::Span Tracer("Foo"); + EXPECT_EQ(nullptr, Tracer.Args); +} + } // namespace } // namespace clangd } // namespace clang Index: clang-tools-extra/clangd/support/Trace.h =================================================================== --- clang-tools-extra/clangd/support/Trace.h +++ clang-tools-extra/clangd/support/Trace.h @@ -79,8 +79,11 @@ /// Returns a derived context that will be destroyed when the event ends. /// Usually implementations will store an object in the returned context /// whose destructor records the end of the event. - /// The args are *Args, only complete when the event ends. - virtual Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args); + /// If the tracer wants event details, it should call RequestArgs. The pointer + /// must be valid over the whole event, and will be populated before it ends. + virtual Context + beginSpan(llvm::StringRef Name, + llvm::function_ref<void(llvm::json::Object *)> RequestArgs); // Called when a Span is destroyed (it may still be active on other threads). // beginSpan() and endSpan() will always form a proper stack on each thread. // The Context returned by beginSpan is active, but Args is not ready. @@ -146,6 +149,8 @@ llvm::json::Object *const Args; private: + // Awkward constructor works around constant initialization. + Span(std::pair<Context, llvm::json::Object *>); WithContext RestoreCtx; }; Index: clang-tools-extra/clangd/support/Trace.cpp =================================================================== --- clang-tools-extra/clangd/support/Trace.cpp +++ clang-tools-extra/clangd/support/Trace.cpp @@ -53,9 +53,12 @@ // We stash a Span object in the context. It will record the start/end, // and this also allows us to look up the parent Span's information. - Context beginSpan(llvm::StringRef Name, llvm::json::Object *Args) override { - return Context::current().derive( - SpanKey, std::make_unique<JSONSpan>(this, Name, Args)); + Context beginSpan( + llvm::StringRef Name, + llvm::function_ref<void(llvm::json::Object *)> RequestArgs) override { + auto JS = std::make_unique<JSONSpan>(this, Name); + RequestArgs(&JS->Args); + return Context::current().derive(SpanKey, std::move(JS)); } // Trace viewer requires each thread to properly stack events. @@ -85,9 +88,10 @@ private: class JSONSpan { public: - JSONSpan(JSONTracer *Tracer, llvm::StringRef Name, llvm::json::Object *Args) + llvm::json::Object Args; + JSONSpan(JSONTracer *Tracer, llvm::StringRef Name) : StartTime(Tracer->timestamp()), EndTime(0), Name(Name), - TID(llvm::get_threadid()), Tracer(Tracer), Args(Args) { + TID(llvm::get_threadid()), Tracer(Tracer) { // ~JSONSpan() may run in a different thread, so we need to capture now. Tracer->captureThreadMetadata(); @@ -125,7 +129,7 @@ // Finally, record the event (ending at EndTime, not timestamp())! Tracer->jsonEvent("X", llvm::json::Object{{"name", std::move(Name)}, - {"args", std::move(*Args)}, + {"args", std::move(Args)}, {"dur", EndTime - StartTime}}, TID, StartTime); } @@ -144,7 +148,6 @@ std::string Name; uint64_t TID; JSONTracer *Tracer; - llvm::json::Object *Args; }; static Key<std::unique_ptr<JSONSpan>> SpanKey; @@ -277,12 +280,11 @@ T->instant("Log", llvm::json::Object{{"Message", Message.str()}}); } -// Returned context owns Args. -static Context makeSpanContext(llvm::Twine Name, llvm::json::Object *Args, - const Metric &LatencyMetric) { +// The JSON object is event args (owned by context), if the tracer wants them. +static std::pair<Context, llvm::json::Object *> +makeSpanContext(llvm::Twine Name, const Metric &LatencyMetric) { if (!T) - return Context::current().clone(); - WithContextValue WithArgs{std::unique_ptr<llvm::json::Object>(Args)}; + return std::make_pair(Context::current().clone(), nullptr); llvm::Optional<WithContextValue> WithLatency; using Clock = std::chrono::high_resolution_clock; WithLatency.emplace(llvm::make_scope_exit( @@ -293,9 +295,12 @@ .count(), Name); })); - return T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef() - : llvm::StringRef(Name.str()), - Args); + llvm::json::Object *Args = nullptr; + Context Ctx = + T->beginSpan(Name.isSingleStringRef() ? Name.getSingleStringRef() + : llvm::StringRef(Name.str()), + [&](llvm::json::Object *A) { Args = A; }); + return std::make_pair(std::move(Ctx), Args); } // Fallback metric that measures latencies for spans without an explicit latency @@ -307,8 +312,9 @@ // beginSpan() context is destroyed, when the tracing engine will consume them. Span::Span(llvm::Twine Name) : Span(Name, SpanLatency) {} Span::Span(llvm::Twine Name, const Metric &LatencyMetric) - : Args(T ? new llvm::json::Object() : nullptr), - RestoreCtx(makeSpanContext(Name, Args, LatencyMetric)) {} + : Span(makeSpanContext(Name, LatencyMetric)) {} +Span::Span(std::pair<Context, llvm::json::Object *> Pair) + : Args(Pair.second), RestoreCtx(std::move(Pair.first)) {} Span::~Span() { if (T) @@ -323,7 +329,9 @@ T->record(*this, Value, Label); } -Context EventTracer::beginSpan(llvm::StringRef Name, llvm::json::Object *Args) { +Context EventTracer::beginSpan( + llvm::StringRef Name, + llvm::function_ref<void(llvm::json::Object *)> RequestArgs) { return Context::current().clone(); } } // namespace trace
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits