Documentation
¶
Index ¶
- Constants
- func AnyValueToString(v *dash0api.AnyValue) string
- func DefaultScopeVersion() string
- func DerefHexBytes(b *[]byte) string
- func DerefInt64(i *int64) string
- func DerefString(s *string) string
- func FindAttribute(attrs []dash0api.KeyValue, key string) string
- func InstallWidthRefresh(ctx context.Context, ch chan<- struct{})
- func MergeAttributes(attrSlices ...[]dash0api.KeyValue) []dash0api.KeyValue
- func NewOtlpCmd() *cobra.Command
- func ParseKeyValuePairs(pairs []string) (map[string]string, error)
- func ParseSpanID(s string) (pcommon.SpanID, error)
- func ParseTraceID(s string) (pcommon.TraceID, error)
- func RenderLogs(ld plog.Logs) string
- func RenderMetrics(md pmetric.Metrics) string
- func RenderTraces(td ptrace.Traces) string
- func ResolveScopeDefaults(cmd *cobra.Command, scopeName *string, scopeVersion *string)
- func SetTailColorEnabled(enabled bool)
- func SeverityNumberToRange(n int32) string
- func Sparkline(series []float64) string
- type Decorator
- type Emitter
- func (e *Emitter) EmitError(kind ErrorKind, reason string, code int)
- func (e *Emitter) EmitForwarded(sig Signal, count, bytes int64)
- func (e *Emitter) EmitShutdown(reason string, finalTotals [signalCount]int64)
- func (e *Emitter) EmitStarted(httpEndpoint, grpcEndpoint, dataset, profileName string)
- func (e *Emitter) EmitStats(snap SnapshotWithRate)
- type ErrorKind
- type Forwarder
- type LifecycleEvent
- type LifecycleKind
- type OtlpLogSeverityRange
- type Pipeline
- type PipelineEndpoints
- type ProxyConsumer
- func (c *ProxyConsumer) Capabilities() consumer.Capabilities
- func (c *ProxyConsumer) ConsumeLogs(_ context.Context, ld plog.Logs) error
- func (c *ProxyConsumer) ConsumeMetrics(_ context.Context, md pmetric.Metrics) error
- func (c *ProxyConsumer) ConsumeTraces(_ context.Context, td ptrace.Traces) error
- func (c *ProxyConsumer) LogsChannel() <-chan plog.Logs
- func (c *ProxyConsumer) MetricsChannel() <-chan pmetric.Metrics
- func (c *ProxyConsumer) TracesChannel() <-chan ptrace.Traces
- type RateSampler
- type Signal
- type Snapshot
- type SnapshotWithRate
- type Stats
- type StderrWriter
- type StdoutWriter
- type WorkerPool
Constants ¶
const DefaultScopeName = "dash0-cli"
DefaultScopeName is the default instrumentation scope name used by the CLI.
Variables ¶
This section is empty.
Functions ¶
func AnyValueToString ¶ added in v1.5.0
AnyValueToString converts an AnyValue to its string representation.
func DefaultScopeVersion ¶
func DefaultScopeVersion() string
DefaultScopeVersion returns the default scope version (the CLI version).
func DerefHexBytes ¶ added in v1.5.0
DerefHexBytes returns the hex encoding of a *[]byte, or "" if nil.
func DerefInt64 ¶ added in v1.5.0
DerefInt64 returns the string representation of a *int64, or "" if nil.
func DerefString ¶ added in v1.5.0
DerefString returns the value of a *string, or "" if nil.
func FindAttribute ¶ added in v1.5.0
FindAttribute looks up key in attrs and returns its string representation. Returns "" if the key is not found or the value is empty.
func InstallWidthRefresh ¶ added in v1.14.0
InstallWidthRefresh subscribes to SIGWINCH on Unix and writes to ch every time the terminal is resized. The writer can use this to redraw the stats line immediately on resize instead of waiting for the next 1- second stats tick.
Cleans up the signal handler when ctx is done. Non-blocking sends on ch: if the writer hasn't drained the previous resize event, the new one is dropped — the next tick's normal width refresh will pick up the latest size anyway.
func MergeAttributes ¶ added in v1.5.0
MergeAttributes merges multiple attribute slices into a single slice. Later slices take precedence over earlier ones for duplicate keys.
func NewOtlpCmd ¶ added in v1.14.0
NewOtlpCmd creates the otlp parent command. The proxy subcommand exposes a local OTLP forwarder that brokers traffic from local OpenTelemetry SDKs to the active Dash0 profile.
func ParseKeyValuePairs ¶
ParseKeyValuePairs parses a slice of "key=value" strings into a map.
func ParseSpanID ¶
ParseSpanID parses a 16 hex character string into a pcommon.SpanID.
func ParseTraceID ¶
ParseTraceID parses a 32 hex character string into a pcommon.TraceID.
func RenderLogs ¶ added in v1.14.0
RenderLogs returns the multi-line debug-exporter-style rendering for a pdata Logs batch. An empty batch (zero ResourceLogs) returns the empty string so the caller can skip writing.
func RenderMetrics ¶ added in v1.14.0
RenderMetrics returns the multi-line debug-exporter-style rendering for a pdata Metrics batch.
func RenderTraces ¶ added in v1.14.0
RenderTraces returns the multi-line debug-exporter-style rendering for a pdata Traces batch.
func ResolveScopeDefaults ¶
ResolveScopeDefaults clears the default value for scope-name or scope-version when only the other flag is explicitly set. This avoids pairing a custom scope name with the dash0-cli version (or vice versa).
func SetTailColorEnabled ¶ added in v1.14.0
func SetTailColorEnabled(enabled bool)
SetTailColorEnabled is called by main() once `dashcolor.NoColor` has been resolved. Pass true to enable semantic coloring of `--tail` output. Safe to call before or after the proxy starts; the renderer reads the variable each time it formats a record.
func SeverityNumberToRange ¶
SeverityNumberToRange maps an OTel severity number (0–24) to its severity range. Numbers outside the defined bands return a formatted string like "SEVERITY_25".
func Sparkline ¶ added in v1.14.0
Sparkline returns a string of len(series) characters from the sparklineGlyphs ramp, normalized against the maximum non-zero value in the series. Zero and negative values map to the lowest glyph; NaN and Inf are treated as zero so a single ill-formed sample doesn't blank the whole rendering.
Empty input returns the empty string so callers can suppress rendering without an additional length check.
Types ¶
type Decorator ¶ added in v1.14.0
type Decorator struct {
// contains filtered or unexported fields
}
Decorator upserts user-provided resource attributes, scope attributes, scope name, and scope version onto every pdata batch flowing through the proxy before it is forwarded upstream. The mirror flags (`--resource-attribute`, `--scope-attribute`, `--scope-name`, `--scope-version`) on the proxy command match the same flags on `dash0 logs send` and `dash0 spans send` so the user experience is consistent across signal-authoring and signal-forwarding workflows.
All upserts are no-ops when the corresponding flag was not provided — the proxy does NOT default scope name/version to `dash0-cli` / CLI version the way the send commands do, because the inbound pdata already carries the SDK's own instrumentation-library identity and silently overwriting it would erase useful diagnostic context.
Decoration happens in the worker pool, after the consumer has returned 200 to the SDK. The pdata is therefore mutated only by the proxy's own goroutines; the receiver-side contract reported by ProxyConsumer.Capabilities is unaffected.
func NewDecorator ¶ added in v1.14.0
func NewDecorator( resourceAttrs, scopeAttrs map[string]string, scopeName, scopeVersion string, logAttrs, spanAttrs, metricAttrs map[string]string, ) *Decorator
NewDecorator returns a Decorator with the supplied user-controlled upserts. Any zero-valued field is a no-op when Decorate* is called.
func (*Decorator) DecorateLogs ¶ added in v1.14.0
DecorateLogs upserts the configured fields onto each ResourceLogs, each ScopeLogs scope, and each LogRecord in ld.
func (*Decorator) DecorateMetrics ¶ added in v1.14.0
DecorateMetrics upserts the configured fields onto each ResourceMetrics, each ScopeMetrics scope, and each metric data point in md. Metric data points come in five flavors — Gauge, Sum, Histogram, ExponentialHistogram, Summary — and the decorator iterates the appropriate slice for each.
func (*Decorator) DecorateTraces ¶ added in v1.14.0
DecorateTraces upserts the configured fields onto each ResourceSpans, each ScopeSpans scope, and each Span in td.
type Emitter ¶ added in v1.14.0
type Emitter struct {
// contains filtered or unexported fields
}
Emitter builds OTLP/JSON event records about the proxy's own lifecycle and sends them on a channel. The actual stdout write is performed by a separate writer goroutine (StdoutWriter) so the hot path (consumer + workers calling EmitForwarded / EmitError) never blocks on I/O.
When the channel is nil (the no-agent-mode case), every Emit method is a silent no-op — the caller constructs one Emitter shape regardless of mode and the events naturally drop when no one is listening.
func NewEmitter ¶ added in v1.14.0
NewEmitter returns an Emitter that pushes events on ch. Pass a nil channel in non-agent mode to turn every Emit call into a no-op.
func (*Emitter) EmitError ¶ added in v1.14.0
EmitError emits an error event with KTD14 classification. code is the HTTP/gRPC status code from upstream when applicable; pass 0 when not.
func (*Emitter) EmitForwarded ¶ added in v1.14.0
EmitForwarded emits one event per inbound batch the consumer enqueued for forwarding.
func (*Emitter) EmitShutdown ¶ added in v1.14.0
EmitShutdown emits the terminating event with final cumulative totals. Callers should invoke this synchronously before cancelling the writer's context so the event lands before the process exits.
func (*Emitter) EmitStarted ¶ added in v1.14.0
EmitStarted emits the proxy-startup event once both listeners are bound and the receiver is ready to accept traffic.
func (*Emitter) EmitStats ¶ added in v1.14.0
func (e *Emitter) EmitStats(snap SnapshotWithRate)
EmitStats emits the per-interval rate + total snapshot for agents to consume. Carries the same data as the TTY stats line, in structured form.
type ErrorKind ¶ added in v1.14.0
type ErrorKind string
ErrorKind classifies a worker outbound failure (KTD14). Agents reading the event stream can use this to differentiate transient upstream errors (the SDK should keep retrying) from terminal ones (the proxy's own credentials are bad and retry won't help).
type Forwarder ¶ added in v1.14.0
type Forwarder interface {
SendLogs(ctx context.Context, ld plog.Logs, dataset *string) error
SendTraces(ctx context.Context, td ptrace.Traces, dataset *string) error
SendMetrics(ctx context.Context, md pmetric.Metrics, dataset *string) error
}
Forwarder abstracts the dash0api.Client OTLP send surface so the worker pool can be exercised with a fake in unit tests without standing up the full API client. dash0api.Client satisfies this implicitly.
type LifecycleEvent ¶ added in v1.14.0
type LifecycleEvent struct {
Kind LifecycleKind
Message string
}
LifecycleEvent is the typed channel input for one-shot stderr messages that should print above the live stats block. The writer renders Message verbatim followed by a newline; Kind is reserved for future color or prefix customization and currently informational only.
type LifecycleKind ¶ added in v1.14.0
type LifecycleKind int
LifecycleKind classifies lifecycle messages. v1 doesn't differentiate visually; the kind is recorded so a future polish pass can color or prefix the rendering without changing the channel signature.
const ( LifecycleInfo LifecycleKind = iota LifecycleWarning LifecycleError LifecycleBanner )
type OtlpLogSeverityRange ¶
type OtlpLogSeverityRange string
OtlpLogSeverityRange represents the OpenTelemetry log severity ranges. Each range covers a band of four severity numbers as defined by the OpenTelemetry specification.
const ( Unknown OtlpLogSeverityRange = "UNKNOWN" Trace OtlpLogSeverityRange = "TRACE" Debug OtlpLogSeverityRange = "DEBUG" Info OtlpLogSeverityRange = "INFO" Warn OtlpLogSeverityRange = "WARN" Error OtlpLogSeverityRange = "ERROR" Fatal OtlpLogSeverityRange = "FATAL" )
type Pipeline ¶ added in v1.14.0
type Pipeline struct {
// contains filtered or unexported fields
}
Pipeline owns the otlpreceiver-based listener stack. Construction pre-binds ports (so the supervisor can decide collision behavior before the receiver internals fire), builds the receiver Config, and creates the three signal-receiver instances (logs/traces/metrics). Start transfers control to the receiver, which actually binds the HTTP and gRPC servers.
func BuildPipeline ¶ added in v1.14.0
func BuildPipeline(ctx context.Context, httpPort, grpcPort int, consumer *ProxyConsumer) (*Pipeline, error)
BuildPipeline pre-binds the requested ports (falling back per PortRequest semantics), assembles the receiver Config, and constructs the three signal receivers wired to the supplied consumer. The returned Pipeline has not started any servers yet; call Start to bind the listeners and accept traffic.
On failure mid-construction the function returns an error; no resources are leaked because pre-bound listeners are closed before construction returns.
func (*Pipeline) Endpoints ¶ added in v1.14.0
func (p *Pipeline) Endpoints() PipelineEndpoints
Endpoints returns the bound HTTP and gRPC host:port pairs. Stable after BuildPipeline returns successfully.
func (*Pipeline) Shutdown ¶ added in v1.14.0
Shutdown stops both listeners. Safe to call multiple times and without a prior Start (per the component.Component contract).
func (*Pipeline) Start ¶ added in v1.14.0
Start brings up both HTTP and gRPC listeners via the receiver. Because the three signal-receivers returned by the otlpreceiver factory share a single underlying instance (sharedcomponent semantics), one Start call is sufficient — but we Start all three for symmetry and to surface any future divergence in the upstream library quickly.
On any partial-start failure, Start best-effort-Shutdowns the others and returns the first error. The caller's supervisor (U5) treats this as a fatal startup error per KTD5.
type PipelineEndpoints ¶ added in v1.14.0
type PipelineEndpoints struct {
HTTPEndpoint string // e.g. "127.0.0.1:4318" or "127.0.0.1:53291"
GRPCEndpoint string // e.g. "127.0.0.1:4317"
}
PipelineEndpoints reports the actual host:port each listener bound to, after pre-bind fallback to OS-assigned ports. The supervisor (U5) uses these to compose the banner and the agent-mode `started` event.
type ProxyConsumer ¶ added in v1.14.0
type ProxyConsumer struct {
// contains filtered or unexported fields
}
ProxyConsumer implements consumer.Logs / consumer.Traces / consumer.Metrics and bridges the otlpreceiver's pdata delivery into the worker pool's per-signal channels.
Per KTD3a (async-forward), the consumer returns nil (mapping to HTTP 200 / gRPC OK) after enqueueing — the actual upstream forward happens asynchronously on the worker goroutines. The OTLP spec scopes acceptance to a single hop, so this is spec-compliant.
Lifecycle side-effects on each Consume call:
- stats forwarded counter incremented (U6) — drives both the TTY sparkline (U7) and the agent-mode stats event (U8).
- agent-mode `dash0.cli.otlp_proxy.forwarded` event emitted (U8).
- --tail rendering pushed to TailCh when --tail is enabled (U7/U9).
- Non-blocking enqueue to the per-signal channel.
- Non-empty channel → return nil (200). Full channel → return retryable error (503 + SDK exponential backoff).
func NewProxyConsumer ¶ added in v1.14.0
func NewProxyConsumer(stats *Stats, emitter *Emitter, tailCh chan<- string) *ProxyConsumer
NewProxyConsumer constructs the consumer plus its three per-signal channels. tailCh may be nil; when non-nil the consumer pushes the debug-exporter-style rendering of each inbound batch to it.
func (*ProxyConsumer) Capabilities ¶ added in v1.14.0
func (c *ProxyConsumer) Capabilities() consumer.Capabilities
Capabilities reports MutatesData=false so the receiver knows it can hand us the pdata directly without making a defensive copy. The consumer never modifies inbound data — workers send it through dash0api.Client as-is.
func (*ProxyConsumer) ConsumeLogs ¶ added in v1.14.0
ConsumeLogs implements consumer.Logs.
func (*ProxyConsumer) ConsumeMetrics ¶ added in v1.14.0
ConsumeMetrics implements consumer.Metrics.
func (*ProxyConsumer) ConsumeTraces ¶ added in v1.14.0
ConsumeTraces implements consumer.Traces.
func (*ProxyConsumer) LogsChannel ¶ added in v1.14.0
func (c *ProxyConsumer) LogsChannel() <-chan plog.Logs
LogsChannel returns the channel the worker pool drains for log batches.
func (*ProxyConsumer) MetricsChannel ¶ added in v1.14.0
func (c *ProxyConsumer) MetricsChannel() <-chan pmetric.Metrics
MetricsChannel returns the channel the worker pool drains for metric batches.
func (*ProxyConsumer) TracesChannel ¶ added in v1.14.0
func (c *ProxyConsumer) TracesChannel() <-chan ptrace.Traces
TracesChannel returns the channel the worker pool drains for trace batches.
type RateSampler ¶ added in v1.14.0
type RateSampler struct {
// contains filtered or unexported fields
}
RateSampler tracks a rolling window of snapshots so consumers can render a sparkline timeline of forwarded rate per signal. The sampler owns the per-interval ticking and fans snapshots out to subscribed sink channels.
func NewRateSampler ¶ added in v1.14.0
func NewRateSampler(stats *Stats, interval time.Duration, capacity int) *RateSampler
NewRateSampler constructs a sampler. capacity is the size of the rolling window the sparkline renderer (U7) reads from — at the proxy's hardcoded 1s tick interval, capacity=30 gives a 30-second history.
func (*RateSampler) History ¶ added in v1.14.0
func (rs *RateSampler) History() []SnapshotWithRate
History returns the current rolling window in chronological order (oldest first). The returned slice is a defensive copy so callers can iterate without holding the sampler's lock.
func (*RateSampler) Run ¶ added in v1.14.0
func (rs *RateSampler) Run(ctx context.Context, sinks ...chan<- SnapshotWithRate)
Run loops on a ticker at the sampler's interval, calls Sample on each tick, and fans the result out to every sink channel. Returns when ctx is done or when ctx is already done at entry. Non-blocking sends to sinks prevent a slow consumer from stalling the stats pipeline — if a sink's channel is full at tick time, that sink misses one sample rather than the whole pipeline backing up.
func (*RateSampler) Sample ¶ added in v1.14.0
func (rs *RateSampler) Sample() SnapshotWithRate
Sample takes a fresh snapshot, computes per-signal rate against the previous sample in the window, appends to the window with ring-buffer semantics (oldest drops at capacity), and returns the result.
type Signal ¶ added in v1.14.0
type Signal int
Signal enumerates the three OTLP signal types the proxy tracks. Profiles is intentionally absent — the OTel Profiles signal is not stable and adding it would lock the proxy to a moving target.
type Snapshot ¶ added in v1.14.0
Snapshot is a moment-in-time view of the counters. Captured atomically per signal but not transactionally across signals — a snapshot taken during a burst may see logs from after a span counter increment but spans from before. For visibility purposes this is fine.
type SnapshotWithRate ¶ added in v1.14.0
type SnapshotWithRate struct {
Snapshot
// Rate[i] is records-per-second for signal i, derived from the delta
// against the previous snapshot. Rate is 0 on the first sample (no prior
// reference) or when the time delta is zero.
Rate [signalCount]float64
}
SnapshotWithRate annotates a Snapshot with per-signal forwarded rate (records per second) computed against the previous sample in the sampler's rolling window.
type Stats ¶ added in v1.14.0
type Stats struct {
// contains filtered or unexported fields
}
Stats holds atomic counters per signal. Methods are concurrency-safe; the hot path (consumer.ConsumeX + worker outcome) calls them with no locking overhead beyond an atomic add.
func (*Stats) Failed ¶ added in v1.14.0
Failed returns the current failed count for a signal (lock-free read).
func (*Stats) Forwarded ¶ added in v1.14.0
Forwarded returns the current forwarded count for a signal (lock-free read).
func (*Stats) RecordFailed ¶ added in v1.14.0
RecordFailed adds n to the per-signal failed counter. Workers (U4) call this after a terminal outbound failure (retries exhausted).
func (*Stats) RecordForwarded ¶ added in v1.14.0
RecordForwarded adds n to the per-signal forwarded counter. The consumer (U13) calls this at enqueue time — it counts "accepted by the proxy", not "delivered to Dash0". Upstream failures are tracked separately via RecordFailed.
type StderrWriter ¶ added in v1.14.0
type StderrWriter struct {
// contains filtered or unexported fields
}
StderrWriter owns os.Stderr in TTY mode and interleaves the live stats block with one-shot lifecycle messages.
The writer maintains its own rolling per-signal rate history independent of the RateSampler — the stats channel only carries the current snapshot, not the full history, so the writer accumulates samples as they arrive. This decouples the writer from the sampler beyond the channel.
func NewStderrWriter ¶ added in v1.14.0
func NewStderrWriter(out io.Writer, fd int) (*StderrWriter, chan SnapshotWithRate, chan LifecycleEvent)
NewStderrWriter returns a writer plus the two channels callers push to. Stats updates feed the live block; lifecycle events render above it.
func (*StderrWriter) Run ¶ added in v1.14.0
func (w *StderrWriter) Run(ctx context.Context, statsCh <-chan SnapshotWithRate, lifecycleCh <-chan LifecycleEvent)
Run drains the stats and lifecycle channels until ctx is done.
In TTY mode the writer renders a multi-line stats block — one line per signal — and redraws it in place on each tick using ANSI cursor controls. Lifecycle messages are inserted above the block by erasing the block first, printing the message, then redrawing.
In non-TTY mode the writer emits lifecycle events as plain lines but skips the live stats display — piping stderr to a file or another process means in-place redraw would litter the output with control sequences rather than produce a useful log.
type StdoutWriter ¶ added in v1.14.0
type StdoutWriter struct {
// contains filtered or unexported fields
}
StdoutWriter drains an event channel and writes one OTLP/JSON line per event to its underlying writer. The single-goroutine ownership of os.Stdout guarantees one valid JSON record per line: concurrent emitters produce no interleaving because everyone funnels through one channel and one writer.
Each event triggers a marshal → write → newline → flush cycle, so a downstream consumer reading the stream line-by-line sees complete records without head-of-line buffering delays.
func NewStdoutWriter ¶ added in v1.14.0
func NewStdoutWriter(out io.Writer) (*StdoutWriter, chan plog.Logs)
NewStdoutWriter returns a writer that drains events to out. The caller also receives the event channel that emitters should push to.
func (*StdoutWriter) Run ¶ added in v1.14.0
Run drains ch into the writer's out until ctx is done or the channel is closed. Returns nil on graceful exit; returns an error only when writing to out fails irrecoverably (which should be rare on os.Stdout — typically only when the receiving pipe has closed).
type WorkerPool ¶ added in v1.14.0
type WorkerPool struct {
// contains filtered or unexported fields
}
WorkerPool drains the per-signal channels populated by ProxyConsumer (U13), calls the upstream Forwarder, classifies outcomes per KTD14, and surfaces failures via the Stats counters, the agent-mode event channel, and an at-most-once-per-throttle-window stderr line for credential issues.
Concurrency is one goroutine per signal — the transport's max-concurrent-requests semaphore (KTD3b) provides the actual outbound concurrency cap, and per-signal goroutines keep batch ordering intact for downstream sanity (e.g., a metrics burst arriving in order goes upstream in order, modulo SDK retries).
func NewWorkerPool ¶ added in v1.14.0
func NewWorkerPool(forwarder Forwarder, dataset *string, stats *Stats, emitter *Emitter, consumer *ProxyConsumer, lifecycleCh chan<- LifecycleEvent, decorator *Decorator) *WorkerPool
NewWorkerPool constructs a pool. No goroutines are started until Run is called. The decorator may be nil — workers treat that the same as an empty decorator and skip the per-batch upsert step.
func (*WorkerPool) Run ¶ added in v1.14.0
func (p *WorkerPool) Run(ctx context.Context)
Run launches one goroutine per signal and blocks until ctx is cancelled. When ctx fires, each worker stops accepting new work from its channel; any in-flight forward finishes (the transport has its own per-request deadline) and the worker returns. Tests that want immediate shutdown should cancel and not wait on queued batches.
Source Files
¶
- attributes.go
- log_severity_range.go
- otlp_cmd.go
- parse.go
- proxy.go
- proxy_consumer.go
- proxy_decorator.go
- proxy_events.go
- proxy_lifecycle.go
- proxy_pipeline.go
- proxy_port_lookup_unix.go
- proxy_sparkline.go
- proxy_stats.go
- proxy_stderr_writer.go
- proxy_stderr_writer_unix.go
- proxy_stdout_writer.go
- proxy_tail.go
- proxy_tail_color.go
- proxy_workers.go