@zudojs/observability
Logs, metrics and traces for a Zudojs application, behind one small facade you can point at any backend.
OVERVIEW
When your program runs on your laptop you can read the screen. When it runs on a server you cannot. Observability is the practice of making a running program explain itself from the outside, and this package gives you the three standard ways to do that.
- →Structured logs are messages with named fields instead of one glued-together sentence.
{ "message": "order paid", "orderId": "o_9" }can be searched and filtered;"order o_9 paid"cannot. - →Metrics are numbers measured over time — requests per minute, queue depth, response time. They answer "how much" and "how often", cheaply, forever.
- →Traces follow one request through every step it touches, so you can see which step was slow. A span is one of those steps: a named piece of work with a start time, an end time and some labelled facts attached.
This package does not talk to Datadog, Prometheus or OpenTelemetry itself. It defines the shapes — LogExporter, SpanExporter, MetricExporter — and ships console implementations. A provider package supplies a real one later, and your application code never changes.
USE IT WHEN
- Your code runs somewhere you cannot watch it.
- You need to know why one request out of a thousand was slow.
- You want counts and latencies you can graph.
- You are writing a library and want telemetry without picking a vendor for your users.
SKIP IT WHEN
- A script runs once on your machine and prints its result.
- Your host already collects everything you need and you are happy with plain
console.log. - You are inside a unit test — use
createNoopObservability()instead.
INSTALLATION
The runtime dependencies are @zudojs/errors and @zudojs/logger (whose secret-field rules the redactor reuses), which npm installs for you. Node 24 or newer is required — context propagation uses Node's built-in AsyncLocalStorage, so this package does not run in a browser.
These docs follow the framework source. If an export shown here is missing from the version you installed, update to the latest @zudojs release.
QUICK START
createObservability() builds one object holding a logger, a metrics registry, a tracer and a propagation manager. This is the only thing most applications create, and they create it once at startup.
This program logs a line, counts a request, times a span, and shuts everything down.
What you should see. Three JSON lines on stdout: one log record, one span, and one metric snapshot. The log line looks like this (formatted here for reading; it prints on a single line):
WATCH OUT
Printing to the console is the default, not a choice you made. useConsoleExporters defaults to true, so a deployed service will spray JSON at stdout until you pass real exporters or set it to false.
CHANGED IN 1.2.0
shutdown() exports the final metric snapshot once. Up to 1.1.x it exported it twice, with the same value and timestamp, so a backend that adds up counter exports counted the last interval double. If you added deduplication in your exporter for that, you can remove it. flush() is unchanged.
TIP
Always await obs.shutdown() before the process exits. Logs, spans and metrics are batched in memory, so anything not yet flushed is lost if you skip it. obs.flush() drains the buffers without closing anything.
LOGGING
A log level is a severity dial. Every message carries one, and the logger drops anything less severe than its threshold. LogLevel runs TRACE (0), DEBUG, INFO, WARN, ERROR, FATAL, OFF (6).
Every logging method takes the same three arguments: a message, an optional context object of named fields, and an optional error. Nothing is formatted into the message — the fields stay separate so a log tool can filter on them.
This creates a logger directly (no facade), writes at three levels, and shows what the threshold does.
What you should see. Two lines, not three. The info line goes to console.log; the error line goes to console.error and carries an error field with the name, message and stack.
Child loggers
logger.child(name, context) returns a new logger whose name is parent.child and whose context is merged into every record it writes. Use it to stamp a request ID once instead of on every call.
WATCH OUT
A child copies the parent's level at the moment it is created. Calling setLevel() on the parent afterwards does not reach children that already exist.
IN PLAIN WORDS
Logging never throws. If a transport fails, the failure is swallowed rather than crashing the code that was trying to log — so a broken log sink shows up as silence, not as an error.
METRICS
There are three kinds of metric, and picking the right one is most of the work:
- →A counter only ever goes up, and counts how many times something happened.
- →A gauge goes up and down, and holds a current value like "connections open right now".
- →A histogram records many individual measurements and reports their spread — count, sum, min, max, and estimated percentiles.
Labels are the extra key/value pairs you pass alongside the name. Each distinct combination of name and labels is its own series, tracked separately.
This records all three kinds and prints what each one holds.
Percentiles are estimated from bucket boundaries, not from the raw values, so spread.p95 and latency.percentile(0.95) are approximations. The default boundaries are exported as DEFAULT_BUCKET_BOUNDARIES (1 through 10,000); pass your own through histogramBoundaries when your values live on a different scale.
Cardinality: the mistake that takes a backend down
Cardinality means how many distinct series a metric produces. A label holding a user ID, an order ID or a raw URL path produces one new series per value, forever. That is a memory leak in your process and a bill in your monitoring vendor.
The registry caps itself at 10,000 series by default. Past the cap it stops registering new ones and calls onCardinalityLimit with the offending metric name, once per rejected series; the facade's onError hears about each metric name once. Lower the cap and watch that callback.
What you should see. 3, plus repeated MetricsRegistry lines on stderr saying check for a high-cardinality label. The fix is the label, not the cap: use /orders/{id} as the route template.
DANGER
One metric name can only be one type. registry.counter("latency") followed by registry.histogram("latency") throws ObservabilityConfigError, because a backend that received both would reject the whole scrape.
WATCH OUT
counter.increment() throws MetricValueError on a negative, NaN or infinite value, and histogram.record() throws on NaN or infinity. A metric that silently ignored bad input would report a number nobody can reconcile with the code.
TRACING
A trace is the story of one request. A span is one chapter: a named piece of work with a start, an end, and attached facts. Spans nest — the span for "handle request" is the parent of the span for "query database".
Every span carries a context with a traceId (shared by every span in the request) and a spanId (unique to it). Passing a parent's context into startSpan links the two; with no parent, startSpan joins the active propagation context, and withSpan(tracer, name, fn) makes the span itself the active context.
This traces a request with one child step, records an error on the child, and exports both spans.
What you should see. true twice, then two JSON span lines. The child's parentSpanId equals the parent's spanId, its status is "ERROR", and it carries an "exception" event holding exception.type, exception.message and exception.stacktrace.
SpanKind says what the work was: INTERNAL (the default), SERVER, CLIENT, PRODUCER, CONSUMER. SpanStatus is UNSET, OK or ERROR; recordError() sets it to ERROR for you.
DANGER
A span you never end() is never exported and never freed. Put span.end() in a finally block so a thrown error cannot skip it.
IN PLAIN WORDS
Spans are capped so one runaway request cannot eat memory: 128 attributes, 128 events, 128 attributes per event, and attribute strings truncated at 4096 characters. Anything discarded is reported as droppedAttributes and droppedEvents on the exported span. Change the caps with spanLimits.
SAMPLING
Tracing every request in a busy service costs more than the service does. Sampling keeps a fraction of traces and drops the rest. A sampler makes that decision once, when the first span of a trace starts.
Four samplers ship in the box:
- →
createAlwaysOnSampler()— keep everything. The default. - →
createAlwaysOffSampler()— keep nothing. - →
createProbabilitySampler(p)— keep roughlypof traces, decided from the trace ID so every service in the request agrees. - →
createParentBasedSampler(rootOrOptions?)— follow the incoming parent's decision, and use a root sampler only when there is no parent.
This keeps ten percent of new traces but always follows a decision already made upstream.
What you should see. About one run in ten prints true and emits a span line; the rest print false and emit nothing. The span still has a real traceId either way, so child services stay correlated.
WATCH OUT
The probability is a fraction, not a percentage. Pass 0.1 for ten percent. A value outside 0–1 is silently clamped, so 10 quietly means "sample everything"; only NaN or infinity throws ObservabilityConfigError.
CONTEXT PROPAGATION
Passing a request ID down through twelve function calls is miserable. Propagation stores it once, at the top, and every function underneath can read it without being handed it — including across await. Node's AsyncLocalStorage does the work.
The stored value is a PropagationContext: traceId, spanId, and optional parentSpanId, requestId, correlationId, userId, service, traceFlags and baggage.
This runs a handler inside a context and shows the logger picking it up automatically.
What you should see. req_17, then a log line that carries traceId and spanId fields you never wrote — the logger stamps them from the active context. Set correlate: false on a logger to turn that off.
Use runSync for synchronous work, and derive() to make a child context that keeps the trace ID and sampling flags but gets a fresh span ID.
WATCH OUT
current() returns undefined outside a run() scope. That is deliberate — inventing a context would make "no active trace" look like a real one. Use requireCurrentContext() only where starting a brand-new trace is an acceptable answer.
REDACTION
Redaction means replacing a sensitive value with a placeholder before it leaves the process. Telemetry is the classic accidental leak: a request body lands in a log context, the log ships to a vendor, and a password is now in someone else's database.
Redaction is on by default, as it is in @zudojs/logger. With no redaction option, every field name the logger redacts by default (password, passphrase, token, jwt, bearer, authorization, cookie, sid, pwd, API keys, card numbers and more) is redacted, along with this package's own DEFAULT_SENSITIVE_FIELDS. It is applied inside the logger and inside the span, so every processor and exporter downstream sees the already-redacted value.
CHANGED IN 1.2.0
Up to 1.1.x redaction was off unless you passed redaction, so obs.logger.info("login", { password }) exported the password in clear text. You no longer need redaction: {}; it still works and means the same as leaving the option out. To turn redaction off, pass redaction: false.
This uses the defaults and shows what they catch in both a log and a span.
What you should see. The log context prints as { email: "ada@example.com", userPassword: "[REDACTED]", headers: { "x-api-key": "[REDACTED]" } }, and the span prints authorization: "[REDACTED]" while http.route is untouched.
What is covered, and what is not
| Data | Redacted? | Notes |
|---|---|---|
| Log context fields | Yes, by default | Nested objects, arrays and instances of your own classes are walked too; built-ins such as Error, Date, Map and Set are left intact. |
| Span attributes | Yes, by default | Applied on setAttribute, before any processor sees it. |
| Span event attributes | Yes, by default | Covers addEvent. |
| The log message string | No | Only named fields are examined. Never interpolate a secret into the message. |
| The error you pass to a log method | No | Its name, message and stack reach the exporter as written. |
| Error message and stack on a span | No | recordError stores them as strings under non-sensitive keys, so the field rules never fire. Set captureStackTraces: false to drop the stack. |
| Metric names and labels | No | Keep secrets and user IDs out of labels — see cardinality above. |
| Resource attributes | No | You write these once at startup; do not put credentials in them. |
Tuning the rules
Matching is case-insensitive and, by default, word-aware. userPassword, x-api-key and accessToken all match; shippingAddress and authorId do not, even though they contain the letters pin and auth. Pass matchMode: "exact" to match whole names only.
This adds a field, a pattern and a custom rule on top of the defaults. fields, patterns and customRedactor all add to the default rules, so they can only redact more.
Traversal stops at depth 8 by default (raise it with maxDepth) and is cycle-aware. Anything cut off is replaced with MAX_DEPTH_MARKER or CIRCULAR_MARKER, both exported so you can recognise them.
DEFAULT_SENSITIVE_FIELDS is the whole default list: @zudojs/logger's DEFAULT_LOGGER_SECRET_FIELDS plus this package's extra spellings, frozen. You do not need to spread it into fields; fields: ["nationalId"] already redacts nationalId and every default name. To use your list alone, pass replaceDefaults: true:
CHANGED IN 1.2.1 (BEHAVIOUR CHANGE, SECURITY)
Up to 1.2.0, fields replaced the default rules, and DEFAULT_SENSITIVE_FIELDS lacked jwt, sid, pwd, passphrase and bearer, so the old advice to write fields: [...DEFAULT_SENSITIVE_FIELDS, "nationalId"] left jwt in clear text. fields now extends the defaults, and that spread (or spreading DEFAULT_LOGGER_SECRET_FIELDS too) is harmless but no longer needed. If you relied on fields to redact less than the default, add replaceDefaults: true, and only for data you are sure is safe to export.
EXPORTERS & PROCESSORS
An exporter is the thing that actually sends telemetry somewhere. A processor sits in front of it and decides when: BatchSpanProcessor collects spans and ships them in groups, SimpleSpanProcessor ships each one immediately.
Batching exists because one network call per span is unaffordable. The cost is that a crash loses whatever is still queued — which is why shutdown() matters.
This writes spans into your own exporter instead of the console, and proves the span arrived.
The same shape works for logs (LogExporter with export(records)) and metrics (MetricExporter with export(snapshots)). Metrics are pulled on a timer rather than pushed: metricExportIntervalMs defaults to 60,000, and 0 disables the timer while still exporting once on flush and shutdown.
Pass processors yourself when you want full control of batching. Do so and the facade stops building its own — which also means you own the exporter's lifecycle.
Resource attributes and scopes
Resource attributes describe who emitted the telemetry. serviceName, serviceVersion and environment become service.name, service.version and deployment.environment on every span.
WATCH OUT
A scope shares the parent's logger, registry and exporters — only the span resource differs. shutdown() on a scope is a no-op; shut down the root instance instead. flush() on a scope does work.
CONFIGURATION
Every field of ObservabilityConfig. Only serviceName is required.
| Field | What it does | Default |
|---|---|---|
serviceName | Names the service on every log and span. | required |
serviceVersion, environment | Extra resource attributes. | omitted |
logLevel | Threshold for the facade's logger. | LogLevel.INFO |
logExporter, spanExporter, metricExporter | Where each signal is sent. | console, or noop when console exporters are off |
useConsoleExporters | Fall back to console exporters when none is supplied. | true |
sampler | Which traces to record. | AlwaysOnSampler |
processors | Your own span processors. Supplying them disables the built-in batch processor. | one BatchSpanProcessor |
redaction | Redaction rules for log contexts and span attributes (RedactionConfig), or false to turn redaction off. | on, with the default rules |
metrics | MetricsRegistryOptions: maxSeries, histogramBoundaries, onCardinalityLimit. | cap 10,000 |
spanLimits | Per-span caps on attributes, events and string length. | 128 / 128 / 128 / 4096 |
resource | Extra attributes stamped on every span. | {} |
metricExportIntervalMs | How often metrics are exported. 0 disables the timer. | 60000 |
logFlushIntervalMs, logBatchSize | Log buffering behaviour. | 1000 / 256 |
captureStackTraces | Record exception.stacktrace on spans. Stacks are not redacted. | true |
onError | Called with (error, source) for telemetry failures that are otherwise swallowed. | none |
TIP
Set onError in every real deployment. Without it a failing exporter, a full queue or a cardinality blow-up is completely silent.
API REFERENCE
Everything below is exported from @zudojs/observability. Most applications only need createObservability and the four things it hands back.
Functions
| Name | What it does | Notes |
|---|---|---|
createObservability(config) | Builds the facade: logger, metrics, tracer, propagation. | The main entry point. Returns DefaultObservability. |
createNoopObservability() | A facade that records nothing. | For tests and for libraries with no telemetry configured. |
createStructuredLogger(options) | A logger on its own, without the facade. | Takes LoggerOptions. |
createMetricsRegistry(options?) | A metrics registry on its own. | Takes MetricsRegistryOptions. |
createCounter, createGauge, createHistogram | Single, unregistered metric instruments. | (name, labels?); histogram also takes boundaries?. |
createPeriodicMetricReader(options) | Snapshots a registry on a timer and exports it. | The facade builds one for you. |
metricKey(type, name, labels?) | The cache key for one series. | Useful when mirroring the registry's identity rules. |
createTracer(options?) | A tracer on its own. | Takes TracerOptions, including redactAttribute. |
createSpan(name, options?) | A span without a tracer. | No sampling, no processors. |
createSpanContext, createChildSpanContext, isSampledContext | Build and inspect span contexts; IDs are validated and an invalid parent starts a fresh trace (isValidSpanContext). | For wiring trace headers by hand. |
createAlwaysOnSampler, createAlwaysOffSampler, createProbabilitySampler(p), createParentBasedSampler(rootOrOptions?) | The four built-in samplers. | p is a fraction in 0–1. |
isSampled(result), isRecording(result) | Read a SamplingResult. | For custom samplers. |
createPropagationContext, derivePropagationContext, createPropagationManager | Build contexts and the manager that stores them. | The facade exposes a manager as obs.propagation. |
getCurrentContext(), requireCurrentContext() | Read the active context. | The first may return undefined; the second invents a new trace. |
createConsoleLogExporter, createConsoleSpanExporter, createConsoleMetricExporter | Print telemetry as JSON. | Take ConsoleExporterOptions (pretty, console). |
createBatchSpanProcessor, createSimpleSpanProcessor, createBatchLogProcessor | Buffer or forward telemetry to an exporter. | Batch options: batchSize, flushIntervalMs, maxQueueSize, onError, onDrop. |
createRedactor(config?), createStructureRedactor(config?) | Redact one field, or walk a whole structure. | Used internally unless redaction is false. |
redactObject(object, config?), redactValue(value, config?), isSensitiveField(key, config?) | One-shot redaction helpers. | Handy in tests and in your own sinks. |
generateTraceId(), generateSpanId(), isValidTraceId, isValidSpanId | W3C-shaped IDs: 32 and 16 hex characters. | Applied by every context factory: an invalid inbound ID starts a fresh trace. Use parseTraceparent / formatTraceparent for W3C headers. |
logLevelToName, logLevelFromName, parseLogLevel, shouldLog, getLogLevelNames | Convert between levels and names. | parseLogLevel returns undefined on junk — good for env vars. |
createLogRecord, createErrorLogRecord, serializeError | Build records and serialise thrown values. | For custom transports. |
safeStringify(value, pretty?) | JSON.stringify that cannot throw. | Handles cycles, BigInt, functions, symbols, errors. |
isObservabilityError(value) | Type guard for this package's errors. | Use in catch blocks. |
Classes
| Name | What it does | Notes |
|---|---|---|
DefaultObservability | The facade implementation. | Adds resource(), flush(), shutdown(). |
StructuredLogger | The logger implementation. | Adds child(), setLevel(), flush(). |
DefaultMetricsRegistry | In-memory registry with the series cap. | Throws on a name reused as another type. |
DefaultCounter, DefaultGauge, DefaultHistogram | The three instruments. | Reject non-finite values. |
PeriodicMetricReader | Timer that collects and exports snapshots. | start(), collect(), shutdown(). |
DefaultTracer, DefaultSpan | Tracer and span implementations. | Tracer adds forceFlush(), shutdown(), exportSpan(). |
AlwaysOnSampler, AlwaysOffSampler, ProbabilitySampler, ParentBasedSampler | Sampler implementations. | Prefer the create* factories. |
AsyncPropagationManager | Context storage backed by AsyncLocalStorage. | run, runSync, current, derive. |
ConsoleSpanExporter, ConsoleLogExporter, ConsoleMetricExporter | JSON-to-stdout exporters. | Log records at ERROR and above go to console.error. |
BatchSpanProcessor, SimpleSpanProcessor, BatchLogProcessor | Buffering and forwarding. | Batch versions expose getQueueSize() and getDroppedCount(). |
NoopObservability | Facade that discards everything. | Paired with noopLogger, noopTracer and friends. |
Types & enums
| Name | What it does | Notes |
|---|---|---|
LogLevel, LogLevelName | Severity, numeric and by name. | TRACE 0 … OFF 6. |
SpanStatus, SpanKind, TraceFlags | Span outcome, role, and the sampling bit. | TraceFlags.SAMPLED is 1. |
ObservabilityConfig, Observability | What you pass in and what you get back. | See Configuration above. |
Logger, LoggerOptions, LogRecord, LogRecordError, LogTransport | The logging contract. | Implement LogTransport for a custom sink. |
Counter, Gauge, Histogram, HistogramValue, MetricsRegistry, MetricSnapshot | The metrics contract. | HistogramValue carries p50–p99 and cumulative buckets. |
MetricsRegistryOptions, PeriodicMetricReaderOptions | Registry and reader tuning. | metrics in the config takes the former. |
Span, SpanContext, SpanEvent, SpanOptions, SpanLimits, ReadableSpan, Tracer, TracerOptions | The tracing contract. | TracerOptions.redactAttribute redacts every attribute a span records. |
Sampler, SamplingResult, ParentBasedSamplerOptions | The sampling contract. | Decision is one of three strings. |
PropagationContext, PropagationContextOptions, PropagationManager | The propagation contract. | current() may be undefined. |
SpanExporter, LogExporter, MetricExporter, SpanProcessor | What a backend package implements. | Two methods each: export and shutdown. |
ConsoleExporterOptions, ConsoleLike | Console exporter tuning. | console lets tests capture output. |
BatchSpanProcessorOptions, BatchLogProcessorOptions | Batching tuning. | Include onDrop for queue overflow. |
RedactionConfig, RedactionMatchMode | Redaction rules. | "contains" (default) or "exact". |
Errors
| Name | Thrown when | Notes |
|---|---|---|
ObservabilityError | Base class for everything below (defined in @zudojs/errors and re-exported). | Test with isObservabilityError(value). |
ObservabilityConfigError | A name is reused as another metric type, or a sampler probability is out of range. | A programming mistake — fix the call, do not catch it. |
MetricValueError | A metric receives a negative, NaN or infinite value, or invalid histogram boundaries. | Carries the metric name and the offending value. |
ExporterError | An exporter fails. | Surfaces through onError rather than at your call site. |
Constants & singletons
| Name | What it is | Notes |
|---|---|---|
DEFAULT_SENSITIVE_FIELDS | The effective default redaction field list. | The logger's DEFAULT_LOGGER_SECRET_FIELDS plus this package's extra spellings; frozen. fields adds to it unless replaceDefaults: true. |
DEFAULT_BUCKET_BOUNDARIES | Default histogram buckets, 1 to 10,000. | Tuned for millisecond latencies. |
CIRCULAR_MARKER, MAX_DEPTH_MARKER | Placeholders left by the redactor. | "[CIRCULAR]" and "[MAX_DEPTH]". |
INVALID_PROPAGATION_CONTEXT | All-zero context used by the noop manager. | Frozen. |
noopLogger, noopCounter, noopGauge, noopHistogram, noopMetricsRegistry, noopSpan, noopTracer, noopPropagationManager | Do-nothing implementations of each interface. | Useful as defaults in library code. |
noopSpanExporter, noopLogExporter, noopMetricExporter | Exporters that discard everything. | What the facade uses when console exporters are off. |
COMMON MISTAKES
- Exiting without
await obs.shutdown(). Buffered logs, spans and the final metric snapshot are dropped, and the process may hang on the metric timer. Awaitshutdown()in your termination handler. - Assuming every secret is stripped. Redaction covers named fields in log contexts and span attributes. Log messages, error messages and stacks, and metric labels are not covered, so keep secrets out of them. And never ship
redaction: falseoutside a local debugging session. - Putting an ID in a metric label.
{ path: "/orders/9182" }creates one series per order. You hit the 10,000-series cap, new series are refused, and your graphs go flat. Use the route template. - Deploying with the console exporters.
useConsoleExportersdefaults totrue, so production writes JSON to stdout. Pass real exporters or set it tofalse. - Forgetting
span.end()on the error path. The span is never exported and never released. End it in afinally. - Reaching for
replaceDefaults: trueto add a name. Since 1.2.1,redaction: { fields: ["myToken"] }addsmyTokento the defaults.replaceDefaults: truethrows the defaults away, sopasswordstops being redacted. Leave it off unless you mean to redact less. - Leaving
onErrorunset. Dropped batches, failing exporters and cardinality warnings all go nowhere. Wire it to your own logger.
COMPLETE EXPORT INDEX
Every name @zudojs/observability exports from its package root at v1.1.1 — 142 in total, generated from the package’s own entry point rather than written by hand. The sections above explain the ones you reach for most; this is the exhaustive list, so nothing shipped is undocumented. Names not covered above are typically internal helpers and supporting types.
Show all 142 exports
AlwaysOffSampler AlwaysOnSampler AsyncPropagationManager BatchLogProcessor BatchSpanProcessor ConsoleLogExporter ConsoleMetricExporter ConsoleSpanExporter DefaultCounter DefaultGauge DefaultHistogram DefaultMetricsRegistry DefaultObservability DefaultSpan DefaultTracer ExporterError MetricValueError NoopObservability ObservabilityConfigError ObservabilityError ParentBasedSampler PeriodicMetricReader ProbabilitySampler SimpleSpanProcessor StructuredLoggercreateAlwaysOffSampler createAlwaysOnSampler createBatchLogProcessor createBatchSpanProcessor createChildSpanContext createConsoleLogExporter createConsoleMetricExporter createConsoleSpanExporter createCounter createErrorLogRecord createGauge createHistogram createLogRecord createMetricsRegistry createNoopObservability createObservability createParentBasedSampler createPeriodicMetricReader createProbabilitySampler createPropagationContext createPropagationManager createRedactor createSimpleSpanProcessor createSpan createSpanContext createStructuredLogger createStructureRedactor createTracer derivePropagationContext formatTraceparent fromLoggerLevel generateSpanId generateTraceId getCurrentContext getLogLevelNames isObservabilityError isRecording isSampled isSampledContext isSensitiveField isValidSpanContext isValidSpanId isValidTraceId logLevelFromName logLevelToName metricKey parseLogLevel parseTraceparent redactObject redactValue requireCurrentContext safeStringify serializeError shouldLog toLoggerLevel withSpanBatchLogProcessorOptions BatchSpanProcessorOptions ConsoleExporterOptions ConsoleLike Counter Gauge Histogram HistogramValue LogExporter Logger LoggerOptions LogRecord LogRecordError LogTransport MetricExporter MetricSnapshot MetricsRegistry MetricsRegistryOptions Observability ObservabilityConfig ParentBasedSamplerOptions PeriodicMetricReaderOptions PropagationContext PropagationContextOptions PropagationManager ReadableSpan RedactionConfig Sampler SamplingResult Span SpanContext SpanEvent SpanExporter SpanLimits SpanOptions SpanProcessor Tracer TracerOptionsLogLevelName RedactionMatchModeCIRCULAR_MARKER DEFAULT_BUCKET_BOUNDARIES DEFAULT_SENSITIVE_FIELDS INVALID_PROPAGATION_CONTEXT MAX_DEPTH_MARKER noopCounter noopGauge noopHistogram noopLogExporter noopLogger noopMetricExporter noopMetricsRegistry noopPropagationManager noopSpan noopSpanExporter noopTracer TraceFlags TRACEPARENT_HEADERLogLevel SpanKind SpanStatus