Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
481 changes: 254 additions & 227 deletions README.md

Large diffs are not rendered by default.

27 changes: 0 additions & 27 deletions _register.php

This file was deleted.

11 changes: 2 additions & 9 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
"autoload": {
"psr-4": {
"Overtrue\\LaravelOpenTelemetry\\": "src/"
},
"files": [
"_register.php"
]
}
},
"authors": [
{
Expand All @@ -19,21 +16,17 @@
],
"require": {
"php": ">=8.4",
"ext-opentelemetry": "*",
"laravel/framework": "^10.0|^11.0|^12.0",
"open-telemetry/api": "^1.0",
"open-telemetry/sdk": "^1.0",
"open-telemetry/exporter-otlp": "^1.3",
"open-telemetry/opentelemetry-auto-laravel": "^1.2"
"open-telemetry/sem-conv": "^1.32"
},
"require-dev": {
"orchestra/testbench": "^9.0",
"laravel/pint": "^1.15",
"spatie/test-time": "^1.3"
},
"suggest": {
"open-telemetry/opentelemetry-auto-guzzle": "If you want to automatically instrument Guzzle HTTP client requests."
},
"autoload-dev": {
"psr-4": {
"Overtrue\\LaravelOpenTelemetry\\Tests\\": "tests/"
Expand Down
73 changes: 61 additions & 12 deletions config/otel.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,67 @@
return [

/**
* The name of the header that will be used to pass the trace id in the response.
* if set to `null`, the header will not be added to the response.
* Enable or disable OpenTelemetry tracing
* When disabled, no watchers will be registered and no tracing will occur
*/
'response_trace_header_name' => env('OTEL_RESPONSE_TRACE_HEADER_NAME', 'X-Trace-Id'),
'enabled' => env('OTEL_ENABLED', true),

/**
* The name of the tracer that will be used to create spans.
* This is useful for identifying the source of the spans.
*/
'tracer_name' => env('OTEL_TRACER_NAME', 'overtrue.laravel-open-telemetry'),

/**
* Middleware Configuration
*/
'middleware' => [
/**
* Trace ID Middleware Configuration
* Used to add X-Trace-Id to response headers
*/
'trace_id' => [
'enabled' => env('OTEL_TRACE_ID_MIDDLEWARE_ENABLED', true),
'global' => env('OTEL_TRACE_ID_MIDDLEWARE_GLOBAL', true),
'header_name' => env('OTEL_TRACE_ID_HEADER_NAME', 'X-Trace-Id'),
],
],

/**
* HTTP Client Configuration
*/
'http_client' => [
/**
* Global Request Middleware Configuration
* Automatically adds OpenTelemetry propagation headers to all HTTP requests
*/
'propagation_middleware' => [
'enabled' => env('OTEL_HTTP_CLIENT_PROPAGATION_ENABLED', true),
],
],

/**
* Watchers Configuration
* Note: Starting from v2.0, we use OpenTelemetry's official auto-instrumentation
* Most tracing functionality is provided by the opentelemetry-auto-laravel package
* This package provides the following additional Watcher functionality:
*
* Available Watcher classes:
* - \Overtrue\LaravelOpenTelemetry\Watchers\CacheWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\QueryWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\HttpClientWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\ExceptionWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\AuthenticateWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\EventWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\QueueWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\RedisWatcher::class
* - \Overtrue\LaravelOpenTelemetry\Watchers\FrankenPhpWorkerWatcher::class
*/
'watchers' => [
\Overtrue\LaravelOpenTelemetry\Watchers\CacheWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\QueryWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\HttpClientWatcher::class, // 已添加智能重复检测,可以同时使用
\Overtrue\LaravelOpenTelemetry\Watchers\ExceptionWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\AuthenticateWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\EventWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\QueueWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\RedisWatcher::class,
\Overtrue\LaravelOpenTelemetry\Watchers\FrankenPhpWorkerWatcher::class,
],

/**
Expand All @@ -54,9 +89,23 @@
* Ignore paths will not be traced. You can use `*` as wildcard.
*/
'ignore_paths' => explode(',', env('OTEL_IGNORE_PATHS', implode(',', [
'horizon*',
'telescope*',
'_debugbar*',
'health*',
'up',
'horizon*', // Laravel Horizon dashboard
'telescope*', // Laravel Telescope dashboard
'_debugbar*', // Laravel Debugbar
'health*', // Health check endpoints
'ping', // Simple ping endpoint
'status', // Status endpoint
'metrics', // Metrics endpoint
'favicon.ico', // Browser favicon requests
'robots.txt', // SEO robots file
'sitemap.xml', // SEO sitemap
'api/health', // API health check
'api/ping', // API ping
'admin/health', // Admin health check
'internal/*', // Internal endpoints
'monitoring/*', // Monitoring endpoints
'_profiler/*', // Symfony profiler (if used)
'.well-known/*', // Well-known URIs (RFC 8615)
]))),
];
74 changes: 74 additions & 0 deletions examples/configuration_guide.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

/**
* Laravel OpenTelemetry Configuration Guide
*
* This file demonstrates how to use the new HTTP client configuration options
*/

// 1. Check if OpenTelemetry is enabled
if (config('otel.enabled', true)) {
echo "OpenTelemetry is enabled\n";
} else {
echo "OpenTelemetry is disabled\n";
}

// 2. Check tracer name
$tracerName = config('otel.tracer_name', 'overtrue.laravel-open-telemetry');
echo "Tracer name: {$tracerName}\n";

// 3. Check middleware configuration
$traceIdEnabled = config('otel.middleware.trace_id.enabled', true);
$traceIdGlobal = config('otel.middleware.trace_id.global', true);
$traceIdHeaderName = config('otel.middleware.trace_id.header_name', 'X-Trace-Id');

echo 'Trace ID Middleware enabled: '.($traceIdEnabled ? 'Yes' : 'No')."\n";
echo 'Trace ID Middleware global: '.($traceIdGlobal ? 'Yes' : 'No')."\n";
echo "Trace ID Header name: {$traceIdHeaderName}\n";

// 4. Check new HTTP client configuration
$httpClientPropagationEnabled = config('otel.http_client.propagation_middleware.enabled', true);
echo 'HTTP Client propagation middleware enabled: '.($httpClientPropagationEnabled ? 'Yes' : 'No')."\n";

// 5. View all available watchers
$watchers = config('otel.watchers', []);
echo "Available watchers:\n";
foreach ($watchers as $watcher) {
echo " - {$watcher}\n";
}

// 6. Environment variable configuration examples
echo "\n=== Environment Variable Examples ===\n";
echo "OTEL_ENABLED=true\n";
echo "OTEL_TRACER_NAME=my-app\n";
echo "OTEL_TRACE_ID_MIDDLEWARE_ENABLED=true\n";
echo "OTEL_TRACE_ID_MIDDLEWARE_GLOBAL=true\n";
echo "OTEL_TRACE_ID_HEADER_NAME=X-Custom-Trace-Id\n";
echo "OTEL_HTTP_CLIENT_PROPAGATION_ENABLED=true\n";

// 7. Demonstrate how to use in code
use Illuminate\Support\Facades\Http;
use Overtrue\LaravelOpenTelemetry\Facades\Measure;

// Fully automatic HTTP request tracing
// No manual code needed - all requests through Http facade are automatically traced with context propagation
$response = Http::get('https://httpbin.org/ip');

// View tracing status
$status = Measure::getStatus();
echo "\n=== Tracing Status ===\n";
echo 'Recording: '.($status['is_recording'] ? 'Yes' : 'No')."\n";
echo 'Current trace ID: '.($status['current_trace_id'] ?? 'None')."\n";
echo 'Active spans count: '.$status['active_spans_count']."\n";
echo 'Tracer provider: '.$status['tracer_provider']['class']."\n";

// 8. How to disable HTTP client propagation middleware
echo "\n=== How to Disable HTTP Client Propagation ===\n";
echo "In your .env file, set:\n";
echo "OTEL_HTTP_CLIENT_PROPAGATION_ENABLED=false\n";
echo "\nOr in config/otel.php:\n";
echo "'http_client' => [\n";
echo " 'propagation_middleware' => [\n";
echo " 'enabled' => false,\n";
echo " ],\n";
echo "],\n";
59 changes: 59 additions & 0 deletions examples/duplicate_tracing_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

/**
* Duplicate Tracing Prevention Test
*
* This file demonstrates how HttpClientWatcher intelligently avoids duplicate tracing
* through automatic context propagation using Laravel's globalRequestMiddleware
*/
echo "=== HTTP Client Tracing Solution ===\n\n";

echo "Previous Issue:\n";
echo "HTTP requests could potentially be traced multiple times if different\n";
echo "mechanisms were attempting to instrument the same request.\n\n";

echo "Current Solution:\n";
echo "- HttpClientWatcher creates spans for all HTTP requests\n";
echo "- Laravel's globalRequestMiddleware automatically adds propagation headers\n";
echo "- Smart duplicate detection prevents overlapping instrumentation\n";
echo "- Fully automatic - no manual configuration required\n\n";

echo "How it works:\n";

// Example 1: Automatic tracing (HttpClientWatcher handles everything)
echo "1. Automatic HTTP request tracing:\n";
echo " Http::get('https://httpbin.org/ip')\n";
echo " → HttpClientWatcher creates span\n";
echo " → globalRequestMiddleware adds propagation headers\n";
echo " → Single span created automatically\n\n";

// Example 2: Context propagation in microservices
echo "2. Microservice context propagation:\n";
echo " Http::get('http://service-b/api/users')\n";
echo " → Automatically includes trace context in headers\n";
echo " → Service B can continue the trace seamlessly\n\n";

echo "Key Features:\n";
echo "- No manual withTrace() calls needed\n";
echo "- Automatic propagation headers (traceparent, tracestate, etc.)\n";
echo "- Smart duplicate detection\n";
echo "- Works with all Laravel HTTP client usage patterns\n";
echo "- Zero configuration required\n\n";

echo "Configuration Options:\n";
echo "You can disable automatic propagation if needed:\n";
echo "OTEL_HTTP_CLIENT_PROPAGATION_ENABLED=false\n\n";
echo "Or in config/otel.php:\n";
echo "'http_client' => [\n";
echo " 'propagation_middleware' => ['enabled' => false]\n";
echo "]\n\n";

echo "Best Practices:\n";
echo "1. Let HttpClientWatcher handle all HTTP request tracing automatically\n";
echo "2. Use Measure::trace() for custom business logic spans\n";
echo "3. No need to manually add tracing to HTTP client calls\n";
echo "4. Context propagation happens automatically across services\n\n";

echo "Result:\n";
echo "Every HTTP request is traced exactly once with proper context propagation\n";
echo "between microservices - completely automatically!\n";
Loading