承接 gilbitron/canonical-context-logging 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

gilbitron/canonical-context-logging

最新稳定版本:0.2.0

Composer 安装命令:

composer require gilbitron/canonical-context-logging

包简介

PHP SDK for Canonical Context Logging - structured JSON logs with one wide event per request

README 文档

README

PHP SDK for Canonical Context Logging - structured JSON logs with one wide event per request.

Overview

This package implements the Canonical Context Logging pattern:

  1. Emit structured logs only - JSON, consistent keys, no free-text messages
  2. Log one "wide event" per request - Capture all context in a single final log entry
  3. Accumulate context via middleware - Build an event object at request start, enrich it throughout execution, emit once at the end
  4. Prefer context over volume - Fewer logs, richer data
  5. Tail-sample aggressively - Always keep errors + slow requests; sample the rest
  6. Store logs as queryable data - Columnar DB + SQL > grep
  7. OTel is transport, not design - You decide what to log; business context is your job

Requirements

  • PHP 8.1 or higher
  • OpenTelemetry SDK

Installation

composer require gilbitron/canonical-context-logging

Quick Start

Basic Usage (Framework-Agnostic)

use CanonicalContextLogging\Context\SingletonStorage; use CanonicalContextLogging\Exporter\OtlpExporter; use CanonicalContextLogging\Logger\CanonicalLogger; use CanonicalContextLogging\Middleware\RequestMiddleware; // Setup - OTLP exporter reads from environment variables by default // Set OTEL_EXPORTER_OTLP_ENDPOINT=https://otel-collector:4318 $storage = new SingletonStorage(); $exporter = new OtlpExporter(); // Reads config from environment $logger = new CanonicalLogger( exporter: $exporter, slowRequestThreshold: 1.0, // Log requests slower than 1 second sampleRate: 0.1 // Sample 10% of normal requests ); $middleware = new RequestMiddleware($storage, $logger); // Start request $context = $middleware->start(); $context->setService('my-service', '1.0.0'); $context->addContext('user_id', 123); $context->addContext('org_id', 456); // ... your application logic ... // End request $context->setStatus(200); $context->setDuration(0.123); $middleware->end($context);

With Error Handling

try { $context = $middleware->start(); $context->setService('my-service', '1.0.0'); // ... application logic ... $context->setStatus(200); } catch (\Throwable $e) { $context->setError($e); $context->setStatus(500); } finally { $context->setDuration($context->getDuration()); $middleware->end($context); }

Configuration

Exporter Options

Console Exporter (Development)

For local development, you can use the console exporter to output logs to stdout/stderr:

use CanonicalContextLogging\Exporter\ConsoleExporter; // Output to stderr with pretty printing $exporter = new ConsoleExporter(useStderr: true, prettyPrint: true); // Output to stdout, compact JSON $exporter = new ConsoleExporter(useStderr: false, prettyPrint: false);

OTLP Exporter (Production)

The OTLP exporter uses the official OpenTelemetry SDK and reads configuration from environment variables:

use CanonicalContextLogging\Exporter\OtlpExporter; use CanonicalContextLogging\Exporter\OtlpConfig; // Option 1: Use environment variables (recommended) $exporter = new OtlpExporter(); // Reads from environment // Option 2: Explicit configuration $config = OtlpConfig::create( endpoint: 'https://otel-collector:4318', protocol: 'http/protobuf', headers: ['Authorization' => 'Bearer ' . $apiKey], timeout: 10 ); $exporter = new OtlpExporter($config);

Environment Variables:

The exporter reads standard OpenTelemetry environment variables:

  • OTEL_EXPORTER_OTLP_ENDPOINT - OTLP endpoint URL (default: http://localhost:4318)
  • OTEL_EXPORTER_OTLP_PROTOCOL - Protocol to use: http/protobuf or http/json (default: http/protobuf)
  • OTEL_EXPORTER_OTLP_HEADERS - Headers as comma-separated key=value pairs (e.g., key1=value1,key2=value2)
  • OTEL_EXPORTER_OTLP_TIMEOUT - Timeout in seconds (default: 10)

Example:

export OTEL_EXPORTER_OTLP_ENDPOINT=https://otel-collector:4318 export OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer token123" export OTEL_EXPORTER_OTLP_TIMEOUT=10

File Exporter

Write logs to a file in JSONL format (one JSON object per line):

use CanonicalContextLogging\Exporter\FileExporter; // Compact JSON (default) $exporter = new FileExporter('/var/log/app.jsonl'); // Pretty-printed JSON $exporter = new FileExporter('/var/log/app.jsonl', prettyPrint: true);

The FileExporter automatically creates the directory structure if it doesn't exist and appends each log entry as a new line (JSONL format).

Custom Exporter

Implement ExporterInterface to create your own exporter:

use CanonicalContextLogging\Exporter\ExporterInterface; class CustomExporter implements ExporterInterface { public function export(array $data): void { // Your custom export logic } }

Logger Configuration

use CanonicalContextLogging\Logger\CanonicalLogger; $logger = new CanonicalLogger( exporter: $exporter, slowRequestThreshold: 1.0, // Always log requests slower than 1 second sampleRate: 0.1 // Sample 10% of normal requests (0.0 to 1.0) );

Tail-Sampling Rules:

  • Errors are always logged
  • Slow requests (above threshold) are always logged
  • Other requests are sampled based on sampleRate
  • If sampleRate is null, all requests are logged

Context Storage

Singleton Storage (Framework-Agnostic)

use CanonicalContextLogging\Context\SingletonStorage; $storage = new SingletonStorage();

Container Storage (Framework-Specific)

For framework integration, create a custom storage implementation that uses your framework's container.

EventContext API

The EventContext class accumulates all context for a single request:

$context = new EventContext(); // Initialize request $context->startRequest($traceId, $spanId); // Service metadata $context->setService('my-service', '1.0.0'); // Business context (user, org, plan, feature flags, etc.) $context->addContext('user_id', 123); $context->addContext('org_id', 456); $context->addContext('plan', 'premium'); $context->addContext('feature_flags', ['feature_a', 'feature_b']); // Or add multiple at once $context->addContexts([ 'user_id' => 123, 'org_id' => 456, 'plan' => 'premium', ]); // Error handling $context->setError($exception); // HTTP status $context->setStatus(200); // Duration (auto-calculated if not set) $context->setDuration(0.123); // Export as array for JSON encoding $data = $context->toArray();

Log Output Format

The structured log output follows this schema:

{ "timestamp": "2024-01-15T10:30:45+00:00", "trace_id": "a1b2c3d4e5f6...", "span_id": "1234567890abcdef", "service": { "name": "my-service", "version": "1.0.0" }, "status": 200, "duration": 0.123, "context": { "user_id": 123, "org_id": 456, "plan": "premium", "feature_flags": ["feature_a", "feature_b"] }, "error": { "type": "RuntimeException", "message": "Something went wrong", "file": "/path/to/file.php", "line": 42, "code": 0 } }

Best Practices

  1. One log per request - Use middleware to emit a single log at request end
  2. Accumulate context - Add business context throughout request execution
  3. Structured data only - No free-text messages, use consistent keys
  4. Tail-sample - Configure sampling to reduce volume while keeping errors and slow requests
  5. Business context - Include user, org, plan, feature flags, etc. - anything that helps answer questions
  6. Error handling - Always capture exceptions in context, even if you re-throw them

License

MIT

统计信息

  • 总下载量: 90
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-01-04

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固