Сервіс каталогу продуктів

Цей сервіс відповідає за повернення інформації про продукти. Сервіс може бути використаний для отримання всіх продуктів, пошуку конкретних продуктів або повернення деталей про будь-який окремий продукт.

Сирці сервісу каталогу продуктів

Трейси

Ініціалізація Трейсингу

OpenTelemetry SDK ініціалізується з main за допомогою функції initTracerProvider.

func initTracerProvider() *sdktrace.TracerProvider {
    ctx := context.Background()

    exporter, err := otlptracegrpc.New(ctx)
    if err != nil {
        log.Fatalf("OTLP Trace gRPC Creation: %v", err)
    }
    tp := sdktrace.NewTracerProvider(
        sdktrace.WithBatcher(exporter),
        sdktrace.WithResource(initResource()),
    )
    otel.SetTracerProvider(tp)
    otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
    return tp
}

Ви повинні викликати TracerProvider.Shutdown() при завершенні роботи вашого сервісу, щоб забезпечити експорт всіх відрізків. Цей сервіс викликає цю функцію як частину відкладеної функції в main.

tp := InitTracerProvider()
defer func() {
    if err := tp.Shutdown(context.Background()); err != nil {
        log.Fatalf("Tracer Provider Shutdown: %v", err)
    }
}()

Додавання gRPC автоінструментування

Цей сервіс отримує gRPC запити, які інструментуються в функції main як частина створення gRPC сервера.

srv := grpc.NewServer(
    grpc.StatsHandler(otelgrpc.NewServerHandler()),
)

Цей сервіс буде здійснювати вихідні gRPC виклики, які всі інструментуються обгортанням gRPC клієнта інструментуванням.

func createClient(ctx context.Context, svcAddr string) (*grpc.ClientConn, error) {
    return grpc.DialContext(ctx, svcAddr,
        grpc.WithTransportCredentials(insecure.NewCredentials()),
        grpc.WithStatsHandler(otelgrpc.NewClientHandler()),
    )
}

Додавання атрибутів до автоінструментованих відрізків

В межах виконання автоінструментованого коду ви можете отримати поточний відрізок з контексту.

span := trace.SpanFromContext(ctx)

Додавання атрибутів до відрізка здійснюється за допомогою SetAttributes на обʼєкті відрізка. У функції GetProduct атрибут для ID продукту додається до відрізка.

span.SetAttributes(
    attribute.String("app.product.id", req.Id),
)

Встановлення статусу відрізка

Цей сервіс може захоплювати та обробляти помилки на основі прапорця функції. У випадку помилки статус відрізка встановлюється відповідно за допомогою SetStatus на обʼєкті відрізка. Ви можете побачити це у функції GetProduct.

msg := fmt.Sprintf("Error: ProductCatalogService Fail Feature Flag Enabled")
span.SetStatus(otelcodes.Error, msg)

Додавання подій до відрізка

Додавання подій до відрізка здійснюється за допомогою AddEvent на обʼєкті відрізка. У функції GetProduct подія відрізка додається, коли обробляється помилка, або коли продукт успішно знайдений.

span.AddEvent(msg)

Метрики

Ініціалізація Метрик

OpenTelemetry SDK ініціалізується з main за допомогою функції initMeterProvider.

func initMeterProvider() *sdkmetric.MeterProvider {
    ctx := context.Background()

    exporter, err := otlpmetricgrpc.New(ctx)
    if err != nil {
        log.Fatalf("new otlp metric grpc exporter failed: %v", err)
    }

    mp := sdkmetric.NewMeterProvider(sdkmetric.WithReader(sdkmetric.NewPeriodicReader(exporter)))
    global.SetMeterProvider(mp)
    return mp
}

Ви повинні викликати initMeterProvider.Shutdown() при завершенні роботи вашого сервісу, щоб забезпечити експорт всіх записів. Цей сервіс викликає цю функцію як частину відкладеної функції в main.

mp := initMeterProvider()
defer func() {
    if err := mp.Shutdown(context.Background()); err != nil {
        log.Fatalf("Error shutting down meter provider: %v", err)
    }
}()

Додавання автоінструментування Golang runtime

Golang runtime інструментується у функції main.

err := runtime.Start(runtime.WithMinimumReadMemStatsInterval(time.Second))
if err != nil {
    log.Fatal(err)
}

Логи

You can send your logs to the OpenTelemetry Collector in two ways:

  • Directly to the Collector
  • Through a file or stdout

You can find documentation specifying how to use both these approaches in the Logs section of the Manual Instrumentation documentation.

The Product Catalog service sends the logs directly to the Collector, and uses a log bridge to send its logs, bridging to the slog logging package, which outputs structured logs.

Ініціалізація LoggerProvider

OpenTelemetry SDK ініціалізується з main за допомогою функції initLoggerProvider.

ctx := context.Background()

logExporter, err := otlploggrpc.New(ctx)
if err != nil {
	return nil
}

loggerProvider := sdklog.NewLoggerProvider(
	sdklog.WithProcessor(sdklog.NewBatchProcessor(logExporter)),
)
global.SetLoggerProvider(loggerProvider)

return loggerProvider

Зробіть виклик LoggerProvider.Shutdown(), коли ваш сервіс не працює, щоб переконатися, що всі журнали експортовано. Цей сервіс виконує цей виклик як частину відкладеної функції у main:

lp := initLoggerProvider()
defer func() {
	if err := lp.Shutdown(context.Background()); err != nil {
		logger.Error(fmt.Sprintf("Logger Provider Shutdown: %v", err))
	}
	logger.Info("Shutdown logger provider")
}()

Функціональність ведення журналу

Цей сервіс надсилає логи до Collector за допомогою викликів gRPC. Логи виводяться у структурованому форматі за допомогою пакета slog.

Спочатку ініціалізуйте логер:

logger   *slog.Logger
logger = otelslog.NewLogger("product-catalog")

Зверніть увагу на використання fmt.Sprintf для форматування виводу перед надсиланням до журналу:

logger.Info("Loading Product Catalog...")
logger.Info(fmt.Sprintf("Product Catalog reload interval: %d", interval))
logger.Error(fmt.Sprintf("Error shutting down meter provider: %v", err))

Перевагою використання log є можливість додавання додаткових атрибутів до виводу. У наступному прикладі додано атрибути product.name та product.id. Це дозволяє переглядати і аналізувати їх як частину виводу журналу, а також полегшує їх перегляд як окремих стовпців у Grafana:

logger.LogAttrs(
	ctx,
	slog.LevelInfo, "Product Found",
	slog.String("app.product.name", found.Name),
	slog.String("app.product.id", req.Id),
)

Востаннє змінено December 26, 2024: [uk] Ukrainian documentation for OpenTelemetry (2a3c5648)