Genkit 원격 분석 플러그인 작성

Firebase Genkit 라이브러리는 trace, 측정항목, 로그 수집을 지원하기 위해 OpenTelemetry를 통해 계측됩니다. Genkit 사용자는 특정 OpenTelemetry 지원 시스템으로 내보내도록 OpenTelemetry Go SDK를 구성하는 플러그인을 설치하여 이 원격 분석 데이터를 모니터링 및 시각화 도구로 내보낼 수 있습니다.

Genkit에는 Google Cloud Monitoring 및 Cloud Logging으로 데이터를 내보내도록 OpenTelemetry를 구성하는 플러그인이 포함되어 있습니다. 다른 모니터링 시스템을 지원하려면 이 페이지에 설명된 대로 원격 분석 플러그인을 작성하여 Genkit를 확장할 수 있습니다.

시작하기 전에

원격 분석 플러그인을 포함한 모든 종류의 Genkit 플러그인 작성에 관한 자세한 내용은 Genkit 플러그인 작성을 참조하세요. 특히 모든 플러그인은 사용자가 플러그인을 사용하기 전에 호출해야 하는 Init 함수를 내보내야 합니다.

내보내기 도구 및 로거

앞서 언급했듯이 원격 분석 플러그인의 기본 작업은 특정 서비스로 데이터를 내보내도록 OpenTelemetry(Genkit가 이미 계측됨)를 구성하는 것입니다. 이렇게 하려면 다음이 필요합니다.

  • 원하는 서비스로 데이터를 내보내는 OpenTelemetry의 SpanExporter 인터페이스 구현
  • 원하는 서비스로 데이터를 내보내는 OpenTelemetry의 metric.Exporter 인터페이스 구현
  • 원하는 서비스로 로그를 내보내는 slog.Logger 또는 slog.Handler 인터페이스 구현

내보내려는 서비스에 따라 비교적 낮은 수준의 작업 또는 높은 수준의 작업이 필요합니다.

OpenTelemetry는 업계 표준이기 때문에 이미 많은 모니터링 서비스에 이러한 인터페이스를 구현하는 라이브러리가 있습니다. 예를 들면 Genkit용 googlecloud 플러그인은 Google Cloud팀에서 관리하는 opentelemetry-operations-go 라이브러리를 사용합니다. 마찬가지로 많은 모니터링 서비스는 표준 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
    }
    
  • trace 스팬 내보내기 도구를 초기화하고 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)
    

    PeriodicReader를 초기화할 때 사용자가 구성한 수집 간격(Config.MetricInterval)을 사용합니다.

  • slog 핸들러를 기본 로거로 등록합니다.

    logger := slog.New(YourCustomHandler{
    	Options: &slog.HandlerOptions{Level: cfg.LogLevel},
    })
    slog.SetDefault(logger)
    

    사용자가 지정한 최소 로그 수준(Config.LogLevel)을 준수하도록 핸들러를 구성해야 합니다.

PII 수정

대부분의 생성형 AI 흐름은 일종의 사용자 입력으로 시작되므로 일부 흐름 trace에는 개인 식별 정보가 포함될 가능성이 높습니다. 사용자의 정보를 보호하려면 trace를 내보내기 전에 trace에서 개인 식별 정보를 수정해야 합니다.

자체 스팬 내보내기 도구를 빌드하는 경우 이 기능을 여기에 빌드할 수 있습니다.

기존 OpenTelemetry 통합을 중심으로 플러그인을 빌드하는 경우 제공된 스팬 내보내기 도구를 이 작업을 수행하는 커스텀 내보내기 도구로 래핑할 수 있습니다. 예를 들어 googlecloud 플러그인은 다음과 비슷한 래퍼를 사용하여 내보내기 전에 모든 스팬에서 genkit:inputgenkit: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 문제의 원인을 찾는 데 도움이 되는 유용한 진단 도구를 제공합니다.