Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoray committed Jan 16, 2025
1 parent f4f8c56 commit 855ed33
Show file tree
Hide file tree
Showing 20 changed files with 287 additions and 857 deletions.
37 changes: 5 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,47 +107,20 @@ Deduplication and buffering are enabled by default to enhance logging. Customize

### Deduplication

Group similar errors to avoid duplicate issues. By default, the package uses file-based storage. Customize the storage and time window to fit your application.
Group similar errors to avoid duplicate issues. The package uses Laravel's cache system for deduplication storage.

```php
'github' => [
// ... basic config from above ...
'deduplication' => [
'store' => 'file', // Default store
'time' => 60, // Time window in seconds
'time' => 60, // Time window in seconds - how long to wait before creating a new issue
'store' => null, // Uses your default cache store (from cache.default)
'prefix' => 'dedup', // Prefix for cache keys
],
]
```

#### Alternative Storage Options

Consider other storage options in these Laravel-specific scenarios:

- **Redis Store**: Use when:
- Running async queue jobs (file storage won't work across processes)
- Using Laravel Horizon for queue management
- Running multiple application instances behind a load balancer

```php
'deduplication' => [
'store' => 'redis',
'prefix' => 'github-monolog:',
'connection' => 'default', // Uses your Laravel Redis connection
],
```

- **Database Store**: Use when:
- Running queue jobs but Redis isn't available
- Need to persist deduplication data across deployments
- Want to query/debug deduplication history via database

```php
'deduplication' => [
'store' => 'database',
'table' => 'github_monolog_deduplication',
'connection' => null, // Uses your default database connection
],
```
For cache store configuration, refer to the [Laravel Cache documentation](https://laravel.com/docs/cache).

### Buffering

Expand Down
89 changes: 89 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Upgrade Guide

## Upgrading from 2.x to 3.0

### Breaking Changes

Version 3.0 introduces several breaking changes in how deduplication storage is handled:

1. **Removed Custom Store Implementations**
- FileStore, RedisStore, and DatabaseStore have been removed
- All deduplication storage now uses Laravel's cache system

2. **Configuration Changes**
- Store-specific configuration options have been removed
- New simplified cache-based configuration

### Migration Steps

1. **Update Package**
```bash
composer require naoray/laravel-github-monolog:^3.0
```

2. **Run Cleanup**
- Keep your old configuration in place
- Run the cleanup code above to remove old storage artifacts
- The cleanup code needs your old configuration to know what to clean up

3. **Update Configuration**
- Migrate to new store-specific configuration
- Add new cache-based configuration
- Configure Laravel cache as needed

### Configuration Updates

#### Before (2.x)
- [ ] ```php
'deduplication' => [
'store' => 'redis', // or 'file', 'database'
'connection' => 'default', // Redis/Database connection
'prefix' => 'github-monolog:', // Redis prefix
'table' => 'github_monolog_deduplication', // Database table
'time' => 60,
],
```

#### After (3.0)
```php
'deduplication' => [
'store' => null, // (optional) Uses Laravel's default cache store
'time' => 60, // Time window in seconds
'prefix' => 'dedup', // Cache key prefix
],
```

### Cleanup Code

Before updating your configuration to the new format, you should clean up artifacts from the 2.x version. The cleanup code uses your existing configuration to find and remove old storage:

```php
use Illuminate\Support\Facades\{Schema, Redis, File, DB};

// Get your current config
$config = config('logging.channels.github.deduplication', []);
$store = $config['store'] ?? 'file';

if ($store === 'database') {
// Clean up database table using your configured connection and table name
$connection = $config['connection'] ?? config('database.default');
$table = $config['table'] ?? 'github_monolog_deduplication';

Schema::connection($connection)->dropIfExists($table);
}

if ($store === 'redis') {
// Clean up Redis entries using your configured connection and prefix
$connection = $config['connection'] ?? 'default';
$prefix = $config['prefix'] ?? 'github-monolog:';
Redis::connection($connection)->del($prefix . 'dedup');
}

if ($store === 'file') {
// Clean up file storage using your configured path
$path = $config['path'] ?? storage_path('logs/github-monolog-deduplication.log');
if (File::exists($path)) {
File::delete($path);
}
}
```
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
"illuminate/http": "^11.0",
"illuminate/support": "^11.0",
"illuminate/filesystem": "^11.0",
"monolog/monolog": "^3.6"
"illuminate/cache": "^11.0",
"monolog/monolog": "^3.6",
"laravel/prompts": "^0.3.3"
},
"require-dev": {
"laravel/pint": "^1.14",
Expand Down
65 changes: 65 additions & 0 deletions src/Deduplication/CacheManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace Naoray\LaravelGithubMonolog\Deduplication;

use Illuminate\Contracts\Cache\Repository;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;

class CacheManager
{
private const KEY_PREFIX = 'github-monolog';
private const KEY_SEPARATOR = ':';

private readonly string $store;
private readonly Repository $cache;

public function __construct(
?string $store = null,
private readonly string $prefix = 'dedup',
private readonly int $ttl = 60
) {
$this->store = $store ?? config('cache.default');
$this->cache = Cache::store($this->store);
}

public function has(string $signature): bool
{
return $this->cache->has($this->composeKey($signature));
}

public function add(string $signature): void
{
$this->cache->put(
$this->composeKey($signature),
Carbon::now()->timestamp,
$this->ttl
);
}

/**
* Clear all entries for the current prefix.
* Note: This is a best-effort operation and might not work with all cache stores.
*/
public function clear(): void
{
// For Redis/Memcached stores that support tag-like operations
if (method_exists($this->cache->getStore(), 'flush')) {
$this->cache->getStore()->flush();
return;
}

// For other stores, we'll have to rely on TTL cleanup
// You might want to implement a more specific cleanup strategy
// based on your cache store if needed
}

private function composeKey(string $signature): string
{
return implode(self::KEY_SEPARATOR, [
self::KEY_PREFIX,
$this->prefix,
$signature,
]);
}
}
17 changes: 11 additions & 6 deletions src/Deduplication/DeduplicationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
use Monolog\Handler\HandlerInterface;
use Monolog\Level;
use Monolog\LogRecord;
use Naoray\LaravelGithubMonolog\Deduplication\Stores\StoreInterface;

class DeduplicationHandler extends BufferHandler
{
private CacheManager $cache;

public function __construct(
HandlerInterface $handler,
protected StoreInterface $store,
protected SignatureGeneratorInterface $signatureGenerator,
string $store = 'default',
string $prefix = 'github-monolog:dedup:',
int $ttl = 60,
int|string|Level $level = Level::Error,
int $bufferLimit = 0,
bool $bubble = true,
Expand All @@ -27,6 +30,8 @@ public function __construct(
bubble: $bubble,
flushOnOverflow: $flushOnOverflow,
);

$this->cache = new CacheManager($store, $prefix, $ttl);
}

public function flush(): void
Expand All @@ -42,17 +47,17 @@ public function flush(): void
// Create new record with signature in extra data
$record = $record->with(extra: ['github_issue_signature' => $signature] + $record->extra);

// If the record is a duplicate, we don't want to add it to the store
if ($this->store->isDuplicate($record, $signature)) {
// If the record is a duplicate, we don't want to process it
if ($this->cache->has($signature)) {
return null;
}

$this->store->add($record, $signature);
$this->cache->add($signature);

return $record;
})
->filter()
->pipe(fn (Collection $records) => $this->handler->handleBatch($records->toArray()));
->pipe(fn(Collection $records) => $this->handler->handleBatch($records->toArray()));

$this->clear();
}
Expand Down
53 changes: 0 additions & 53 deletions src/Deduplication/Stores/AbstractStore.php

This file was deleted.

69 changes: 0 additions & 69 deletions src/Deduplication/Stores/DatabaseStore.php

This file was deleted.

Loading

0 comments on commit 855ed33

Please sign in to comment.