Menulis plugin telemetri Genkit

Library Firebase Genkit dilengkapi dengan OpenTelemetry untuk mendukung pengumpulan trace, metrik, dan log. Pengguna Genkit dapat mengekspor data telemetri ini ke alat pemantauan dan visualisasi dengan menginstal plugin yang mengonfigurasi OpenTelemetry Go SDK agar dapat mengekspor ke sistem yang mendukung OpenTelemetry tertentu.

Genkit menyertakan plugin yang mengonfigurasi OpenTelemetry agar dapat mengekspor data ke Google Cloud Monitoring dan Cloud Logging. Untuk mendukung sistem pemantauan lain, Anda dapat memperluas Genkit dengan menulis plugin telemetri, seperti yang dijelaskan di halaman ini.

Sebelum memulai

Baca Menulis plugin Genkit untuk mengetahui informasi tentang penulisan segala jenis plugin Genkit, termasuk plugin telemetri. Secara khusus, perhatikan bahwa setiap plugin harus mengekspor fungsi Init, yang diharapkan akan dipanggil oleh pengguna sebelum menggunakan plugin.

Pengekspor dan Pencatat

Seperti yang disebutkan sebelumnya, tugas utama plugin telemetri adalah mengonfigurasi OpenTelemetry (yang telah dilengkapi dengan Genkit) untuk mengekspor data ke layanan tertentu. Untuk melakukannya, Anda memerlukan hal berikut:

  • Implementasi antarmuka SpanExporter OpenTelemetry yang mengekspor data ke layanan pilihan Anda.
  • Implementasi antarmuka metric.Exporter OpenTelemetry yang mengekspor data ke layanan pilihan Anda.
  • slog.Logger atau implementasi antarmuka slog.Handler , yang mengekspor log ke layanan pilihan Anda.

Tergantung pada layanan yang ingin Anda ekspor, hal ini bisa dianggap upaya yang relatif kecil atau besar.

Karena OpenTelemetry merupakan standar industri, banyak layanan pemantauan yang sudah memiliki library yang mengimplementasikan antarmuka ini. Misalnya, plugin googlecloud untuk Genkit memanfaatkan library opentelemetry-operations-go, yang dikelola oleh tim Google Cloud. Demikian pula, banyak layanan pemantauan menyediakan library yang mengimplementasikan antarmuka slog standar.

Di sisi lain, jika tidak ada library seperti itu yang tersedia untuk layanan Anda, penerapan antarmuka yang diperlukan bisa menjadi project yang besar.

Periksa registry OpenTelemetry atau dokumen layanan pemantauan untuk melihat apakah integrasi sudah tersedia.

Jika Anda perlu membangun integrasi ini sendiri, lihat sumber pengekspor resmi OpenTelemetry dan halaman Panduan untuk Menulis Handler slog.

Membuat plugin

Dependensi

Setiap plugin telemetri perlu mengimpor library inti Genkit dan beberapa library 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"
}

Jika Anda membangun plugin berdasarkan OpenTelemetry atau integrasi slog yang sudah ada, Anda juga perlu mengimpornya.

Config

Setidaknya, plugin telemetri harus mendukung opsi konfigurasi berikut:

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
}

Contoh berikut mengasumsikan bahwa Anda membuat opsi ini tersedia dan akan memberikan beberapa panduan tentang cara menanganinya.

Sebagian besar plugin juga akan menyertakan setelan konfigurasi untuk layanan yang diekspornya (kunci API, nama project, dan seterusnya).

Init()

Fungsi Init() plugin telemetri harus melakukan semua hal berikut:

  • Kembali lebih awal jika Genkit berjalan di lingkungan pengembangan (seperti saat berjalan dengan genkit start) dan opsi Config.ForceExport belum ditetapkan:

    shouldExport := cfg.ForceExport || os.Getenv("GENKIT_ENV") != "dev"
    if !shouldExport {
    	return nil
    }
    
  • Inisialisasi pengekspor span trace Anda dan daftarkan ke Genkit:

    spanProcessor := trace.NewBatchSpanProcessor(YourCustomSpanExporter{})
    core.RegisterSpanProcessor(spanProcessor)
    
  • Inisialisasi pengekspor metrik dan daftarkan ke library OpenTelemetry:

    r := metric.NewPeriodicReader(
    	YourCustomMetricExporter{},
    	metric.WithInterval(cfg.MetricInterval),
    )
    mp := metric.NewMeterProvider(metric.WithReader(r))
    otel.SetMeterProvider(mp)
    

    Gunakan interval pengumpulan yang dikonfigurasi pengguna (Config.MetricInterval) saat menginisialisasi PeriodicReader.

  • Daftarkan handler slog Anda sebagai pencatat default:

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

    Anda harus mengonfigurasi handler agar mengikuti level log minimum yang ditentukan pengguna (Config.LogLevel).

Penyamaran PII

Karena sebagian besar flow AI generatif dimulai dengan input pengguna, maka kemungkinan bahwa beberapa trace flow berisi informasi identitas pribadi (PII). Untuk melindungi informasi pengguna, Anda harus menyamarkan PII dari trace sebelum mengekspornya.

Jika membangun pengekspor span sendiri, Anda dapat membangun fungsi ini ke dalamnya.

Jika Anda membangun plugin berdasarkan integrasi OpenTelemetry yang ada, Anda dapat menggabungkan pengekspor span yang disediakan dengan pengekspor kustom yang melakukan tugas ini. Misalnya, plugin googlecloud menghapus atribut genkit:input dan genkit:output dari setiap span sebelum mengekspornya menggunakan wrapper yang serupa dengan contoh berikut ini:

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
}

Pemecahan masalah

Jika Anda mengalami kesulitan untuk memunculkan data di tempat yang Anda harapkan, OpenTelemetry menyediakan alat diagnostik yang membantu menemukan sumber masalahnya.