Skip to content
This repository was archived by the owner on Dec 5, 2025. It is now read-only.

Commit 0a0c98e

Browse files
committed
wip
1 parent f7f9923 commit 0a0c98e

39 files changed

+1837
-1858
lines changed

README.md

Lines changed: 202 additions & 328 deletions
Large diffs are not rendered by default.

_register.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use OpenTelemetry\SDK\Sdk;
6+
7+
// Check if disabled
8+
if (class_exists(Sdk::class) && Sdk::isInstrumentationDisabled('laravel') === true) {
9+
return;
10+
}
11+
12+
// Check if OpenTelemetry extension is loaded
13+
if (extension_loaded('opentelemetry') === false) {
14+
trigger_error('The opentelemetry extension must be loaded in order to autoload the OpenTelemetry Laravel auto-instrumentation', E_USER_WARNING);
15+
return;
16+
}
17+
18+
// Check if Laravel exists
19+
if (! class_exists(\Illuminate\Foundation\Application::class)) {
20+
return;
21+
}
22+
23+
// Register Laravel enhancements
24+
require_once __DIR__ . '/src/LaravelInstrumentation.php';
25+
26+
\Overtrue\LaravelOpenTelemetry\LaravelInstrumentation::register();

composer.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
"autoload": {
77
"psr-4": {
88
"Overtrue\\LaravelOpenTelemetry\\": "src/"
9-
}
9+
},
10+
"files": [
11+
"_register.php"
12+
]
1013
},
1114
"authors": [
1215
{
@@ -16,6 +19,7 @@
1619
],
1720
"require": {
1821
"php": ">=8.4",
22+
"ext-opentelemetry": "*",
1923
"laravel/framework": "^10.0|^11.0|^12.0",
2024
"open-telemetry/api": "^1.0",
2125
"open-telemetry/sdk": "^1.0",
@@ -27,9 +31,7 @@
2731
"laravel/pint": "^1.15",
2832
"spatie/test-time": "^1.3"
2933
},
30-
"suggest": {
31-
"ext-opentelemetry": "Required for zero-code instrumentation"
32-
},
34+
"suggest": {},
3335
"autoload-dev": {
3436
"psr-4": {
3537
"Overtrue\\LaravelOpenTelemetry\\Tests\\": "tests/"

config/otel.php

Lines changed: 20 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,32 @@
11
<?php
22

3-
use Overtrue\LaravelOpenTelemetry\Watchers;
4-
53
return [
6-
/**
7-
* Enable or disable the OpenTelemetry Laravel Extension.
8-
*/
9-
'enabled' => env('OTEL_ENABLED', true),
104

115
/**
12-
* Auto Register the MeasureRequest middleware.
13-
*/
14-
'automatically_trace_requests' => env('OTEL_AUTO_TRACE_REQUESTS', true),
15-
16-
/**
17-
* SDK Configuration
18-
*/
19-
'sdk' => [
20-
'auto_initialize' => env('OTEL_SDK_AUTO_INITIALIZE', true),
21-
'service_name' => env('OTEL_SERVICE_NAME', config('app.name', 'laravel-app')),
22-
'service_version' => env('OTEL_SERVICE_VERSION', '1.0.0'),
23-
],
24-
25-
/**
26-
* Exporter Configuration
6+
* The name of the header that will be used to pass the trace id in the response.
7+
* if set to `null`, the header will not be added to the response.
278
*/
28-
'exporters' => [
29-
'traces' => env('OTEL_TRACES_EXPORTER', 'console'),
30-
'metrics' => env('OTEL_METRICS_EXPORTER', 'none'),
31-
'logs' => env('OTEL_LOGS_EXPORTER', 'none'),
32-
],
9+
'response_trace_header_name' => env('OTEL_RESPONSE_TRACE_HEADER_NAME', 'X-Trace-Id'),
3310

3411
/**
35-
* OTLP Exporter Configuration
12+
* Watchers Configuration
13+
* Note: Starting from v2.0, we use OpenTelemetry's official auto-instrumentation
14+
* Most tracing functionality is provided by the opentelemetry-auto-laravel package
15+
* This package provides the following additional Watcher functionality:
16+
*
17+
* Available Watcher classes:
18+
* - \Overtrue\LaravelOpenTelemetry\Watchers\ExceptionWatcher::class
19+
* - \Overtrue\LaravelOpenTelemetry\Watchers\AuthenticateWatcher::class
20+
* - \Overtrue\LaravelOpenTelemetry\Watchers\EventWatcher::class
21+
* - \Overtrue\LaravelOpenTelemetry\Watchers\QueueWatcher::class
22+
* - \Overtrue\LaravelOpenTelemetry\Watchers\RedisWatcher::class
3623
*/
37-
'otlp' => [
38-
'endpoint' => env('OTEL_EXPORTER_OTLP_ENDPOINT', 'http://localhost:4318'),
39-
'headers' => env('OTEL_EXPORTER_OTLP_HEADERS', ''),
40-
'timeout' => env('OTEL_EXPORTER_OTLP_TIMEOUT', 10),
24+
'watchers' => [
25+
\Overtrue\LaravelOpenTelemetry\Watchers\ExceptionWatcher::class,
26+
\Overtrue\LaravelOpenTelemetry\Watchers\AuthenticateWatcher::class,
27+
\Overtrue\LaravelOpenTelemetry\Watchers\EventWatcher::class,
28+
\Overtrue\LaravelOpenTelemetry\Watchers\QueueWatcher::class,
29+
\Overtrue\LaravelOpenTelemetry\Watchers\RedisWatcher::class,
4130
],
4231

4332
/**
@@ -68,22 +57,4 @@
6857
'_debugbar*',
6958
'health*',
7059
]))),
71-
72-
/**
73-
* The name of the header that will be used to pass the trace id in the response.
74-
* if set to `null`, the header will not be added to the response.
75-
*/
76-
'response_trace_header_name' => env('OTEL_RESPONSE_TRACE_HEADER_NAME', 'X-Trace-Id'),
77-
78-
/**
79-
* Watchers to be registered.
80-
*/
81-
'watchers' => [
82-
Watchers\ExceptionWatcher::class,
83-
Watchers\AuthenticateWatcher::class,
84-
Watchers\EventWatcher::class,
85-
Watchers\QueueWatcher::class,
86-
Watchers\RedisWatcher::class,
87-
// App\Trace\Watchers\YourCustomWatcher::class, // Add your custom watcher here.
88-
],
8960
];

src/Console/Commands/TestCommand.php

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,21 @@ public function handle(): int
3434
return Command::FAILURE;
3535
}
3636

37-
// 获取详细状态信息
37+
// Detect running mode
38+
$hasExtension = extension_loaded('opentelemetry');
39+
$mode = $hasExtension ? 'Auto-Instrumentation' : 'Manual';
40+
41+
$this->info("🔧 Mode: <comment>{$mode}</comment>");
42+
$this->info('📦 Extension: '.($hasExtension ? '<info>Loaded</info>' : '<comment>Not Available</comment>'));
43+
$this->info('');
44+
45+
// Get detailed status information
3846
$status = Measure::getStatus();
3947

4048
$this->info('📊 Current Status:');
4149
$this->line(' Recording: '.($status['is_recording'] ? '<info>Yes</info>' : '<comment>No</comment>'));
4250
$this->line(" TracerProvider: <comment>{$status['tracer_provider']['class']}</comment>");
51+
$this->line(' Source: <comment>'.($status['tracer_provider']['source'] ?? 'Unknown').'</comment>');
4352
$this->line(" Active Spans: <info>{$status['active_spans_count']}</info>");
4453
$this->info('');
4554

@@ -99,7 +108,7 @@ public function handle(): int
99108
sleep(1);
100109

101110
// End child span
102-
Measure::end('Child Operation');
111+
Measure::end();
103112
$this->info('Child span completed.');
104113

105114
// Record event
@@ -115,7 +124,7 @@ public function handle(): int
115124
$traceId = $rootSpan->span->getContext()->getTraceId();
116125

117126
// End root span
118-
Measure::end('Test Span');
127+
Measure::end();
119128

120129
// Output result
121130
$this->info('');
@@ -136,7 +145,10 @@ public function handle(): int
136145
]
137146
);
138147

139-
// 显示最终状态
148+
// Check enhancement status
149+
$this->checkEnhancementStatus();
150+
151+
// Display final status
140152
$finalStatus = Measure::getStatus();
141153
$this->info('');
142154
$this->info('📈 Final Status:');
@@ -160,4 +172,73 @@ public function handle(): int
160172

161173
return Command::SUCCESS;
162174
}
175+
176+
/**
177+
* Check enhancement status
178+
*/
179+
private function checkEnhancementStatus(): void
180+
{
181+
$this->info('');
182+
$this->info('🚀 Enhancement Status:');
183+
184+
// Check official package
185+
$hasOfficialPackage = class_exists('OpenTelemetry\\Contrib\\Instrumentation\\Laravel\\LaravelInstrumentation');
186+
$this->line(' Official Laravel Package: '.($hasOfficialPackage ? '<info>Installed</info>' : '<error>Not Installed</error>'));
187+
188+
// Check our enhancement features
189+
$hasEnhancement = class_exists('Overtrue\\LaravelOpenTelemetry\\Support\\AutoInstrumentation\\LaravelInstrumentation');
190+
$this->line(' Enhancement Classes: '.($hasEnhancement ? '<info>Available</info>' : '<error>Not Available</error>'));
191+
192+
// Check if _register.php is in autoload
193+
$autoloadFilePath = base_path('vendor/composer/autoload_files.php');
194+
$hasRegisterFile = false;
195+
if (file_exists($autoloadFilePath)) {
196+
$composerAutoload = file_get_contents($autoloadFilePath);
197+
$hasRegisterFile = strpos($composerAutoload, '_register.php') !== false;
198+
}
199+
$this->line(' Auto Register File: '.($hasRegisterFile ? '<info>Loaded</info>' : '<comment>Not Detected</comment>'));
200+
201+
// Check Guzzle macro
202+
$hasGuzzleMacro = \Illuminate\Http\Client\PendingRequest::hasMacro('withTrace');
203+
$this->line(' Guzzle Trace Macro: '.($hasGuzzleMacro ? '<info>Registered</info>' : '<error>Not Registered</error>'));
204+
205+
// Check Watcher status
206+
$this->info('');
207+
$this->info('👀 Watchers Status:');
208+
$watchers = config('otel.watchers', []);
209+
if (empty($watchers)) {
210+
$this->line(' <comment>No watchers configured</comment>');
211+
} else {
212+
foreach ($watchers as $watcherClass) {
213+
$className = class_basename($watcherClass);
214+
$exists = class_exists($watcherClass);
215+
$status = $exists ? '<info>Enabled</info>' : '<error>Class not found</error>';
216+
$this->line(" {$className}: {$status}");
217+
}
218+
}
219+
220+
// Check if Watcher classes exist
221+
$watcherClasses = [
222+
'ExceptionWatcher' => 'Overtrue\\LaravelOpenTelemetry\\Watchers\\ExceptionWatcher',
223+
'AuthenticateWatcher' => 'Overtrue\\LaravelOpenTelemetry\\Watchers\\AuthenticateWatcher',
224+
'EventWatcher' => 'Overtrue\\LaravelOpenTelemetry\\Watchers\\EventWatcher',
225+
'QueueWatcher' => 'Overtrue\\LaravelOpenTelemetry\\Watchers\\QueueWatcher',
226+
'RedisWatcher' => 'Overtrue\\LaravelOpenTelemetry\\Watchers\\RedisWatcher',
227+
];
228+
229+
$this->info('');
230+
$this->info('🔍 Watcher Classes Status:');
231+
foreach ($watcherClasses as $name => $class) {
232+
$exists = class_exists($class);
233+
$this->line(" {$name}: ".($exists ? '<info>Available</info>' : '<error>Not Available</error>'));
234+
}
235+
236+
if (! $hasOfficialPackage) {
237+
$this->warn('⚠️ Recommend installing the official opentelemetry-auto-laravel package for full functionality');
238+
}
239+
240+
if (! $hasEnhancement) {
241+
$this->error('❌ Enhancement classes not available, please check package installation');
242+
}
243+
}
163244
}

src/Facades/Measure.php

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace Overtrue\LaravelOpenTelemetry\Facades;
46

57
use Illuminate\Support\Facades\Facade;
8+
use OpenTelemetry\API\Trace\SpanBuilderInterface;
69
use OpenTelemetry\API\Trace\SpanInterface;
710
use OpenTelemetry\API\Trace\TracerInterface;
8-
use OpenTelemetry\Context\ContextInterface;
9-
use OpenTelemetry\Context\Propagation\TextMapPropagatorInterface;
11+
use OpenTelemetry\Context\Context;
12+
use OpenTelemetry\Context\Propagation\PropagationGetterInterface;
1013
use OpenTelemetry\Context\ScopeInterface;
11-
use Overtrue\LaravelOpenTelemetry\Support\SpanBuilder;
12-
use Overtrue\LaravelOpenTelemetry\Support\StartedSpan;
1314

1415
/**
15-
* @method static SpanBuilder span(string $name, ?string $prefix = null)
16-
* @method static StartedSpan start(int|string $name, ?callable $callback = null)
17-
* @method static void end(?string $name = null)
16+
* @method static \Overtrue\LaravelOpenTelemetry\Support\SpanBuilder span(string $spanName)
17+
* @method static \Overtrue\LaravelOpenTelemetry\Support\StartedSpan start(string $spanName)
18+
* @method static void end()
19+
* @method static TracerInterface tracer()
1820
* @method static SpanInterface activeSpan()
1921
* @method static ScopeInterface|null activeScope()
20-
* @method static string|null traceId()
21-
* @method static TracerInterface tracer()
22-
* @method static TextMapPropagatorInterface propagator()
23-
* @method static array propagationHeaders(?ContextInterface $context = null)
24-
* @method static ContextInterface extractContextFromPropagationHeaders(array $headers)
25-
* @method static bool isRecording()
26-
* @method static array getStatus()
27-
* @method static void flush()
22+
* @method static string traceId()
23+
* @method static mixed propagator()
24+
* @method static array propagationHeaders(Context $context = null)
25+
* @method static Context extractContextFromPropagationHeaders(array $headers)
26+
*
27+
* @see \Overtrue\LaravelOpenTelemetry\Support\Measure
2828
*/
2929
class Measure extends Facade
3030
{
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Overtrue\LaravelOpenTelemetry\Hooks\Illuminate\Foundation;
6+
7+
use Illuminate\Foundation\Application as FoundationApplication;
8+
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHook;
9+
use OpenTelemetry\Contrib\Instrumentation\Laravel\Hooks\LaravelHookTrait;
10+
use function OpenTelemetry\Instrumentation\hook;
11+
12+
class Application implements LaravelHook
13+
{
14+
use LaravelHookTrait;
15+
16+
public function instrument(): void
17+
{
18+
hook(
19+
class: FoundationApplication::class,
20+
function: 'boot',
21+
post: function (FoundationApplication $app) {
22+
$this->registerWatchers($app);
23+
}
24+
);
25+
}
26+
27+
/**
28+
* Register all configured Watchers
29+
*/
30+
private function registerWatchers(FoundationApplication $app): void
31+
{
32+
$watchers = $app['config']->get('otel.watchers', []);
33+
34+
foreach ($watchers as $watcherClass) {
35+
if (class_exists($watcherClass)) {
36+
$watcher = new $watcherClass($this->instrumentation);
37+
$watcher->register($app);
38+
}
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)