spatie/flare-debug-sender
Debug sender for Flare payloads, mainly for internal testing. Swap Flare’s sender to log, inspect, and optionally passthrough errors/traces/zipkin, replace tracing IDs/timestamps, and print parts or the full payload via configurable channels.
composer require spatie/flare-debug-sender
php artisan vendor:publish --tag=flare-config
config/flare.php:
'sender' => [
'class' => \Spatie\FlareDebugSender\FlareDebugSender::class,
'config' => [
'channel' => \Spatie\FlareDebugSender\Channels\RayDebugChannel::class,
'passthrough_errors' => true,
],
],
\Spatie\FlareDebugSender\Facades\FlareDebugSender::send(
new \Exception('Test error for debugging')
);
Or use the Artisan command:
php artisan flare:debug-send "Test error message"
// In your exception handler or test
FlareDebugSender::send(
new \App\Exceptions\CustomPaymentException('Payment failed'),
context: ['user_id' => 123, 'amount' => 100.00]
);
Check Ray or your configured channel (e.g., Laravel logs) for the payload.
Configure for your environment:
RayDebugChannel for interactive debugging (default).LaravelLogDebugChannel for CI/CD pipelines:
'channel' => \Spatie\FlareDebugSender\Channels\LaravelLogDebugChannel::class,
FileDebugChannel for long-running processes:
'channel' => \Spatie\FlareDebugSender\Channels\FileDebugChannel::class,
'channel_config' => ['file' => storage_path('logs/flare-debug.log')],
Send payloads programmatically:
// Simulate a 500 error with context
FlareDebugSender::send(
new \RuntimeException('Database connection failed'),
context: ['query' => 'SELECT * FROM users']
);
// Simulate a trace (e.g., API call)
FlareDebugSender::sendTrace(
'api.payment.process',
startTime: now()->subMinutes(2),
endTime: now(),
tags: ['payment_id' => 'pay_123']
);
Integrate with tests:
public function test_payment_failure()
{
FlareDebugSender::send(
new \Exception('Payment declined'),
context: ['user' => $this->user]
);
$this->assertLogContains('Payment declined');
}
if (app()->environment('local')) {
FlareDebugSender::send(
new \Exception('Debug only in local'),
context: ['debug' => true]
);
}
Override the default CurlSender to mock API responses:
'sender' => \App\Services\MockFlareSender::class,
'sender_config' => [
'mock_responses' => [
'flare.spatie.be' => [
'status' => 200,
'body' => '{"success": true}',
],
],
],
// Record a trace locally
FlareDebugSender::sendTrace('user.login', startTime: now()->subMinutes(1));
// Later, replay it with adjusted timings
FlareDebugSender::sendTrace(
'user.login',
startTime: now()->subSeconds(5), // Simulate faster response
endTime: now()
);
Combine multiple channels (e.g., log + file):
'channel' => \Spatie\FlareDebugSender\Channels\ChainDebugChannel::class,
'channel_config' => [
'channels' => [
\Spatie\FlareDebugSender\Channels\RayDebugChannel::class,
\Spatie\FlareDebugSender\Channels\FileDebugChannel::class,
],
],
Payload Size Limits:
print_full_payload: true to debug, then trim data for production.FlareDebugSender::send(
new \Exception('Large data'),
context: ['data' => json_encode($largeArray)] // Avoid direct serialization
);
SSL Verification:
CurlSender disables SSL verification (CURLOPT_SSL_VERIFYPEER => 0). This is fine for local debugging but disable in production.'sender' => \Spatie\FlareDebugSender\Senders\SecureCurlSender::class,
Trace ID Collisions:
replace_tracing_ids: true helps readability but may obscure debugging if traces span multiple requests. Disable for complex workflows:
'replace_tracing_ids' => false,
Channel Buffering:
FileDebugChannel and LaravelLogDebugChannel may buffer writes. For critical debugging, use RayDebugChannel or flush manually:
\Spatie\FlareDebugSender\Facades\FlareDebugSender::flush();
Flare v3 Breaking Changes:
context fields). Test with real payloads early:
// Compare v2 vs. v3 payloads
$v3Payload = FlareDebugSender::getPayloadStructure();
dd($v3Payload);
Inspect Raw Payloads: Enable full payload printing to validate structure:
'print_full_payload' => true,
Then check your channel (e.g., Ray or logs).
Simulate Production Errors:
Use passthrough_errors: false to block errors from reaching Flare’s real endpoint:
'passthrough_errors' => false, // Only debug locally
Debugging Artisan Commands:
Add this to your AppServiceProvider to auto-send command errors:
public function boot()
{
if ($this->app->environment('local')) {
\Artisan::error(function ($e) {
FlareDebugSender::send($e);
});
}
}
Zipkin Integration: For distributed tracing, enable Zipkin passthrough (requires local Zipkin instance):
'passthrough_zipkin' => true,
'sender_config' => [
'zipkin_url' => 'http://localhost:9411/api/v2/spans',
],
Performance Profiling:
Use replace_tracing_times: false to analyze real timing data:
'replace_tracing_times' => false,
Then inspect traces in Ray or your channel.
Custom Channels:
Extend DebugChannel to integrate with tools like Laravel Horizon or Sentry:
namespace App\Channels;
use Spatie\FlareDebugSender\DebugChannel;
class SentryDebugChannel implements DebugChannel
{
public function send(string $message): void
{
\Sentry\captureMessage($message);
}
}
Then configure:
'channel' => \App\Channels\SentryDebugChannel::class,
Payload Transformers: Modify payloads before sending (e.g., redact sensitive data):
'sender_config' => [
'payload_transformer' => function ($payload) {
$payload['context']['password'] = '[redacted]';
return $payload;
},
],
Dynamic Configuration:
Override config per environment using Laravel’s config():
// In a service provider
$this->app->singleton('flare.debug.sender', function () {
$config = config('flare.sender.config');
$config['channel'] = app()->environment('local')
? \Spatie\FlareDebugSender\Channels\RayDebugChannel::class
: \Spatie\FlareDebugSender\Channels\LaravelLogDebugChannel::class;
return new \
How can I help you explore Laravel packages today?