การเขียนปลั๊กอินทางไกลของ Genkit

ไลบรารี Firebase Genkit มีเครื่องมือ OpenTelemetry เพื่อรองรับการรวบรวมการติดตาม เมตริก และบันทึก ผู้ใช้ Genkit ส่งออกข้อมูลนี้ได้ การส่งข้อมูลทางไกลไปยังเครื่องมือการตรวจสอบและการแสดงข้อมูลผ่านภาพโดยการติดตั้งปลั๊กอินที่ กำหนดค่า OpenTelemetry Go SDK เพื่อส่งออกไปยังระบบที่รองรับ OpenTelemetry โดยเฉพาะ

Genkit มีปลั๊กอินที่กำหนดค่า OpenTelemetry เพื่อส่งออกข้อมูลไปยัง Google Cloud Monitoring และ Cloud Logging เพื่อให้การสนับสนุน ระบบตรวจสอบอื่นๆ คุณสามารถขยาย Genkit โดยการเขียนปลั๊กอินการวัดและส่งข้อมูลทางไกล ตามที่อธิบายไว้ในหน้านี้

ก่อนเริ่มต้น

อ่านการเขียนปลั๊กอิน Genkit เพื่อดูข้อมูลเกี่ยวกับการเขียน ปลั๊กอิน Genkit ทุกประเภท รวมถึงปลั๊กอินทางไกล โดยเฉพาะอย่างยิ่ง โปรดทราบว่า ปลั๊กอินทุกตัวจะต้องส่งออกฟังก์ชัน Init ซึ่งคาดว่าผู้ใช้จะเรียกใช้ ก่อนใช้ปลั๊กอิน

ผู้ส่งออกและบันทึก

ตามที่ระบุไว้ก่อนหน้านี้ งานหลักของปลั๊กอินการวัดและส่งข้อมูลทางไกลคือการกำหนดค่า OpenTelemetry (ซึ่งใช้ Genkit อยู่แล้ว) เพื่อส่งออกข้อมูล ไปยังบริการใดบริการหนึ่ง ในการดำเนินการนี้ คุณจะต้องมีสิ่งต่อไปนี้

  • การใช้งาน SpanExporter ของ OpenTelemetry ที่ส่งออกข้อมูลไปยังบริการที่คุณต้องการ
  • การใช้งาน metric.Exporter ของ OpenTelemetry ที่ส่งออกข้อมูลไปยังบริการที่คุณต้องการ
  • ใช้ slog.Logger ก็ได้ หรือการใช้ slog.Handler ซึ่งส่งออกบันทึกไปยังบริการที่คุณต้องการ

ซึ่งขึ้นอยู่กับบริการที่คุณต้องการใช้เพื่อส่งออก ใช้ความพยายามเพียงเล็กน้อยหรือใช้ความพยายามมาก

เนื่องจาก OpenTelemetry เป็นมาตรฐานอุตสาหกรรม บริการตรวจสอบจำนวนมาก มีไลบรารีที่ใช้อินเทอร์เฟซเหล่านี้ ตัวอย่างเช่น googlecloud แต่ปลั๊กอินสำหรับ Genkit ก็ใช้ประโยชน์จาก opentelemetry-operations-go ที่ดูแลโดยทีม Google Cloud ในทำนองเดียวกัน บริการตรวจสอบจำนวนมากมีไลบรารีที่ใช้ อินเทอร์เฟซ slog มาตรฐาน

ในทางกลับกัน หากไม่มีไลบรารีดังกล่าวสำหรับบริการของคุณ การนำอินเทอร์เฟซที่จำเป็นมาใช้นับเป็นโครงการที่สำคัญ

ตรวจสอบรีจิสทรี OpenTelemetry หรือเอกสารของบริการตรวจสอบเพื่อดูว่าการผสานรวมพร้อมใช้งานแล้วหรือไม่

หากคุณต้องสร้างการผสานรวมเหล่านี้ด้วยตนเอง ให้ลองดูแหล่งที่มาของ ผู้ส่งออกอย่างเป็นทางการของ OpenTelemetry และหน้าคู่มือการเขียน slog Handler

การสร้างปลั๊กอิน

การอ้างอิง

ปลั๊กอินการวัดและส่งข้อมูลทางไกลทุกรายการจะต้องนำเข้าไลบรารีหลักของ 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
    }
    
  • เริ่มต้นผู้ส่งออกช่วงการติดตามและลงทะเบียนกับ 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)

การปกปิด PII

เนื่องจากการทำงานของ Generative AI ส่วนใหญ่เริ่มจากข้อมูลจากผู้ใช้บางอย่าง ความเป็นไปได้ที่การติดตามโฟลว์บางรายการจะมีข้อมูลระบุตัวตนที่ระบุตัวบุคคลได้ (PII) เพื่อปกป้องผู้ใช้ของคุณ ข้อมูล คุณควรปกปิด PII จากการติดตามก่อนส่งออก

หากคุณกำลังสร้างผู้ส่งออก Span ของคุณเอง คุณสามารถสร้างฟังก์ชันนี้ได้ ลงไปแล้ว

ถ้าคุณสร้างปลั๊กอินโดยใช้การผสานรวม OpenTelemetry ที่มีอยู่ สามารถรวมผู้ส่งออก span ที่ให้มากับผู้ส่งออกที่กำหนดเองซึ่งจะดำเนินการนี้ งาน ตัวอย่างเช่น ปลั๊กอิน googlecloud จะนำ genkit:input และ แอตทริบิวต์ genkit:output จากทุกช่วงก่อนที่จะส่งออกโดยใช้ Wrapper ที่คล้ายกับข้อความต่อไปนี้

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 ให้เครื่องมือวินิจฉัยที่มีประโยชน์ ซึ่งช่วยค้นหาที่มาของปัญหา