# Logging Platform Integrations
This guide covers integrating the Monolog GDPR Filter with popular logging platforms and services.
## Table of Contents
- [ELK Stack (Elasticsearch, Logstash, Kibana)](#elk-stack)
- [Graylog](#graylog)
- [Datadog](#datadog)
- [New Relic](#new-relic)
- [Sentry](#sentry)
- [Papertrail](#papertrail)
- [Loggly](#loggly)
- [AWS CloudWatch](#aws-cloudwatch)
- [Google Cloud Logging](#google-cloud-logging)
- [Fluentd/Fluent Bit](#fluentdfluent-bit)
## ELK Stack
### Elasticsearch with Monolog
```php
setHosts(['localhost:9200'])
->build();
// Create handler
$handler = new ElasticsearchHandler($client, [
'index' => 'app-logs',
'type' => '_doc',
]);
$handler->setFormatter(new ElasticsearchFormatter('app-logs', '_doc'));
// Create logger with GDPR processor
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
// Logs are now GDPR-compliant before reaching Elasticsearch
$logger->info('User login', ['email' => 'user@example.com', 'ip' => '192.168.1.1']);
```
### Logstash Integration
For Logstash, use the Gelf handler or send JSON to a TCP/UDP input:
```php
setFormatter(new JsonFormatter());
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
```
Logstash configuration:
```ruby
input {
tcp {
port => 5000
codec => json
}
}
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "app-logs-%{+YYYY.MM.dd}"
}
}
```
## Graylog
### GELF Handler Integration
```php
pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
$logger->info('Payment processed', [
'user_email' => 'customer@example.com',
'card_last_four' => '4242',
]);
```
### Graylog Stream Configuration
Create a stream to filter GDPR-sensitive logs:
1. Create an extractor to identify masked fields
2. Set up alerts for potential data leaks (unmasked patterns)
```php
pushProcessor(function ($record) {
$record['extra']['gdpr_processed'] = true;
$record['extra']['app_version'] = '1.0.0';
return $record;
});
```
## Datadog
### Datadog Handler Integration
```php
setFormatter(new JsonFormatter());
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
// Add Datadog-specific context
$logger->pushProcessor(function ($record) {
$record['extra']['dd'] = [
'service' => 'my-php-app',
'env' => getenv('DD_ENV') ?: 'production',
'version' => '1.0.0',
];
return $record;
});
$logger->info('User action', ['user_id' => 123, 'email' => 'user@example.com']);
```
### Datadog APM Integration
```php
pushProcessor(function ($record) {
$tracer = GlobalTracer::get();
$span = $tracer->getActiveSpan();
if ($span) {
$record['extra']['dd.trace_id'] = $span->getTraceId();
$record['extra']['dd.span_id'] = $span->getSpanId();
}
return $record;
});
```
## New Relic
### New Relic Handler Integration
```php
pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
// Errors are sent to New Relic with masked PII
$logger->error('Authentication failed', [
'email' => 'user@example.com',
'ip' => '192.168.1.1',
]);
```
### Custom Attributes
```php
pushProcessor(function ($record) {
if (function_exists('newrelic_add_custom_parameter')) {
newrelic_add_custom_parameter('log_level', $record['level_name']);
newrelic_add_custom_parameter('channel', $record['channel']);
}
return $record;
});
```
## Sentry
### Sentry Handler Integration
```php
'https://key@sentry.io/project']);
$handler = new Handler(Hub::getCurrent());
$logger = new Logger('app');
$logger->pushHandler($handler);
// IMPORTANT: Add GDPR processor BEFORE Sentry handler processes
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
$logger->error('Payment failed', [
'user_email' => 'customer@example.com',
'card_number' => '4111111111111111',
]);
```
### Sentry Breadcrumbs
```php
pushProcessor(function ($record) {
\Sentry\addBreadcrumb(new Breadcrumb(
Breadcrumb::LEVEL_INFO,
Breadcrumb::TYPE_DEFAULT,
$record['channel'],
$record['message'], // Already masked by GDPR processor
$record['context'] // Already masked
));
return $record;
});
```
## Papertrail
### Papertrail Handler Integration
```php
setFormatter($formatter);
$logger = new Logger('my-app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
```
## Loggly
### Loggly Handler Integration
```php
pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
$logger->info('User registered', [
'email' => 'newuser@example.com',
'phone' => '+1-555-123-4567',
]);
```
## AWS CloudWatch
### CloudWatch Handler Integration
```php
'us-east-1',
'version' => 'latest',
]);
$handler = new CloudWatch(
$client,
'app-log-group',
'app-log-stream',
retentionDays: 14
);
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
$logger->info('API request', [
'user_email' => 'api-user@example.com',
'endpoint' => '/api/v1/users',
]);
```
### CloudWatch with Laravel
```php
[
'cloudwatch' => [
'driver' => 'custom',
'via' => App\Logging\CloudWatchLoggerFactory::class,
'retention' => 14,
'group' => env('CLOUDWATCH_LOG_GROUP', 'laravel'),
'stream' => env('CLOUDWATCH_LOG_STREAM', 'app'),
],
],
];
```
```php
config('services.aws.region'),
'version' => 'latest',
]);
$handler = new CloudWatch(
$client,
$config['group'],
$config['stream'],
$config['retention']
);
$logger = new Logger('cloudwatch');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
return $logger;
}
}
```
## Google Cloud Logging
### Google Cloud Handler Integration
```php
'your-project-id',
]);
$psrLogger = $logging->psrLogger('app-logs');
// Wrap in Monolog for processor support
$monologLogger = new Logger('app');
$monologLogger->pushHandler(new \Monolog\Handler\PsrHandler($psrLogger));
$monologLogger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
$monologLogger->info('User action', [
'email' => 'user@example.com',
'action' => 'login',
]);
```
## Fluentd/Fluent Bit
### Fluentd Integration
```php
setFormatter(new JsonFormatter());
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
// Add Fluentd tag
$logger->pushProcessor(function ($record) {
$record['extra']['fluent_tag'] = 'app.logs';
return $record;
});
```
Fluentd configuration:
```ruby
@type forward
port 24224
@type elasticsearch
host elasticsearch
port 9200
index_name app-logs
```
### Fluent Bit with File Tail
```php
setFormatter(new JsonFormatter());
$logger = new Logger('app');
$logger->pushHandler($handler);
$logger->pushProcessor(new GdprProcessor(DefaultPatterns::all()));
```
Fluent Bit configuration:
```ini
[INPUT]
Name tail
Path /var/log/app/*.json.log
Parser json
[OUTPUT]
Name es
Host elasticsearch
Port 9200
Index app-logs
```
## Best Practices
### 1. Always Process Before Sending
Ensure the GDPR processor runs before logs leave your application:
```php
pushHandler($externalHandler);
$logger->pushProcessor(new GdprProcessor($patterns)); // Runs before handlers
```
### 2. Add Compliance Metadata
```php
pushProcessor(function ($record) {
$record['extra']['gdpr'] = [
'processed' => true,
'processor_version' => '3.0.0',
'timestamp' => date('c'),
];
return $record;
});
```
### 3. Monitor for Leaks
Set up alerts in your logging platform for unmasked PII patterns:
```json
{
"query": {
"regexp": {
"message": "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
}
}
}
```
### 4. Retention Policies
Configure retention aligned with GDPR requirements:
- Most platforms support automatic log deletion
- Set retention to 30 days for most operational logs
- Archive critical audit logs separately with longer retention