Initial commit
This commit is contained in:
commit
6f4cc23526
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "okawari/job-logging",
|
||||
"description": "Simple dependency for logging information about jobs",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"illuminate/support": "^11.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Okawari\\JobLogging\\": "src/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Tommy Stigen Olsen",
|
||||
"email": "tommysolsen@gmail.com"
|
||||
}
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="Okawari\JobLogging" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/vendor" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace Okawari\JobLogging;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
|
||||
/**
|
||||
* App\Models\JobLog
|
||||
*
|
||||
* @property int $id
|
||||
* @property string|null $job_id
|
||||
* @property string $class
|
||||
* @property string $name
|
||||
* @property string|null $owner_type
|
||||
* @property int|null $owner_id
|
||||
* @property bool|null $success
|
||||
* @property string $output
|
||||
* @property \Illuminate\Support\Carbon|null $started_at
|
||||
* @property \Illuminate\Support\Carbon|null $ended_at
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
* @property-read Model|\Eloquent $owner
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog newModelQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog newQuery()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog query()
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereClass($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereCreatedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereEndedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereJobId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereName($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereOutput($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereOwnerId($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereOwnerType($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereStartedAt($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereSuccess($value)
|
||||
* @method static \Illuminate\Database\Eloquent\Builder|JobLog whereUpdatedAt($value)
|
||||
* @mixin \Eloquent
|
||||
*/
|
||||
class JobLog extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $casts = [
|
||||
'started_at' => 'datetime',
|
||||
'ended_at' => 'datetime',
|
||||
];
|
||||
protected $fillable = [
|
||||
'job_id',
|
||||
'class',
|
||||
'name',
|
||||
'owner_type',
|
||||
'owner_id',
|
||||
'output',
|
||||
'started_at',
|
||||
'ended_at',
|
||||
'success'
|
||||
];
|
||||
|
||||
public function owner(): MorphTo {
|
||||
return $this->morphTo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace Okawari\JobLogging;
|
||||
|
||||
use App\Contracts\NamedJob;
|
||||
use App\Contracts\OwnedJob;
|
||||
use App\Models\JobLog;
|
||||
use App\Services\JobLogger;
|
||||
use Illuminate\Queue\Events\JobFailed;
|
||||
use Illuminate\Queue\Events\JobProcessed;
|
||||
use Illuminate\Queue\Events\JobProcessing;
|
||||
use Illuminate\Queue\Jobs\SyncJob;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class JobLogProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
|
||||
$driver = Log::getDefaultDriver();
|
||||
|
||||
Event::listen(function (JobProcessing $event) {
|
||||
/** @var \Monolog\Logger $logger */
|
||||
$logger = Log::getLogger();
|
||||
|
||||
$job = $event->job;
|
||||
$owner = $job instanceof OwnedJob ? $job->getOwner() : null;
|
||||
$name = $job instanceof NamedJob ? $job->getJobLogName() : $event->job->getName();
|
||||
|
||||
if ($job instanceof SyncJob) {
|
||||
$job = unserialize(data_get(json_decode($job->getRawBody()), 'data.command'));
|
||||
$owner = $job instanceof OwnedJob ? $job->getOwner() : $owner;
|
||||
$name = $job instanceof NamedJob ? $job->getJobLogName() : $name;
|
||||
}
|
||||
|
||||
$jobLog = app(JobLog::class)::create([
|
||||
'job_id' => $event->job->getJobId() ?: '',
|
||||
'class' => get_class($event->job),
|
||||
'name' => $name,
|
||||
'owner_type' => $owner ? get_class($owner) : null,
|
||||
'owner_id' => $owner?->id,
|
||||
'output' => '',
|
||||
'started_at' => now(),
|
||||
]);
|
||||
|
||||
$logger->pushProcessor(new JobLogger($jobLog));
|
||||
});
|
||||
|
||||
Event::listen(function (JobFailed $event) {
|
||||
/** @var \Monolog\Logger $logger */
|
||||
$jobLogger = $this->getJobLogger();
|
||||
|
||||
if (!$jobLogger) {
|
||||
return;
|
||||
}
|
||||
|
||||
$job = $event->job;
|
||||
$logLine = $jobLogger->log;
|
||||
$owner = $job instanceof OwnedJob ? $job->getOwner() : null;
|
||||
$name = $job instanceof NamedJob ? $job->getJobLogName() : $event->job->getName();
|
||||
if ($owner) $logLine->owner()->associate($owner);
|
||||
if ($name) $logLine->name = $name ?: $logLine->name;
|
||||
|
||||
$logLine->output .= "[EXCEPTION] " . now()->toIso8601ZuluString() . ": {$event->exception->getMessage()}";
|
||||
$success = $event->job?->hasFailed() === false;
|
||||
$logLine->success = $success;
|
||||
$logLine->ended_at = now();
|
||||
$logLine->save();
|
||||
});
|
||||
|
||||
Event::listen(function (JobProcessed|JobFailed $event) {
|
||||
try {
|
||||
/** @var \Monolog\Logger $logger */
|
||||
$jobLogger = $this->getJobLogger();
|
||||
if (!$jobLogger) {
|
||||
return;
|
||||
}
|
||||
|
||||
$job = $event->job;
|
||||
$logLine = $jobLogger->log;
|
||||
|
||||
$owner = $job instanceof OwnedJob ? $job->getOwner() : null;
|
||||
$name = $job instanceof NamedJob ? $job->getJobLogName() : $event->job->getName();
|
||||
if ($owner) $logLine->owner()->associate($owner);
|
||||
if ($name) $logLine->name = $name ?: $logLine->name;
|
||||
|
||||
$logLine->success = !$event->job->hasFailed();
|
||||
$logLine->ended_at = now();
|
||||
$logLine->save();
|
||||
} catch (\Throwable $t) {
|
||||
dd($t, debug_backtrace());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
function getJobLogger(): ?JobLogger
|
||||
{
|
||||
$logger = Log::driver()->getLogger();
|
||||
$jobLogger = $logger->popProcessor();
|
||||
if ($jobLogger instanceof JobLogger) {
|
||||
return $jobLogger;
|
||||
} else {
|
||||
$logger->pushProcessor($jobLogger);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Okawari\JobLogging;
|
||||
|
||||
use App\Models\JobLog;
|
||||
use Monolog\LogRecord;
|
||||
use Monolog\Processor\ProcessorInterface;
|
||||
|
||||
class JobProcessor implements ProcessorInterface
|
||||
{
|
||||
|
||||
|
||||
public function __construct(public JobLog $log)
|
||||
{
|
||||
}
|
||||
|
||||
public function __invoke(LogRecord $record)
|
||||
{
|
||||
$line = "[{$record->level->getName()}] $record->datetime: $record->message";
|
||||
$this->log->output = "{$this->log->output}$line\r\n";
|
||||
return $record;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue