PHP code example of prahsys / laravel-api-logs

1. Go to this page and download the library: Download prahsys/laravel-api-logs library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

prahsys / laravel-api-logs example snippets


'channels' => [
    // Raw logs - restricted access, complete data
    'api_logs_raw' => [
        'driver' => 'daily',
        'path' => storage_path('logs/api_logs_raw.log'),
        'level' => 'info',
        'days' => 14,
        'permission' => 0600, // Restricted access
    ],
    
    // Redacted logs - general monitoring and analytics
    'api_logs_redacted' => [
        'driver' => 'daily',
        'path' => storage_path('logs/api_logs_redacted.log'),
        'level' => 'info',
        'days' => 90,
    ],
    
    // External monitoring services with tailored redaction
    'api_logs_sentry' => [
        'driver' => 'sentry',
        'level' => 'error',
        'bubble' => true,
    ],
    
    'api_logs_axiom' => [
        'driver' => 'custom',
        'via' => App\Logging\AxiomLogger::class,
        'level' => 'info',
        'dataset' => 'api_logs',
    ],
    
    // Stack multiple channels for comprehensive monitoring
    'api_logs_monitoring' => [
        'driver' => 'stack',
        'channels' => ['api_logs_redacted', 'api_logs_sentry'],
        'ignore_exceptions' => false,
    ],
],

protected $middlewareGroups = [
    'api' => [
        // ... other middleware
        \Prahsys\ApiLogs\Http\Middleware\ApiLogMiddleware::class,
    ],
];

$response = Http::withHeaders([
    'Idempotency-Key' => 'unique-key-123',
])->post('/api/users', ['name' => 'John Doe']);

use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use Prahsys\ApiLogs\Http\Middleware\GuzzleApiLogMiddleware;

$stack = HandlerStack::create();
$stack->push(app(GuzzleApiLogMiddleware::class));

$client = new Client([
    'handler' => $stack,
    'base_uri' => 'https://api.example.com',
    'timeout' => 30,
]);

// Get your existing handler stack
$stack = $existingClient->getConfig('handler');

// Add API logging middleware
$stack->push(app(GuzzleApiLogMiddleware::class));

// Skip logging by adding request option
$response = $client->get('/status', [
    'prahsys_api_logs_skip' => true
]);

'outbound' => [
    'enabled' => true,
    'exclude_hosts' => [
        'localhost',
        '*.internal.company.com',
        'monitoring.example.com',
    ],
],

use Prahsys\ApiLogs\Models\HasApiLogItems;

class User extends Model
{
    use HasApiLogItems;
    
    // ... model code
}

// Get all API requests for a model
$user = User::find(1);
$requests = $user->apiLogItems;

// Get the latest API request for a model
$latestRequest = $user->latestApiLogItem();

// Get all models associated with an API request
$apiLogItem = ApiLogItem::where('request_id', $requestId)->first();
$users = $apiLogItem->getRelatedModels(User::class)->get();

// Example: Track all models affected by a single API request
$apiLogItem = ApiLogItem::where('request_id', 'abc-123-def')->first();

// Get all users modified in this request
$affectedUsers = $apiLogItem->getRelatedModels(User::class)->get();

// Get all orders created/updated in this request  
$affectedOrders = $apiLogItem->getRelatedModels(Order::class)->get();

// Get all affected models regardless of type
$allAffectedModels = $apiLogItem->relatedModels; // Returns collection of all associated models

// Example output for debugging or audit purposes
foreach ($allAffectedModels as $model) {
    echo "Modified {$model->getMorphClass()}: ID {$model->id}";
}

'channels' => [
    // Raw logs - no redaction for internal secure storage
    'api_logs_raw' => [],
    
    // General monitoring - basic redaction for security
    'api_logs_redacted' => [
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
    ],
    
    // External monitoring services - tailored redaction
    'api_logs_sentry' => [
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
            'paths' => ['**.email', '**.phone', '**.ssn'],
        ],
    ],
    
    'api_logs_axiom' => [
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
            'paths' => ['request.body.internal_id', 'response.body.debug_info'],
        ],
    ],
],

  'users.*.email' // Matches users.1.email, users.john.email, etc.
  

  '**.card.number' // Matches card.number anywhere in the data structure
  '**.password'    // Matches password fields at any depth
  

// Traditional specific paths
\Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
    'paths' => ['request.body.users.0.password', 'request.body.users.1.password'],
]

// Using single wildcards  
\Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
    'paths' => ['request.body.users.*.password'],
]

// Using deep wildcards for complex nested data
\Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
    'paths' => ['**.password', '**.card.number', '**.ssn'],
]

// Create custom model
class CustomApiLogItem extends \Prahsys\ApiLogs\Models\ApiLogItem
{
    protected $fillable = [
        // Default fields
        'request_id', 'path', 'method', 'api_version', 
        'request_at', 'response_at', 'response_status', 'is_error',
        
        // Custom fields
        'request_payload', 'response_payload', 'user_id', 'client_ip'
    ];
    
    protected $casts = [
        // Default casts
        'request_at' => 'datetime:Y-m-d H:i:s.v',
        'response_at' => 'datetime:Y-m-d H:i:s.v',
        'response_status' => 'integer',
        'is_error' => 'boolean',
        
        // Custom casts
        'request_payload' => 'json',
        'response_payload' => 'json',
    ];
}

// Create custom migration
Schema::table('api_log_items', function (Blueprint $table) {
    $table->json('request_payload')->nullable();
    $table->json('response_payload')->nullable();
    $table->string('user_id')->nullable();
    $table->string('client_ip')->nullable();
});

// Update config
'models' => [
    'api_log_item' => \App\Models\CustomApiLogItem::class,
],



namespace App\Redactors;

use Prahsys\ApiLogs\Redactors\DotNotationRedactor;

class PciRedactor extends DotNotationRedactor
{
    public function __construct(array $additionalPaths = [], string|\Closure $replacement = '[REDACTED]')
    {
        $pciPaths = [
            // Credit card numbers
            '**.card.number',
            '**.card_number',
            '**.cc_number',
            
            // CVV codes
            '**.card.cvv',
            '**.card.cvc',
            '**.cvv',
            '**.cvc',
            
            // Expiry dates
            '**.card.expiry',
            '**.card.exp_month',
            '**.card.exp_year',
            
            // Track data
            '**.track1',
            '**.track2',
            '**.magnetic_stripe',
        ];

        parent::__construct(
            array_merge($pciPaths, $additionalPaths),
            $replacement
        );
    }
}



namespace App\Redactors;

use Prahsys\ApiLogs\Redactors\DotNotationRedactor;

class HipaaRedactor extends DotNotationRedactor
{
    public function __construct(array $additionalPaths = [], string|\Closure $replacement = '[REDACTED]')
    {
        $hipaaPaths = [
            // Patient identifiers
            '**.patient.ssn',
            '**.patient.medical_record_number',
            '**.patient.account_number',
            '**.patient.insurance_id',
            
            // Biometric data
            '**.biometric',
            '**.fingerprint',
            '**.voice_print',
            
            // Health information
            '**.diagnosis',
            '**.medical_condition',
            '**.treatment',
            '**.medication',
            
            // Deep wildcard patterns for nested patient data
            '**.patient.**.personal_id',
            '**.health_record.**',
        ];

        parent::__construct(
            array_merge($hipaaPaths, $additionalPaths),
            $replacement
        );
    }
}



namespace App\Redactors;

use Prahsys\ApiLogs\Redactors\DotNotationRedactor;

class PiiRedactor extends DotNotationRedactor
{
    public function __construct(array $additionalPaths = [], string|\Closure $replacement = '[REDACTED]')
    {
        $piiPaths = [
            // Personal identifiers
            '**.ssn',
            '**.social_security_number',
            '**.sin',
            '**.national_id',
            '**.passport_number',
            '**.drivers_license',
            
            // Contact information
            '**.email',
            '**.phone',
            '**.phone_number',
            '**.mobile',
            '**.address',
            '**.street_address',
            '**.postal_code',
            '**.zip_code',
            
            // Financial information
            '**.bank_account',
            '**.routing_number',
            '**.iban',
            '**.account_number',
            
            // Deep patterns for user objects
            '**.user.email',
            '**.user.phone',
            '**.users.*.email',
            '**.users.*.phone',
        ];

        parent::__construct(
            array_merge($piiPaths, $additionalPaths),
            $replacement
        );
    }
}



namespace App\Redactors;

use Prahsys\ApiLogs\Redactors\DotNotationRedactor;

class SmartRedactor extends DotNotationRedactor
{
    public function __construct()
    {
        $paths = ['**.card.number', '**.email'];
        
        $customReplacement = function ($value, $path) {
            if (str_contains($path, 'card.number')) {
                // Show only last 4 digits of card numbers
                return '****-****-****-' . substr($value, -4);
            }
            
            if (str_contains($path, 'email')) {
                // Partially redact email addresses
                [$local, $domain] = explode('@', $value);
                return substr($local, 0, 2) . '***@' . $domain;
            }
            
            return '[REDACTED]';
        };

        parent::__construct($paths, $customReplacement);
    }
}

// config/api-logs.php
'channels' => [
    'api_logs_pci_compliant' => [
        \App\Redactors\PciRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
    ],
    
    'api_logs_healthcare' => [
        \App\Redactors\HipaaRedactor::class,
        \App\Redactors\PiiRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
    ],
],

use Prahsys\ApiLogs\Events\CompleteApiLogItemEvent;

// In your EventServiceProvider
protected $listen = [
    CompleteApiLogItemEvent::class => [
        YourCustomListener::class,
    ],
];

// config/prahsys-api-logs.php
'channels' => [
    'api_logs_sentry' => [
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
        \App\Redactors\PiiRedactor::class, // Custom PII redactor
    ],
],

// config/logging.php
'api_logs_sentry' => [
    'driver' => 'sentry',
    'level' => 'error',
    'bubble' => true,
],

// Custom logger for Axiom
class AxiomLogger
{
    public function __invoke(array $config)
    {
        return new AxiomHandler($config['dataset']);
    }
}

// Channel configuration with Axiom-specific redaction
'api_logs_axiom' => [
    \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
    \Prahsys\ApiLogs\Redactors\DotNotationRedactor::class => [
        'paths' => ['request.body.internal_metrics'],
    ],
],

// config/logging.php
'api_logs_raw' => [
    'driver' => 'daily',
    'path' => storage_path('logs/api_logs_raw.log'),
    'days' => 14, // Rotate log files every 14 days
],

'api_logs_redacted' => [
    'driver' => 'daily', 
    'days' => 90, // Keep redacted logs longer for analytics
],

// Enhanced channel configuration for PCI environments
'channels' => [
    'api_logs_pci_raw' => [
        \App\Redactors\PciRedactor::class, // Custom PCI redactor
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
    ],
    
    'api_logs_pci_monitoring' => [
        \App\Redactors\PciRedactor::class, // Custom PCI redactor
        \Prahsys\ApiLogs\Redactors\CommonHeaderFieldsRedactor::class,
        \Prahsys\ApiLogs\Redactors\CommonBodyFieldsRedactor::class,
    ],
],

// Logging channel with appropriate retention
// config/logging.php
'api_logs_pci_raw' => [
    'driver' => 'daily',
    'path' => storage_path('logs/pci/api_logs_raw.log'),
    'level' => 'info',
    'days' => 365, // Extended retention for audit 

// SIEM integration for SOC 2 ls' => [
    'api_logs_soc2' => [
        'driver' => 'stack',
        'channels' => ['syslog', 'siem_service'],
        'ignore_exceptions' => false,
    ],
    
    'syslog' => [
        'driver' => 'syslog',
        'level' => 'info',
        'facility' => LOG_USER,
    ],
],

// Example retention configuration
// config/logging.php
'api_logs_compliance' => [
    'driver' => 'daily',
    'path' => storage_path('logs/compliance/api_logs.log'),
    'days' => 2555, // Extended retention as needed
    'permission' => 0600,
],
bash
php artisan vendor:publish --provider="Prahsys\ApiLogs\ApiLogsServiceProvider"
php artisan migrate
bash
# Run model pruning manually
php artisan model:prune

# Schedule in your app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    $schedule->command('model:prune')->daily();
}
env
# Retain database references for 1 year (default)
API_LOGS_TTL_HOURS=8760

# Or configure in config file
'database' => [
    'pruning' => [
        'ttl_hours' => 24 * 365, // 365 days
    ],
],