{"id":29824763,"url":"https://github.com/last9/php-7.4-laravel-otel","last_synced_at":"2026-04-13T11:01:21.083Z","repository":{"id":306131346,"uuid":"1021045623","full_name":"last9/php-7.4-laravel-otel","owner":"last9","description":"Manual OpenTelemetry Instrumentation for PHP 7.4 and Laravel app","archived":false,"fork":false,"pushed_at":"2025-07-23T19:03:47.000Z","size":24,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-07-23T21:30:45.325Z","etag":null,"topics":["laravel","opentelemetry","php","traces"],"latest_commit_sha":null,"homepage":"https://last9.io","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/last9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-16T19:44:02.000Z","updated_at":"2025-07-23T19:04:36.000Z","dependencies_parsed_at":"2025-07-23T21:30:47.335Z","dependency_job_id":"a6471715-b6de-4072-88b1-d3e578f3a44a","html_url":"https://github.com/last9/php-7.4-laravel-otel","commit_stats":null,"previous_names":["last9/php-7.4-laravel-otel"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/last9/php-7.4-laravel-otel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fphp-7.4-laravel-otel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fphp-7.4-laravel-otel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fphp-7.4-laravel-otel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fphp-7.4-laravel-otel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/last9","download_url":"https://codeload.github.com/last9/php-7.4-laravel-otel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/last9%2Fphp-7.4-laravel-otel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31749763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-13T09:16:15.125Z","status":"ssl_error","status_checked_at":"2026-04-13T09:16:05.023Z","response_time":93,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","opentelemetry","php","traces"],"created_at":"2025-07-29T04:00:35.273Z","updated_at":"2026-04-13T11:01:21.075Z","avatar_url":"https://github.com/last9.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Complete OpenTelemetry Setup Guide for Your Laravel App\n\n## 📁 Files to Copy\n\nCopy these 4 essential files from this project to your Laravel app:\n\n```\nbootstrap/otel.php                           # Core OpenTelemetry SDK setup\napp/Http/Middleware/OpenTelemetryMiddleware.php  # HTTP request/response tracing  \napp/Providers/AppServiceProvider.php            # Database tracing (copy the boot() method)\nconfig/otel.php                              # OpenTelemetry configuration (route filtering)\n```\n\n## 🔧 Integration Steps\n\n### 1. **Update `public/index.php`**\nAdd this line after the autoloader, before Laravel bootstrap:\n\n```php\n// Initialize OpenTelemetry SDK\nrequire_once __DIR__.'/../bootstrap/otel.php';\n```\n\n### 2. **Register HTTP Middleware**\nIn `app/Http/Kernel.php`, add to the `$middleware` array:\n\n```php\nprotected $middleware = [\n    // ... existing middleware\n    \\App\\Http\\Middleware\\OpenTelemetryMiddleware::class,\n];\n```\n\n### 2.1. **Configure Route Filtering**\nCopy the `config/otel.php` file to your `config/` directory to control which routes are traced:\n\n```php\n\u003c?php\n\nreturn [\n    /*\n    |--------------------------------------------------------------------------\n    | OpenTelemetry Route Tracing Configuration\n    |--------------------------------------------------------------------------\n    |\n    | This array defines which route patterns should be traced by the\n    | OpenTelemetry middleware. Routes starting with these patterns\n    | will have tracing enabled.\n    |\n    | Examples:\n    | - ['api'] - Only trace routes starting with /api\n    | - ['api', 'admin'] - Trace routes starting with /api or /admin\n    | - [''] - Trace all routes (empty string matches all)\n    |\n    */\n    'traced_routes' =\u003e [\n        'api'  // Only trace /api routes by default\n    ],\n];\n```\n\n**Configuration Examples:**\n- `['api']` - Only trace `/api/*` routes (default)\n- `['api', 'admin']` - Trace `/api/*` and `/admin/*` routes  \n- `['']` - Trace all routes (empty string matches all)\n- `[]` - Disable all tracing\n\n**Note:** The `config/otel.php` file is required for the middleware to function properly. Make sure to copy it to your Laravel app's `config/` directory.\n\n### 3. **Add Database Tracing**\nIn your existing `AppServiceProvider.php` `boot()` method, add this code:\n\n```php\npublic function boot()\n{\n    $tracer = $GLOBALS['otel_tracer'] ?? null;\n    \n    \\Illuminate\\Support\\Facades\\DB::listen(function ($query) use ($tracer) {\n        if (!$tracer) {\n            return;\n        }\n        \n        try {\n            $connectionName = $query-\u003econnectionName ?? config('database.default');\n            $connection = config(\"database.connections.{$connectionName}\");\n            \n            $spanBuilder = $tracer-\u003espanBuilder('db.query')\n                -\u003esetSpanKind(\\OpenTelemetry\\API\\Trace\\SpanKind::KIND_CLIENT)\n                -\u003esetAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::DB_SYSTEM, $connection['driver'] ?? 'unknown')\n                -\u003esetAttribute(\\OpenTelemetry\\SemConv\\TraceAttributes::DB_NAME, $connection['database'] ?? $connectionName)\n                -\u003esetAttribute('server.address', $connection['host'] ?? 'localhost')\n                -\u003esetAttribute('server.port', $connection['port'] ?? 3306)\n                -\u003esetAttribute('db.statement', $query-\u003esql)\n                -\u003esetAttribute('db.query.duration_ms', $query-\u003etime);\n            \n            // Add SQL parameter bindings if they exist\n            if (!empty($query-\u003ebindings)) {\n                $spanBuilder-\u003esetAttribute('db.statement.parameters', json_encode($query-\u003ebindings));\n                $spanBuilder-\u003esetAttribute('db.statement.parameters.count', count($query-\u003ebindings));\n            }\n            \n            $span = $spanBuilder-\u003estartSpan();\n            \n            $span-\u003esetStatus(\\OpenTelemetry\\API\\Trace\\StatusCode::STATUS_OK);\n            $span-\u003eend();\n            \n        } catch (\\Throwable $e) {\n            // Silently fail\n        }\n    });\n}\n```\n\n### 4. **Environment Variables**\nAdd to your `.env` file:\n\n```env\nOTEL_SERVICE_NAME=your-app-name\nOTEL_SERVICE_VERSION=1.0.0\nOTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://your-collector-endpoint/v1/traces\nOTEL_EXPORTER_OTLP_HEADERS=\"Authorization=Basic your-auth-token\"\nOTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf\n```\n\n### 5. **Composer Dependencies**\nAdd to your `composer.json` and run `composer install`:\n\n```json\n{\n    \"require\": {\n        \"open-telemetry/sdk\": \"^1.0\",\n        \"open-telemetry/contrib-otlp\": \"^1.0\",\n        \"open-telemetry/sem-conv\": \"^1.0\"\n    }\n}\n```\n\n## 🎯 What You'll Get\n\n- ✅ **HTTP Request Spans** - Configurable route-based tracing (only `/api` routes by default)\n- ✅ **Database Spans** - All Eloquent ORM and raw DB queries traced with SQL parameter binding\n- ✅ **SQL Parameter Binding** - Capture actual parameter values in `db.statement.parameters` attribute\n- ✅ **External HTTP Call Tracing** - Use helper functions `traced_curl_exec()` and `traced_guzzle_request()`\n- ✅ **Proper Span Relationships** - Database spans are children of HTTP request spans\n- ✅ **Performance Optimized** - Zero regex parsing, minimal overhead, non-traced routes skip all instrumentation\n\n## 🚀 Optional: External HTTP Calls\n\nFor tracing external HTTP calls, use these helper functions (included in `bootstrap/otel.php`):\n\n```php\n// Instead of curl_exec($ch)\n$result = traced_curl_exec($ch);\n\n// Instead of $client-\u003erequest($method, $url, $options)  \n$response = traced_guzzle_request($client, $method, $url, $options);\n```\n\n## 🔍 Testing Your Setup\n\nAfter integration, test that tracing is working:\n\n### Quick Test Endpoints\nYou can add these test routes to verify everything is working:\n\n```php\n// Test basic functionality\nRoute::get('/api/test-otel', function () {\n    // This will create HTTP span automatically via middleware\n    \n    // Test database span with parameter binding\n    $users = \\Illuminate\\Support\\Facades\\DB::select('SELECT COUNT(*) as count FROM users WHERE id \u003e ?', [0]);\n    \n    // Test Eloquent with parameter binding\n    $user = \\App\\User::find(1);\n    \n    // Test external HTTP call (if needed)\n    $ch = curl_init();\n    curl_setopt($ch, CURLOPT_URL, 'https://httpbin.org/get');\n    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n    $result = traced_curl_exec($ch);\n    curl_close($ch);\n    \n    return response()-\u003ejson([\n        'message' =\u003e 'OpenTelemetry test completed',\n        'user_count' =\u003e $users[0]-\u003ecount ?? 0,\n        'specific_user' =\u003e $user ? $user-\u003ename : null,\n        'external_call' =\u003e 'success'\n    ]);\n});\n```\n\n### Verification Checklist\n- [ ] HTTP request span appears in your tracing backend\n- [ ] Database query spans appear as children of HTTP span\n- [ ] SQL parameter binding values appear in `db.statement.parameters` attribute\n- [ ] Parameter count appears in `db.statement.parameters.count` attribute\n- [ ] External HTTP call spans appear (if using helper functions)\n- [ ] All spans contain proper semantic attributes\n- [ ] No application errors or performance degradation\n\n### Example Database Span Attributes\n```json\n{\n  \"db.statement\": \"select * from users where id = ? limit 1\",\n  \"db.statement.parameters\": \"[1]\",\n  \"db.statement.parameters.count\": 1,\n  \"db.sql.table\": \"users\",\n  \"db.system\": \"mysql\",\n  \"db.name\": \"laravel_app\",\n  \"db.query.duration_ms\": 2.5\n}\n```\n\n## 🐛 Troubleshooting\n\n### Common Issues\n\n1. **No spans appearing**\n   - Check environment variables are set correctly\n   - Verify collector endpoint is reachable\n   - Check Laravel logs for any errors\n\n2. **Database spans missing**\n   - Ensure `AppServiceProvider.php` boot method includes the DB::listen code\n   - Verify database queries are actually executing\n\n3. **HTTP spans missing**\n   - Confirm middleware is registered in `Kernel.php`\n   - Check middleware order (should be early in the stack)\n   - Ensure `config/otel.php` exists and contains proper route patterns\n\n4. **Route filtering not working**\n   - Verify `config/otel.php` is copied to your Laravel app\n   - Check that `traced_routes` array matches your desired route patterns\n   - Run `php artisan config:cache` after modifying the config file\n\n4. **Performance issues**\n   - This implementation is optimized for minimal overhead\n   - Monitor your application performance before/after\n   - Adjust batch processor settings in `bootstrap/otel.php` if needed\n\n## 📚 Additional Resources\n\n- [OpenTelemetry PHP Documentation](https://opentelemetry.io/docs/php/)\n- [OpenTelemetry Semantic Conventions](https://opentelemetry.io/docs/specs/semconv/)\n- [Laravel Service Providers](https://laravel.com/docs/providers)\n- [Laravel Middleware](https://laravel.com/docs/middleware)\n\n---\n\nThat's it! Your Laravel app will now have comprehensive OpenTelemetry tracing with HTTP, database, and external call monitoring.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flast9%2Fphp-7.4-laravel-otel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flast9%2Fphp-7.4-laravel-otel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flast9%2Fphp-7.4-laravel-otel/lists"}