always: Always
Samples everything, whatever the parent said. The starting point for a service whose traffic is small enough to keep whole.
Generated from the interfaces MoonBit prints for this module, so nothing public is missing and no signature was typed twice. The prose is the documentation comment beside the code.
moonbitstack/moontel/trace
The span model, the tracer that mints spans, the four samplers, and
the two traits a caller implements: Sink for where spans
go and Sampler for what is kept. Nothing here reads a
clock, opens a socket or looks at a header.
always: Always
Samples everything, whatever the parent said. The starting point for a service whose traffic is small enough to keep whole.
discard: Discard
Throws spans away. The default for a tracer whose owner has not decided where they go yet, and the sink a replay uses when it only cares that nothing crashes.
dropped_nothing: Dropped
Nothing dropped, the value a span starts with.
empty_trace_state: TraceState
No vendor state: what a new trace starts with, and what a hop that carries nothing forward hands on.
never: Never
Samples nothing. Useful behind parent_based, where it is the answer for a parent that was not sampled.
parent_based(root~ : &Sampler, remote_sampled? : &Sampler, remote_unsampled? : &Sampler, local_sampled? : &Sampler, local_unsampled? : &Sampler) -> ParentBased
Parent-based sampling over root, which decides for the first span of a trace.
random_flag: Byte
The random bit W3C Trace Context level 2 uses to say a trace id was drawn at random. Carried through a hop unchanged; this library does not read it.
ratio(ratio~ : Double) -> Ratio
A ratio sampler. A ratio outside 0 to 1 is clamped, so configuration read from a file cannot produce a sampler that samples more than everything or less than nothing.
sampled_flag: Byte
The sampled bit of traceparent's flags field (W3C Trace Context §3.2.2.5).
trace_limits: Limits
The OpenTelemetry defaults, from the trace SDK specification's span limits table.
tracestate_limit: Int32
The list-members W3C Trace Context allows in one tracestate (§3.3.1).
Refused
Why a header, an id or a span id source was refused.
One error type for the whole module: a caller parsing an inbound traceparent and a caller handing the tracer a broken source of randomness both have one thing to catch.
Field(at~ : Int32, want~ : String)
A field that is not what the grammar asks for, at this offset in the input.
NotHex(at~ : Int32)
A character that has to be a lowercase hexadecimal digit and is not, at this offset. Uppercase is refused here because W3C Trace Context writes the fields in lowercase, and a parser that accepted both would let two spellings of one trace id into the same backend.
Zero(at~ : Int32)
An id that is all zero octets, which W3C Trace Context declares invalid.
TooMany(limit~ : Int32, got~ : Int32)
More list-members than the limit allows.
TooLong(limit~ : Int32, got~ : Int32)
A header longer than the limit, in octets.
Ids(want~ : Int32, got~ : Int32)
A source of randomness that did not hand back the number of octets asked
for: rand(16) owes sixteen, and anything else is a broken generator rather
than an id this library can guess at.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Always
Samples everything, whatever the parent said. The starting point for a service whose traffic is small enough to keep whole.
Also on the type: description · should_sample — derived, or required by an implementation above.
Decision
The three answers a sampler can give.
Drop
Not recorded at all: the tracer hands back a span that forgets everything, so instrumented code needs no branch of its own.
RecordOnly
Recorded but not sent on: the span keeps its attributes and reaches the
sink, and the sampled bit stays clear so its children are dropped too.
RecordAndSample
Recorded and sent on.
Decision::recording(Self) -> Bool
Whether the span reaches the sink with data in it.
Decision::sampled(Self) -> Bool
Whether the sampled bit is set and the trace continues.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Discard
Throws spans away. The default for a tracer whose owner has not decided where they go yet, and the sink a replay uses when it only cares that nothing crashes.
Also on the type: accept — derived, or required by an implementation above.
Dropped
How much a span gave up at its limits. OpenTelemetry asks for the counts rather than for the dropped values, so a reader can tell "this span had no attributes" from "this span had three hundred and we kept 128".
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Event
Something that happened during a span: a name, when it happened, and what it carried. Events keep the order they were added in, which for timestamps handed in by the caller is not necessarily the order of those timestamps.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Limits
How much one span collects.
The defaults are OpenTelemetry's: 128 attributes, 128 events, 128 links, 128 attributes on an event, and no limit on the length of a value. They exist to keep instrumentation that loops over user data from taking the process down with it, so the counts are per span and fixed when the span starts.
None keeps values of any length. A number cuts every string attribute to that many characters, counting each as one.
Limits::new(attributes? : Int32, events? : Int32, links? : Int32, attributes_per_event? : Int32, attribute_value_length? : Int32?) -> Self
The same defaults, with any of them changed.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Link
A causal relationship to another span that is not this one's parent — a batch item, a message consumed later, a fan-in. The linked context travels with the link so a reader can join the two traces.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Never
Samples nothing. Useful behind parent_based, where it is the answer for a parent that was not sampled.
Also on the type: description · should_sample — derived, or required by an implementation above.
ParentBased
Follows the parent's decision and asks root only when there is no parent.
This is the sampler to give a service, because it is what keeps a distributed trace whole: the hop that made the decision decided for the whole trace, and every later hop obeys it instead of rolling its own dice.
The specification's five rows are the five fields: root without a parent, then a parent from another process or this one, sampled or not. The default for a sampled parent is always and for an unsampled one never, so a program that names only root follows the parent.
Also on the type: description · should_sample — derived, or required by an implementation above.
Ratio
Samples a fixed fraction of traces, decided by the trace id rather than by a coin: the same id gets the same answer on every hop, in every process, and from every service, so a trace that one service keeps is not dropped by the next.
The fraction is read off the low 64 bits of the trace id, which the specification asks for so that two rates nest: raising the rate keeps every trace the lower rate kept.
Also on the type: description · should_sample · to_repr — derived, or required by an implementation above.
Recorder
Keeps spans in memory, in the order they finished.
Meant for replays, examples and the debugging of a single request; a service wants a sink that ships spans off the process, because this one grows without bound.
Recorder::len(Self) -> Int32
How many spans are kept.
Recorder::new() -> Self
An empty recorder.
Recorder::spans(Self) -> Array[SpanData]
The spans kept so far, oldest first.
Recorder::take(Self) -> Array[SpanData]
The spans kept so far, and an empty recorder afterwards. Use this when a replay drives several requests through one tracer and reads one request's spans at a time.
Also on the type: accept — derived, or required by an implementation above.
SampleRequest
What a sampler is told about the span it is deciding on.
The four things a sampler may look at are all known before the span exists: the parent, the trace id the span will carry, its name and its kind. Later changes — a better name, an attribute discovered mid-request — cannot move the decision, which is why the decision is made here and not on the finished span.
Span
The span a caller holds: an identity fixed at creation, and fields that fill in until it is finished.
Everything that changes after creation sits behind a Ref, so one span may be filled in from the task that opened it and read from another. A non-recording span — one the sampler dropped — accepts the same calls and forgets them, which is what lets instrumented code stay the same whatever the sampler decided.
Span::add_event(Self, String, attributes? : Array[(String, Value)], at~ : Int64) -> Unit
Add an event. at is the moment the caller says it happened, so a span recorded after the fact keeps its real timeline.
Span::add_link(Self, Link) -> Unit
Add a link to another span after creation, past the link limit being counted rather than applied.
Span::attributes(Self) -> Array[(String, Value)]
A copy of the attributes set so far, in the order their keys first appeared.
Span::context(Self) -> TraceContext
The identity of the span. It does not change for the span's whole life and stays usable after it ends, because a later span may still name this one as its parent.
Span::events(Self) -> Array[Event]
A copy of the events added so far, in the order they were added.
Span::finish(Self, at~ : Int64) -> Unit
Finish the span at at, handing it to the sink once.
Finishing twice does nothing the second time, and finishing a span the sampler dropped hands nothing over. Child spans are untouched: they may still be running, and they keep naming this one as their parent.
Span::is_ended(Self) -> Bool
Whether the span has been finished. A finished span takes no more writes and is not handed to the sink a second time.
Span::is_recording(Self) -> Bool
Whether the span is collecting anything: false after it ends, and false for a span the sampler dropped. Instrumented code can use it to skip building expensive attributes.
Span::links(Self) -> Array[Link]
A copy of the links added so far.
Span::name(Self) -> String
The name the span carries now, which set_name may have changed since it started.
Span::record_exception(Self, message~ : String, at~ : Int64, type_? : String, stacktrace? : String, attributes? : Array[(String, Value)]) -> Unit
Record an error the way OpenTelemetry's exception conventions ask: an event named exception carrying exception.type, exception.message and exception.stacktrace, with any attributes of the caller's own taking precedence over those three.
Span::set_attribute(Self, String, Value) -> Unit
Set one attribute. A key already present is overwritten in place, so the attribute list keeps the order in which keys first appeared rather than the order of their last write.
Past the attribute limit the write is dropped and counted rather than applied: a span with a runaway loop of attributes must not take the process down with it.
Span::set_attributes(Self, Array[(String, Value)]) -> Unit
Set several attributes at once, each following the same rule as set_attribute.
Span::set_name(Self, String) -> Unit
Rename the span. The sampler has already decided, so a better name found during the request cannot change that decision — it changes what the backend draws.
Span::set_status(Self, Status) -> Unit
Set the status, judged against the order Ok above Error above Unset: Unset changes nothing, Ok is final, and a later Error replaces an earlier one so the message can improve.
Span::status(Self) -> Status
The status as it stands: Unset until a caller sets one.
SpanData
A finished span, as a Sink receives it.
It is a value, not a handle: everything in it is settled, and a sink may keep it, queue it or throw it away. Nothing here is normalised — a span may begin and end at the same nanosecond, and an event may carry a time outside the span.
The parent's span id, or None for the first span of a trace. The parent's own context is deliberately not carried: a child needs the id to say where it hangs, and nothing else about the parent.
SpanData::duration(Self) -> Int64
How long the span lasted, in nanoseconds. Negative only if the caller handed in an end before the start, which is left as it came.
SpanData::sampled(Self) -> Bool
Whether this span carries the sampled bit, which is the one thing a sink needs in order to choose between exporting and merely counting.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
SpanKind
What a span is about, from the point of view of the process that made it. The kind is part of the sampling input and of what a backend draws, so it is settled when the span starts.
Internal
Server
Client
Producer
Consumer
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Status
How the operation ended, as the caller judges it.
The three values form a total order, Ok above Error above Unset, and a status is judged against that order rather than by "last write wins": Ok is final, Error may replace another Error because the message may improve, and Unset is what a span already has.
Unset means "the caller has no opinion", which is not a failure: an instrumentation library leaves it alone unless the semantic conventions say otherwise.
Unset
Ok
Error(String)
Also on the type: equal · not_equal · output · to_repr · to_string — derived, or required by an implementation above.
TraceContext
The identity of a span: the trace it belongs to, its own id, the flags travelling with it, and the vendor state riding along.
Ids are octets, not text: sixteen for the trace and eight for the span, as W3C Trace Context lays them out. Hexadecimal is a spelling used at the wire and in logs, and it is produced there rather than stored here.
remote is the specification's IsRemote: true for a context read off the wire, false for one this process minted. It does not travel in any header.
TraceContext::is_valid(Self) -> Bool
Whether the trace id is sixteen octets and the span id eight, neither all zero. A context that fails this is not a trace to join.
TraceContext::new(trace_id~ : Bytes, span_id~ : Bytes, flags? : Byte, state? : TraceState, remote? : Bool) -> Self
TraceContext::sampled(Self) -> Bool
Whether the sampled bit is set: the flag that says this span, and the children that carry it, are wanted by whoever reads the traces.
TraceContext::to_traceparent(Self) -> String
The traceparent header value for this context: version 00, the trace id, the span id, and the flags, in lowercase hexadecimal.
TraceContext::with_sampled(Self, sampled~ : Bool) -> Self
The same context with the sampled bit set or cleared, which is what a sampler's decision turns into. Every other flag travels as it came: a version of the header this library has not met may have put meaning in them.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
TraceState
Vendor state travelling with the trace, as an ordered list of at most 32 list-members (W3C Trace Context §3.3.1).
It is a list, not a map: the order is what a hop writes back, the first member belongs to the closest hop, and two members may not share a key. The update operations return a new state rather than editing this one, so that a caller holding the state that arrived cannot change what it arrived as.
TraceState::delete(Self, String) -> Self
The same state without the member key names, and unchanged when there is none.
TraceState::get(Self, String) -> String?
The value key is bound to, or None when the state has no such member.
TraceState::insert(Self, key~ : String, value~ : String) -> Self raise Refused
The same state with key set to value as the member closest to this hop (W3C Trace Context §3.3.1): an existing member with that key is replaced rather than moved, and a list already at 32 members drops its rightmost.
Building a header to send means adding your own entry to what came in, which is the one mutation a hop is allowed to make.
TraceState::is_empty(Self) -> Bool
Whether the hop carried no vendor state at all.
TraceState::len(Self) -> Int32
How many list-members the state carries.
TraceState::parse(StringView) -> Self raise Refused
Parse a tracestate header value.
Strict on purpose: a list-member that does not match the grammar or a list longer than 32 members refuses the whole header. A hop that kept the parseable half of a broken tracestate would hand the next hop something the sender never wrote, and W3C Trace Context §3.3.1 asks for the header to be dropped instead.
The one place the reading is wider than §3.3.1's ABNF is the key: the W3C Trace Context's reference parser is followed there, so foo@ and foo@@bar are list-members like any other. check_key says why, and says what is still out.
A key that appears twice is the one thing handled member by member: the first member with that key wins and the later one is dropped, which is the choice W3C Trace Context level 2 allows ("pass the duplicate on as-is or drop one of them") and the one W3C Trace Context's reference parser makes.
Whitespace before a member and after a value is dropped, as is whitespace around the commas; whitespace anywhere else is part of a key or a value that the grammar does not allow.
TraceState::to_header(Self) -> String
The header value: members in order, key=value, comma-separated, with no whitespace (W3C Trace Context §3.3.1.2). Empty when there is no state, which on the wire is the same as no header being sent.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Tracer
Makes spans, and the one place ids and the sampling decision are settled.
A tracer holds three things it cannot invent for itself: where randomness comes from, where finished spans go, and who decides whether a trace is wanted. The clock is the fourth, and it does not even reach the tracer — every call that needs a time is handed one.
Tracer::new(rand~ : (Int32) -> Bytes, sink~ : &Sink, sampler~ : &Sampler, limits? : Limits) -> Self
A tracer drawing ids from rand, handing finished spans to sink, and asking sampler about every span it starts.
rand(n) must return exactly n octets and must not return all zeros: eight octets of zeros is not a valid span id, and a generator that produces one is broken rather than unlucky. A call that breaks either rule makes start refuse; see Refused::Ids and Refused::Zero.
Tracer::start(Self, String, parent? : TraceContext, kind? : SpanKind, at~ : Int64, attributes? : Array[(String, Value)], links? : Array[Link]) -> Span raise Refused
Start a span.
With a parent whose context is valid, the new span joins that trace: it takes the parent's trace id and trace state, and parent_based sampling follows the parent's decision. Without one it starts a trace of its own, with a fresh trace id and no vendor state.
at is the start of the operation in nanoseconds. attributes and links are set before the span is handed back; a sampler sees them, which is why they are parameters here rather than calls on the span afterwards.
Value
One attribute value.
The arrays are separate variants rather than one array of Value because OpenTelemetry requires an array attribute to be homogeneous, and because that is what an exporter has to write: a mixed array has no single type tag.
Bool(Bool)
Int(Int64)
A signed 64-bit integer. Nanosecond timestamps and byte counts both fit; a
Double would lose the low digits of a nanosecond clock.
Double(Double)
Str(String)
Bools(Array[Bool])
Ints(Array[Int64])
Doubles(Array[Double])
Strs(Array[String])
Also on the type: equal · not_equal · output · to_repr · to_string — derived, or required by an implementation above.
Sampler
Whether a span is wanted, and how much of it.
A caller can plug in its own: the four here are the ones the specification names, and anything with a decision — a rate limit read from configuration, a list of paths that must never be dropped — is another implementation of this.
Sampler::should_sample(Self, SampleRequest) -> Decision
Decide whether the span is wanted, and how much of it to record.
Sampler::description(Self) -> String
A short name for logs and debug pages, e.g. TraceIdRatioBased{0.25}.
Sink
Where finished spans go.
This is the one seam this library leaves open: exporting to OTLP, to a file, to a ring buffer that a background task drains, or to nothing at all is the caller's business, and the shapes that do it belong to whoever owns the transport. A sink is called on the task that finished the span, so an implementation that writes to a socket should hand the span to a queue rather than block the request.
A sink receives every recorded span, including the ones the sampler dropped from the trace: SpanData::sampled is the bit that separates "keep for counting" from "send to the backend".
Sink::accept(Self, SpanData) -> Unit
Take one finished span. Called on the task that finished it, so an implementation that writes to a socket should queue rather than block.
moonbitstack/moontel/propagate
W3C Trace Context and W3C Baggage at the header level: what the values
look like on the wire, how to read them off a request, and how to put
them back on the next one. The two calls a service uses are
extract and inject.
baggage_byte_limit: Int32
The size W3C Baggage §3.2.1.3 requires a platform to propagate: 8192 octets of combined header.
baggage_header: String
The header baggage travels in (W3C Baggage §3.2.1).
baggage_member_limit: Int32
The list-members W3C Baggage §3.2.1.3 requires a platform to propagate: a header of 64 members or fewer must survive the hop whole.
empty_baggage: Baggage
Nothing carried, which a request with no baggage header arrives with.
extract(Array[(String, String)]) -> Extracted
Read the propagation headers out of headers, which is the shape both an ASGI scope and an outgoing request carry.
Header names are matched without regard to case; a value is taken as it is, with the whitespace around it dropped.
Two traceparent headers refuse each other: the specification says a request with more than one is invalid, and picking one of the two would be guessing which proxy wrote the one that matters. Several tracestate or baggage headers are combined in order, as RFC 7230 allows a field to be split across lines.
A header that does not parse leaves that field empty and the rest intact: a mangled tracestate must not cost a hop the trace, and a mangled baggage must not cost it the trace either.
inject(Array[(String, String)], Extracted) -> Array[(String, String)]
Put extracted back into headers: the propagation headers already there are removed and rewritten from the context and the bag, and everything else is left exactly as it was.
Rewriting rather than appending is what makes this safe to call on a request that already carried a context — the one from the sender must not survive next to the one this hop decided on.
parse(StringView, tracestate? : StringView) -> @trace.TraceContext raise @trace.Refused
A parsed traceparent, plus the vendor state that came with it.
version is kept even though nothing here acts on it: a caller debugging a failed handshake wants to know which version of the header the other side spoke, and a version above zero may one day carry fields this library does not read.
The ids are validated on the way in — sixteen and eight octets, neither all zero — because a context that fails that is not a trace to join, and passing it on would make a broken hop look like a working one.
parse_traceparent(StringView) -> @trace.TraceContext raise @trace.Refused
Parse a traceparent header value, without any vendor state.
The grammar is W3C Trace Context §3.2:
``text version(2)-trace-id(32)-parent-id(16)-trace-flags(2) ``
A version this library does not know may append fields, but only after a -: 00 headers end at 55 characters, and 00-…-01.whatever is refused rather than read as a version-0 header with a suffix. Version ff is refused by the specification, as is an all-zero id.
Whitespace around the value is dropped. HTTP allows OWS around a field value, and W3C Trace Context's examples send it; whitespace anywhere inside is refused as the illegal character it is.
parse_tracestate(StringView) -> @trace.TraceState raise @trace.Refused
Parse a tracestate header value. The grammar lives with the type that holds the state; this is the name a caller reaching for the header uses.
traceparent_header: String
The header traceparent travels in (W3C Trace Context §3.2.1). Lowercase on the wire; lookups here compare without regard to case.
tracestate_header: String
The header tracestate travels in (W3C Trace Context §3.3.1).
Baggage
Keys and values carried alongside a trace, ordered, with duplicates allowed.
Order is part of the data: W3C Baggage asks a hop to preserve the order of duplicate entries when it mutates the list, so this is an array rather than a map. get answers with the first member carrying a key, which is the one a reader asking "what did the caller say" wants.
Baggage::add(Self, Member) -> Self
The same bag with member added at the end, past the member limit keeping the bag as it was rather than growing an unusable header.
Baggage::get(Self, String) -> String?
The value of the first member keyed key, or None.
Baggage::is_empty(Self) -> Bool
Whether the bag has no members.
Baggage::len(Self) -> Int32
How many members the bag carries.
Baggage::new(members? : Array[Member]) -> Self
A bag carrying members, in the order given.
Baggage::parse(StringView) -> Self raise @trace.Refused
Parse a baggage header value (W3C Baggage §3.2).
Whitespace around a member, around an =, and around the commas is dropped; a member that does not match the grammar refuses the whole header, because a half-read bag is a bag the next hop would rewrite. Values are percent-decoded and sequences that are not UTF-8 become U+FFFD, as §3.2.2.2 asks.
The limits are the ones a platform must propagate — 64 members and 8192 octets — checked against the value as it arrived, and enforced by refusing rather than truncating: a caller that receives a bag too big to be legal has received something a middlebox either wrote or mangled, and guessing which members it meant is not this library's business.
Baggage::to_header(Self) -> String
The header value: members in order, key=value with properties after ;, and every character outside the baggage-octet set percent-encoded in uppercase hexadecimal (W3C Baggage §3.2.2.2). Empty when the bag is empty, which on the wire is the same as sending no header. encode_value says why a space is %20 rather than the + form encoding would use.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Extracted
What a hop takes out of a set of request headers: the trace it joins, if the request carried one, and the baggage that came with it.
One value rather than two calls, because a hop that reads one and forgets the other is a bug this shape makes hard to write: inject puts back exactly what extract found, changed only where the caller changed it.
The parent context, or None when the request carried no context or carried one this library refused. A refused context is not an error here: W3C Trace Context says a hop starts a new trace rather than failing the request.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Member
One baggage entry: a key, a value, and any properties attached to it.
The value is stored decoded, as text. The wire form is percent-encoded ASCII, and decoding is where a hop stops caring how the value was spelled.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
Property
One metadata entry on a baggage member: key or key=value, after the ; of a list-member (W3C Baggage §3.2.2.3). The specification gives properties no meaning of their own; they are carried so a hop that does not understand one can pass it on unchanged.
None for a property written as a bare key.
Also on the type: equal · not_equal · to_repr — derived, or required by an implementation above.
moonbitstack/moontel/asgi
One middleware: a server span per HTTP request, joined to the trace
the request arrived with, and the context written back on the
response. It implements the framework's Layer, so it
stacks with the rest.
method_and_path(String, String) -> String
The default span name: the method and the path, e.g. GET /orders/42.
Tracing
One server span per HTTP request, joined to the trace the request arrived with.
The layer does three things and no more: it reads traceparent and baggage off the request, it opens a span of kind Server as a child of what it read, and it writes the resulting context back on the response. A request that carried no context starts a trace; one that carried a broken context also starts a trace, because refusing the request over a header would be worse than a missing link in the trace.
The span reaches the sink when the application returns, with the response status on it. A request the application fails is recorded as an exception event before the error is passed on to the server, which is what an ASGI server keeps.
The clock. This library never reads one itself, so a replay can drive a request through a timeline it chose and a service can hand in whichever clock it already trusts. Nanoseconds since any fixed origin.
How a request is named. The default is the method and the path, which is what the middleware can see; a site that knows its routes should pass the route template instead, so that /orders/42 and /orders/43 are one span name rather than a thousand.
Whether baggage rides along to the response. On by default: a hop that quietly drops what the caller attached is worse than one that never had it.
Paths to leave untraced. A health check every second is noise a backend pays for and nobody reads.
Tracing::new(tracer~ : @trace.Tracer, now~ : () -> Int64, name? : (String, String) -> String, baggage? : Bool, ignore? : Array[String]) -> Self
A tracing layer over tracer.
Tracing::wrap(Self, async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit) -> async (@spec.Scope, async () -> @spec.Event, async (@spec.Event) -> Unit) -> Unit
Wraps an application in a server span per request. wrap is the Layer method, so the middleware can sit in a stack beside the framework's own layers as well as around a single application.
moonbitstack/moontel
One import for a program that wants all three packages. A type is re-exported, not copied, so it is the same type the package defines; a constructor is still reached through the package that owns it.
pub using @trace
Tracer, Span, TraceContext,
Value, Limits, the four samplers,
Recorder and Discard, and the traits
Sink and Sampler.
pub using @propagate
extract, inject, parse,
parse_traceparent, parse_tracestate,
Baggage, Extracted, Member,
Property, and the three header names.
pub using @asgi
Tracing, and method_and_path.
constructors
A re-exported enum or struct arrives without its constructors:
that is the language's rule, not a decision here. To build an
attribute value, import trace and write
@trace.Str("…"); the facade alone cannot spell it.
Nothing matches that. Clear the filter.