Firebase Genkit 库使用 OpenTelemetry 进行了插桩 来支持收集跟踪记录、指标和日志。Genkit 用户可以导出 将遥测数据传输到监控和可视化工具 配置 OpenTelemetry Go SDK 导出到支持 OpenTelemetry 的特定系统。
Genkit 包含一个插件,用于将 OpenTelemetry 配置为将数据导出到 Google Cloud Monitoring 和 Cloud Logging。为了支持 其他监控系统,您可以通过编写遥测插件来扩展 Genkit, 如本页所述。
准备工作
如需了解如何编写 Genkit 插件,请参阅编写 Genkit 插件
任何类型的 Genkit 插件,包括遥测插件。需要特别注意的是
每个插件都必须导出一个 Init
函数,用户应调用该函数
然后再使用该插件
导出器和日志记录器
如前所述,遥测插件的主要任务是 OpenTelemetry(Genkit 已经插桩)用于导出数据 特定服务为此,您需要具备以下条件:
- OpenTelemetry 的
SpanExporter
的实现 将数据导出到您选择的服务的界面。 - OpenTelemetry 的
metric.Exporter
的实现 将数据导出到您选择的服务的界面。 slog.Logger
或者slog.Handler
的实现 界面,用于将日志导出到您选择的服务。
根据要导出到的服务,这可能是 投入相对较小的工作量或很大的工作量。
由于 OpenTelemetry 是一种行业标准,因此许多监控服务
具有实现这些接口的库。例如,googlecloud
Genkit 插件会利用
opentelemetry-operations-go
由 Google Cloud 团队维护。
同样,许多监控服务都提供了实现
标准的 slog
接口。
另一方面,如果没有此类库可用于您的服务, 实现必要的接口可能是一个庞大的项目。
检查 OpenTelemetry 注册表 或监控服务的文档,看看集成是否已经可用。
如果您需要自行构建这些集成,请查看
官方 OpenTelemetry 导出器
以及编写 slog
处理程序的指南页面。
构建插件
依赖项
每个遥测插件都需要导入 Genkit 核心库和 OpenTelemetry 库:
import {
// Import the Genkit core library.
"github.com/firebase/genkit/go/core"
// Import the OpenTelemetry libraries.
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/trace"
}
如果您围绕现有的 OpenTelemetry 或 slog
构建插件
您还需要导入这些文件
Config
遥测插件应至少支持以下配置 选项:
type Config struct {
// Export even in the dev environment.
ForceExport bool
// The interval for exporting metric data.
// The default is 60 seconds.
MetricInterval time.Duration
// The minimum level at which logs will be written.
// Defaults to [slog.LevelInfo].
LogLevel slog.Leveler
}
以下示例假定您提供了这些选项,并将 提供一些处理方法的指导。
大多数插件还会包含其所在的服务的配置设置 导出到(API 密钥、项目名称等)。
Init()
遥测插件的 Init()
函数应执行以下所有操作:
如果 Genkit 在开发环境中运行(例如 使用
genkit start
运行),Config.ForceExport
选项则不可以 设置:shouldExport := cfg.ForceExport || os.Getenv("GENKIT_ENV") != "dev" if !shouldExport { return nil }
初始化轨迹 span 导出器,并向 Genkit 注册:
spanProcessor := trace.NewBatchSpanProcessor(YourCustomSpanExporter{}) core.RegisterSpanProcessor(spanProcessor)
初始化指标导出器,并将其注册到 OpenTelemetry 库:
r := metric.NewPeriodicReader( YourCustomMetricExporter{}, metric.WithInterval(cfg.MetricInterval), ) mp := metric.NewMeterProvider(metric.WithReader(r)) otel.SetMeterProvider(mp)
在以下情况下,使用用户配置的收集间隔 (
Config.MetricInterval
) 初始化PeriodicReader
。将
slog
处理程序注册为默认日志记录器:logger := slog.New(YourCustomHandler{ Options: &slog.HandlerOptions{Level: cfg.LogLevel}, }) slog.SetDefault(logger)
您应该将处理程序配置为遵循用户指定的最小日志 级别 (
Config.LogLevel
)。
个人身份信息隐去
大多数生成式 AI 流程都是从某种类型的用户输入开始, 某些用户流跟踪记录包含个人身份信息 个人身份信息 (PII) 的。为了保护您用户的则应隐去个人身份信息 然后再导出跟踪记录。
如果您要构建自己的 span 导出器, 进入其中。
如果您围绕现有 OpenTelemetry 集成构建插件,
可以使用执行此任务的自定义导出器来封装提供的 span 导出器
任务。例如,googlecloud
插件会移除 genkit:input
和
在使用封装容器导出每个 span 中的 genkit:output
属性之前
类似于以下内容:
type redactingSpanExporter struct {
trace.SpanExporter
}
func (e *redactingSpanExporter) ExportSpans(ctx context.Context, spanData []trace.ReadOnlySpan) error {
var redacted []trace.ReadOnlySpan
for _, s := range spanData {
redacted = append(redacted, redactedSpan{s})
}
return e.SpanExporter.ExportSpans(ctx, redacted)
}
func (e *redactingSpanExporter) Shutdown(ctx context.Context) error {
return e.SpanExporter.Shutdown(ctx)
}
type redactedSpan struct {
trace.ReadOnlySpan
}
func (s redactedSpan) Attributes() []attribute.KeyValue {
// Omit input and output, which may contain PII.
var ts []attribute.KeyValue
for _, a := range s.ReadOnlySpan.Attributes() {
if a.Key == "genkit:input" || a.Key == "genkit:output" {
continue
}
ts = append(ts, a)
}
return ts
}
问题排查
如果您无法让数据显示在预期位置,OpenTelemetry 一款实用的诊断工具 以便找出问题根源