mirror of
https://github.com/XRPLF/rippled.git
synced 2026-07-24 15:40:26 +00:00
Bring the 5 telemetry files introduced on this branch to the enforced house Doxygen style (/** alone, ' * ' continuation prefix, no single-line blocks) so the check-doxygen-style hook passes under CI's --all-files run. Comment-only: code is byte-identical after comment stripping (verified). Also regenerate levelization results: the committed ordering.txt carried stale 'xrpl.telemetry > xrpld.consensus/rpc' edges that the current include graph no longer produces. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
96 lines
3.2 KiB
C++
96 lines
3.2 KiB
C++
#pragma once
|
|
|
|
/**
|
|
* Thread-local discard signaling between SpanGuard and the span processor.
|
|
*
|
|
* SpanGuard::discard() wants to drop a span without sending it to the
|
|
* exporter. The OTel SDK calls SpanProcessor::OnEnd() synchronously on the
|
|
* same thread that calls Span::End(), so a thread-local flag set just before
|
|
* End() and read inside OnEnd() lets FilteringSpanProcessor drop the span
|
|
* before it enters the batch export queue.
|
|
*
|
|
* This side-channel avoids inspecting the Recordable's internals (which vary
|
|
* by exporter type — SpanData vs OtlpRecordable).
|
|
*
|
|
* The flag is a *private* thread-local member of DiscardScope, mutated only by
|
|
* its constructor and destructor. This gives real access control rather than a
|
|
* naming convention: no code that includes this header can flip the flag
|
|
* directly — it can only enter a DiscardScope (which sets and clears the flag
|
|
* over its own lifetime) and observe the state via DiscardScope::isActive().
|
|
* Binding set/clear to a scope also means the flag cannot leak onto the next
|
|
* span even if End() were to throw.
|
|
*
|
|
* Kept in a separate header to avoid transitive include bloat: SpanGuard.h
|
|
* only needs this signaling, not the full Telemetry.h with BasicConfig/Journal.
|
|
*
|
|
* Usage:
|
|
* @code
|
|
* // In SpanGuard::discard():
|
|
* {
|
|
* DiscardScope discardScope; // flag set for this scope only
|
|
* span->End(); // OnEnd() runs synchronously, sees flag
|
|
* } // flag cleared here, unconditionally
|
|
*
|
|
* // In FilteringSpanProcessor::OnEnd():
|
|
* if (DiscardScope::isActive())
|
|
* return; // drop the span
|
|
* @endcode
|
|
*
|
|
* @note Thread safety: the flag is thread-local, so each thread observes only
|
|
* its own discard signal — no synchronization is required.
|
|
*
|
|
* @see SpanGuard::discard(), FilteringSpanProcessor (Telemetry.cpp)
|
|
*/
|
|
|
|
namespace xrpl::telemetry {
|
|
|
|
/**
|
|
* RAII guard that marks the current thread's span for discard.
|
|
*
|
|
* Sets the thread-local discard flag on construction and clears it on
|
|
* destruction, so a span ended within the guard's scope is dropped by
|
|
* FilteringSpanProcessor::OnEnd() while the flag stays confined to that scope.
|
|
* The flag is private and mutated only here, so no other code can set it.
|
|
* Non-copyable and non-movable — its sole purpose is the scoped flag lifetime.
|
|
*/
|
|
class DiscardScope
|
|
{
|
|
public:
|
|
DiscardScope() noexcept
|
|
{
|
|
discarding = true;
|
|
}
|
|
|
|
~DiscardScope()
|
|
{
|
|
discarding = false;
|
|
}
|
|
|
|
DiscardScope(DiscardScope const&) = delete;
|
|
DiscardScope&
|
|
operator=(DiscardScope const&) = delete;
|
|
DiscardScope(DiscardScope&&) = delete;
|
|
DiscardScope&
|
|
operator=(DiscardScope&&) = delete;
|
|
|
|
/**
|
|
* @return true if the current thread is inside a DiscardScope, i.e. the
|
|
* span ending now should be dropped rather than exported. Read by
|
|
* FilteringSpanProcessor::OnEnd().
|
|
*/
|
|
[[nodiscard]] static bool
|
|
isActive() noexcept
|
|
{
|
|
return discarding;
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* Thread-local discard flag. Private, so only this class's ctor/dtor can
|
|
* mutate it; observers use isActive(). One instance per thread.
|
|
*/
|
|
inline static thread_local bool discarding = false;
|
|
};
|
|
|
|
} // namespace xrpl::telemetry
|