Skip to content

feat(observability): add InMemoryExporter and TLS timeout support#50

Open
wucm667 wants to merge 1 commit intovolcengine:mainfrom
wucm667:feat/observability-in-memory-exporter-and-tls-timeout
Open

feat(observability): add InMemoryExporter and TLS timeout support#50
wucm667 wants to merge 1 commit intovolcengine:mainfrom
wucm667:feat/observability-in-memory-exporter-and-tls-timeout

Conversation

@wucm667
Copy link
Contributor

@wucm667 wucm667 commented Mar 5, 2026

Summary

This PR enhances the observability module with the following improvements:

  1. InMemoryExporter: A new in-memory span exporter for testing and local debugging, with session-based span tracking and JSON dump support.
  2. TLS exporter configurable timeout: Adds a Timeout field to TLSExporterConfig, giving users control over the OTLP HTTP request timeout for both trace and metric TLS exporters.
  3. TLS metric export in NewMetricReader: Automatically registers a TLS periodic metric reader when TLS credentials are configured.
  4. Refactor: Disambiguates the sdk/trace and otel/trace package imports by aliasing the former as sdktrace.

Changed Files

File Change Description
configs/observability.go Modified Added TLSExporterConfig.Timeout field and corresponding env var
observability/exporter.go Modified Added InMemoryExporter, TLS timeout logic, TLS metric reader registration
observability/exporter_test.go Modified Added comprehensive unit tests for InMemoryExporter

Details

1. InMemoryExporter

InMemoryExporter implements the sdktrace.SpanExporter interface and stores spans in memory. It is designed for testing and local debugging scenarios where a real OTLP backend is not available.

Features:

  • Span storage: ExportSpans appends spans to an internal slice and tracks the current TraceID.
  • Session tracking: Scans call_llm spans for the gen_ai.session.id attribute and maintains a session → traceID mapping.
  • Session-scoped retrieval: GetSpansBySession(sessionID) returns all spans belonging to the given session.
  • Full retrieval: GetSpans() returns all collected spans.
  • State reset: Reset() / Shutdown() clear all spans and session mappings.
  • JSON dump: Dump(sessionID, dir) serializes spans to a JSON file. File naming convention:
    • With session: veadk_trace_{sessionID}_{traceID}.json
    • Without session: veadk_trace_{traceID}.json

Usage example:

exp := observability.NewInMemoryExporter()

// Register with TracerProvider
tp := sdktrace.NewTracerProvider(
    sdktrace.WithBatcher(exp),
)

// Retrieve spans after agent run
spans := exp.GetSpansBySession("my-session-id")

// Export spans to JSON
filePath, err := exp.Dump("my-session-id", "./traces")

2. Configurable TLS Exporter Timeout

New config field:

// configs/observability.go
type TLSExporterConfig struct {
    // ... existing fields ...
    Timeout int `yaml:"timeout"` // timeout in seconds, default 10
}

Environment variable:

OBSERVABILITY_OPENTELEMETRY_TLS_TIMEOUT=30

Behavior:

  • When Timeout <= 0, the default of 10s (defaultTLSTimeout) is used.
  • The timeout is applied to both the trace exporter (NewTLSExporter) and the metric exporter (NewTLSMetricExporter) via otlptracehttp.WithTimeout / otlpmetrichttp.WithTimeout.
  • The previous createTraceClient / createMetricClient wrappers are bypassed for TLS exporters to allow direct option composition.

Helper function:

func tlsTimeout(timeoutSec int) time.Duration {
    if timeoutSec <= 0 {
        return defaultTLSTimeout // 10s
    }
    return time.Duration(timeoutSec) * time.Second
}

3. TLS Metric Export in NewMetricReader

NewMetricReader now automatically registers a TLS periodic metric reader when TLS credentials are present:

if cfg.TLS != nil && cfg.TLS.Endpoint != "" && cfg.TLS.AccessKey != "" && cfg.TLS.SecretKey != "" {
    if exp, err := NewTLSMetricExporter(ctx, cfg.TLS); err == nil {
        readers = append(readers, sdkmetric.NewPeriodicReader(exp))
        log.Info("Exporting metrics to TLS", "endpoint", cfg.TLS.Endpoint, "service_name", cfg.TLS.ServiceName)
    }
}

Previously, TLS metric export was not automatically registered even when TLS credentials were configured. This change brings metric export behavior in line with trace export.

4. Import Alias Refactor

The go.opentelemetry.io/otel/sdk/trace package is now imported as sdktrace to disambiguate it from go.opentelemetry.io/otel/trace. The following function signatures are updated accordingly:

  • NewStdoutExporter() (sdktrace.SpanExporter, error)
  • NewCozeLoopExporter(...) (sdktrace.SpanExporter, error)
  • NewAPMPlusExporter(...) (sdktrace.SpanExporter, error)
  • NewTLSExporter(...) (sdktrace.SpanExporter, error)
  • NewFileExporter(...) (sdktrace.SpanExporter, error)
  • NewMultiExporter(...) (sdktrace.SpanExporter, error)
  • multiExporter.ExportSpans(ctx, []sdktrace.ReadOnlySpan)

Tests

Added TestInMemoryExporter test suite covering:

Test case Description
new exporter is empty Newly created exporter has no spans
export and retrieve spans Exported spans are retrievable; TraceID is correctly tracked
session tracking gen_ai.session.id attribute on call_llm spans is mapped to session
reset clears all data Reset() clears spans and session mappings
shutdown clears all data Shutdown() clears all state
force flush is no-op ForceFlush() returns no error
dump to file Session-scoped dump produces correct JSON file with expected content
dump all spans when session is empty Empty sessionID dumps all spans; correct filename format

Configuration Reference

Full TLS exporter configuration example (config.yaml):

observability:
  opentelemetry:
    tls:
      endpoint: "https://tls.volcengineapi.com"
      region: "cn-beijing"
      topic_id: "your-topic-id"
      access_key: "your-ak"
      secret_key: "your-sk"
      timeout: 30  # new: timeout in seconds

Or via environment variables:

OBSERVABILITY_OPENTELEMETRY_TLS_ENDPOINT=https://tls.volcengineapi.com
OBSERVABILITY_OPENTELEMETRY_TLS_REGION=cn-beijing
OBSERVABILITY_OPENTELEMETRY_TLS_TOPIC_ID=your-topic-id
OBSERVABILITY_OPENTELEMETRY_TLS_ACCESS_KEY=your-ak
OBSERVABILITY_OPENTELEMETRY_TLS_SECRET_KEY=your-sk
OBSERVABILITY_OPENTELEMETRY_TLS_TIMEOUT=30

- Add InMemoryExporter for in-memory span collection with session tracking:
  - ExportSpans stores spans with trace ID and session-to-trace mapping
  - GetSpans / GetSpansBySession for retrieval
  - Reset / Shutdown to clear state
  - ForceFlush as no-op
  - Dump method to export spans as JSON file (by session or all)

- Add configurable TLS exporter timeout:
  - New TLSExporterConfig.Timeout field (seconds, default 10s)
  - New env var OBSERVABILITY_OPENTELEMETRY_TLS_TIMEOUT
  - Apply timeout to both trace and metric TLS exporters via otlptracehttp/otlpmetrichttp options

- Add TLS metric export support in NewMetricReader

- Refactor: rename sdk/trace import alias to sdktrace for clarity

- Add comprehensive unit tests for InMemoryExporter
@sjy3
Copy link
Collaborator

sjy3 commented Mar 10, 2026

@shunjiazhu

@sjy3 sjy3 self-requested a review March 10, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants