Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pecs Laravel Package

hamidrezaniazi/pecs

PECS is a Laravel/PHP package that makes PHP enums easier to work with by adding collection-style helpers. Build typed enum collections from cases, then filter, map, sort, and chain operations with a familiar fluent API for cleaner, type-safe code.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the package:

    composer require hamidrezaniazi/pecs
    
  2. Publish and review the config (Laravel). If the service provider auto-registers, the config is tagged pecs:

    php artisan vendor:publish --provider="Hamidrezaniazi\Pecs\PecsServiceProvider"
    

    Look first at config/pecs.php and the source under src/ — specifically the formatter class and any service provider. That is where the ECS fields, defaults (service name, host, log level mapping), and extension points live.

  3. Wire it into a logging channel in config/logging.php. The package is fundamentally a Monolog formatter — you plug it into a channel rather than replacing Laravel's logging API:

    'ecs' => [
        'driver'  => 'daily',
        'path'    => storage_path('logs/laravel.log'),
        'level'   => env('LOG_LEVEL', 'debug'),
        'days'    => 14,
        'formatter' => \Hamidrezaniazi\Pecs\Formatters\PecsFormatter::class,
    ],
    

    Then set LOG_CHANNEL=ecs in .env.

  4. First use case: point that channel at a log file you ship to Elasticsearch/Logstash (via Filebeat) and confirm documents land in Kibana with the @timestamp, log.level, message, and service.name fields populated. For a low-traffic app, the quickest sanity check is to Log::info('hello', ['user.id' => 42]) and inspect the JSON line in storage/logs/laravel.log before touching an ingest pipeline.

Given the package's minimal surface area and low adoption, treat reading the formatter source as step zero — do not configure blind.

Implementation Patterns

Formatter-on-existing-driver (recommended). Keep Laravel's single/daily/stack drivers and just swap the formatter. You retain rotation, permissions, and tap support, and only the line format changes. This is the lowest-risk integration.

'channels' => [
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['ecs'],
    ],
    'ecs' => [
        'driver'    => 'daily',
        'path'      => storage_path('logs/laravel.log'),
        'formatter' => \Hamidrezaniazi\Pecs\Formatters\PecsFormatter::class,
        'formatter_with' => [
            // pass ECS-relevant defaults shown in the config file
        ],
    ],
],

Structured context, ECS-shaped. The formatter's value is that the fields you already pass to Log::info() get emitted under ECS-compatible names. Train the team to log context explicitly:

Log::info('Order captured', [
    'event.action'      => 'order.capture',
    'user.id'           => $user->id,
    'http.request.method' => request()->method(),
    'url.path'          => request()->path(),
    'labels.order_id'   => $order->id,
]);

Prefer ECS dotted paths over ad-hoc keys so Kibana dashboards and ILM rules actually match across services.

Separate channel for local vs. production. Keep human-readable daily in local and reserve the ECS channel for environments that ship to Elastic. Use the stack driver to fan out to both, or gate with LOG_CHANNEL per environment — this avoids paying the JSON/serialization cost in tinker and tests.

Request-scoped enrichment via middleware or Log::withContext. Rather than repeating service.version, host.name, trace.id in every call, set them once:

// AppServiceProvider::boot() or a middleware
Log::withContext([
    'service.name'    => config('app.name'),
    'service.version' => config('app.version'),
    'trace.id'        => $traceId,
]);

This is the idiomatic way to add ECS fields that are constant per request without editing the package.

Custom processors for fields the formatter doesn't know about. If ECS keys you need aren't first-class, add a Monolog processor to the channel:

'ecs' => [
    // ...
    'tap' => [App\Logging\EcsEnricher::class],
],

EcsEnricher::__invoke($logger) can call $logger->pushProcessor(fn ($record) => ...) to inject ecs.version, agent.*, or deployment metadata.

Exception handling expectation. ECS defines error.* fields. If the package's formatter doesn't render exceptions into those keys, capture exceptions yourself by passing 'error.message' => $e->getMessage(), 'error.stack_trace' => $e->getTraceAsString() to Log::error() — or add a processor. Verify this before relying on it in production.

Gotchas and Tips

  • This is a very small package (32 stars, single maintainer). Pin the exact version in composer.json ("hamidrezaniazi/pecs": "x.y.z") and be prepared to fork if a Laravel/Monolog major bump breaks it. Budget a smoke test after every Laravel upgrade. Do not depend on it for anything that cannot be swapped out in an afternoon — the formatter is the whole value proposition.

  • It is a formatter, not a shipping pipeline. PECS gives you ECS-shaped JSON lines; it does not ship them to Elasticsearch. You still need Filebeat/Fluent Bit/Logstash or a direct ES handler. Don't expect it to replace elastic-php or a shipper.

  • ECS is strict about field names and types. log.level must be a valid ECS level, @timestamp follows RFC 3339 with a specific precision, http.response.status_code is an integer — not a string. If you pass ['status_code' => '200'] you'll get ingested documents that Kibana's out-of-the-box dashboards ignore. Sanity check types in the raw JSON, not just in the UI.

  • @timestamp vs. Laravel's datetime. Laravel's default line format includes a datetime field. ECS-compliant pipelines key on @timestamp. Confirm the formatter emits @timestamp and that your ingest pipeline doesn't drop or double-count the record. If both exist, decide which one you actually filter on.

  • Don't assume the default config is production-ready. The published config likely contains placeholder service.name, host.name, or a hardcoded environment. Always override with env('APP_NAME'), gethostname(), and env('APP_ENV') respectively, or your Kibana service.name facet will be a single bucket called "pecs".

  • JSON-encoded logs are larger and slower to write. For high-throughput apps, benchmark the formatter against Laravel's default line formatter. If logging is a hot path, consider async shipping (Filebeat filestream input) rather than synchronous writes to a network share.

  • Extension points to check first if something's missing: (a) the formatter's constructor/formatter_with options; (b) whether the service provider publishes or binds a PecsFormatter singleton you can decorate; (c) Monolog pushProcessor on the channel. In that order — least invasive first.

  • Debugging a "fields are missing" report: log one line, cat it, and diff against the ECS field reference (https://www.elastic.co/guide/en/ecs/current/). Compare what the formatter emits vs. what your ingest pipeline expects. Nine times out of ten it's a mismatch between the log context keys the developer passed and the ECS dotted path the pipeline parses — not a bug in the formatter.

  • Testing strategy: add a unit test that asserts a single log line round-trips through json_decode and contains the required ECS keys (@timestamp, message, log.level, service.name). Keep it in CI so a Laravel/Monolog bump surfaces regressions immediately rather than after a Kibana dashboard goes blank.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels