events

package
v0.5.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package events 实现结构化事件协议(自 hexclaw 下沉,v0.5.0 去 feature-flag)。

目标:把散落各处的 logger.Info/Warn 升级成可观测、可远程上报的结构化事件。 不替换现有 logger 调用 —— 而是并存:调用方在关键路径主动 Emit(ctx, evt), 同时保留 logger 用于人类可读日志。

协议:每个 Event 有 Type / Severity / Source / Timestamp / Data;编码为 JSON, 通过 Sink 投递(本地 JSONL 文件 / 远程 HTTP collector / 测试用 InMemory / NoopSink)。

投递语义:包级 Emit 透传到注入 ctx 的 Emitter(WithEmitter 注入);ctx 中无 Emitter 时退化为 no-op。是否真正落盘 / 上报由 Emitter 持有的 Sink 决定 —— 默认建议 NoopSink(静默),需要观测时切 FileSink / HTTPSink / MultiSink。

注:下沉前本包受 hexclaw feature flag `events.transport.v1`(alpha 默认 OFF) 门控;下沉到框架层后去除该 flag(框架层不依赖 hexclaw/featureflag),改由 Sink 选择控制是否静默 —— 默认 NoopSink 等价于原 flag OFF 的"默认静默"语义。

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Emit

func Emit(ctx context.Context, e Event) error

Emit 是包级便捷函数:从 ctx 取出 Emitter(WithEmitter 注入)并投递。

ctx 中无 emitter 时直接返回 nil(no-op)。是否真正落盘 / 上报由 Emitter 持有的 Sink 决定 —— 默认 NoopSink 即静默(等价于下沉前 feature flag OFF 的行为)。

func WithEmitter

func WithEmitter(ctx context.Context, e *Emitter) context.Context

WithEmitter 在 ctx 中注入 Emitter,供调用栈底部的 Emit() 抓取。

Types

type Emitter

type Emitter struct {
	// contains filtered or unexported fields
}

Emitter 是事件发射器,持有 Sink + 默认 Source 标签。

func NewEmitter

func NewEmitter(sink Sink, defaultSource string) *Emitter

NewEmitter 构造一个 Emitter。sink 为 nil 时退化为 NoopSink。

func (*Emitter) Close

func (em *Emitter) Close() error

Close 关闭底层 sink。

func (*Emitter) Emit

func (em *Emitter) Emit(ctx context.Context, e Event) error

Emit 投递一条事件:

  • 校验 Type 非空(缺 Type 直接返回 error,不进 Sink)
  • 自动补 Source(如果调用方没设)
  • Sink 失败仅记 fallback log,不上抛——投递必须 best-effort

如果 emitter 是 nil,这是 no-op。

func (*Emitter) Sink

func (em *Emitter) Sink() Sink

Sink 返回 emitter 持有的底层 sink(用于关闭 / 单测断言)。

type Event

type Event struct {
	Type      string         `json:"type"`      // 事件类型,如 "tool.call.completed"、"llm.failover"
	Severity  Severity       `json:"severity"`  // 严重级别
	Source    string         `json:"source"`    // 事件来源模块,如 "engine.tool_executor"
	Timestamp time.Time      `json:"timestamp"` // 发出时刻(UTC)
	TraceID   string         `json:"trace_id,omitempty"`
	SessionID string         `json:"session_id,omitempty"`
	Data      map[string]any `json:"data,omitempty"`
}

Event 是单条结构化事件。所有字段都有 JSON tag,可被 Sink 直接 marshal。

Data 是任意 key → value(值可序列化为 JSON);用 map 而非 typed struct 是为了 兼容现有点位(trace_id、tool_name、duration_ms 等异质字段不必引入新类型)。

func New

func New(eventType string, severity Severity) Event

New 构造一个 Event 并填充 Timestamp。

func (Event) With

func (e Event) With(key string, value any) Event

With 为 Event.Data 设置一个键值对,并返回 Event 自身(方便链式构造)。

evt := events.New("tool.call.completed", events.SeverityInfo).
    With("tool", "shell").
    With("duration_ms", 142)

func (Event) WithSource

func (e Event) WithSource(src string) Event

WithSource 链式设置 Source。

func (Event) WithTrace

func (e Event) WithTrace(traceID, sessionID string) Event

WithTrace 链式设置 TraceID / SessionID。

type FileSink

type FileSink struct {
	// contains filtered or unexported fields
}

FileSink 把事件以 JSON Lines 写入文件。每次 Submit 一行。

func NewFileSink

func NewFileSink(path string) (*FileSink, error)

NewFileSink 打开(或创建)path 对应的文件以 append 模式。失败返回 error。

func (*FileSink) Close

func (s *FileSink) Close() error

Close 关闭文件。多次调用是安全的。

func (*FileSink) Submit

func (s *FileSink) Submit(_ context.Context, e Event) error

Submit 写一行 JSONL。

type HTTPSink

type HTTPSink struct {
	// contains filtered or unexported fields
}

HTTPSink POST 单条事件 JSON 到远端 collector。

设计取舍:

  • 同步 POST:实现简单;不阻塞由调用方决定是否在 goroutine 里调 Emit
  • 不带本地 buffer / retry:远端不可达时 Submit 返回 error,Emitter 会记录 fallback 不会丢失现有 logger 输出。要做高可靠投递的留给 v0.4.1+ 的 BatchSink

func NewHTTPSink

func NewHTTPSink(url string, timeout time.Duration) *HTTPSink

NewHTTPSink 构造一个 HTTPSink。timeout <= 0 时取 5s。

func (*HTTPSink) Close

func (s *HTTPSink) Close() error

Close noop(HTTPSink 无持久状态)。

func (*HTTPSink) Submit

func (s *HTTPSink) Submit(ctx context.Context, e Event) error

Submit POST 一条事件。

type MemorySink

type MemorySink struct {
	// contains filtered or unexported fields
}

MemorySink 把事件累计到内存里,用于测试 / 本地调试。线程安全。

func NewMemorySink

func NewMemorySink() *MemorySink

NewMemorySink 创建一个空的 MemorySink。

func (*MemorySink) Close

func (m *MemorySink) Close() error

Close noop。

func (*MemorySink) Events

func (m *MemorySink) Events() []Event

Events 返回截至当前的事件副本。

func (*MemorySink) Reset

func (m *MemorySink) Reset()

Reset 清空事件。

func (*MemorySink) Submit

func (m *MemorySink) Submit(_ context.Context, e Event) error

Submit 追加事件。

type MultiSink

type MultiSink struct {
	// contains filtered or unexported fields
}

MultiSink 把事件 fan-out 到多个底层 Sink。任一 Sink Submit 失败不影响其它。 Close 会顺序调用底层每个 Sink.Close。

func NewMultiSink

func NewMultiSink(sinks ...Sink) *MultiSink

NewMultiSink 把多个 sink 组合成一个。nil sink 会被跳过。

func (*MultiSink) Close

func (m *MultiSink) Close() error

Close 关闭所有底层 sink。

func (*MultiSink) Submit

func (m *MultiSink) Submit(ctx context.Context, e Event) error

Submit 把事件分发到所有 sink;汇总错误(用最后一个非 nil error 上抛)。

type NoopSink

type NoopSink struct{}

NoopSink 丢弃所有事件。用于默认静默 / 测试桩。

func NewNoopSink

func NewNoopSink() *NoopSink

NewNoopSink 创建一个 NoopSink。

func (*NoopSink) Close

func (n *NoopSink) Close() error

func (*NoopSink) Submit

func (n *NoopSink) Submit(_ context.Context, _ Event) error

type Severity

type Severity string

Severity 事件严重级别。与 slog.Level 语义对齐,便于日志系统二次接入。

const (
	SeverityDebug Severity = "debug"
	SeverityInfo  Severity = "info"
	SeverityWarn  Severity = "warn"
	SeverityError Severity = "error"
)

type Sink

type Sink interface {
	// Submit 提交一个事件。返回非 nil error 时 Emitter 会记 fallback 日志,
	// 但不会向调用方传播(事件投递必须 best-effort)。
	Submit(ctx context.Context, e Event) error
	// Close 优雅关闭:刷盘 / 清空队列。可重复调用,幂等。
	Close() error
}

Sink 是事件投递器。Submit 不应阻塞调用方过久 —— 慢 Sink 应内部异步化。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL