PHPackages                             konzume/splunk-observability-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. konzume/splunk-observability-sdk

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

konzume/splunk-observability-sdk
================================

Production-grade asynchronous observability SDK for Laravel that ships HTTP, database, exception, queue and custom telemetry to Splunk HEC.

v1.0.2(1mo ago)08MITPHPPHP ^8.3

Since May 26Pushed 1mo agoCompare

[ Source](https://github.com/bhullarap/splunk-observability-sdk)[ Packagist](https://packagist.org/packages/konzume/splunk-observability-sdk)[ RSS](/packages/konzume-splunk-observability-sdk/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (11)Versions (4)Used By (0)

Splunk Observability SDK for Laravel
====================================

[](#splunk-observability-sdk-for-laravel)

A production-grade, fully asynchronous observability SDK for Laravel 13. Captures HTTP requests, database queries, exceptions, queue jobs and custom application events, batches them in-memory, and ships them to Splunk's HTTP Event Collector (HEC) from a queue worker — never on the request thread.

Designed to be a drop-in alternative to Sentry Performance / Datadog APM / New Relic / Bugsnag for teams that already operate Splunk.

Why an async pipeline
---------------------

[](#why-an-async-pipeline)

Telemetry SDKs that synchronously call out to a SaaS during a request can spike p99 latency by hundreds of milliseconds whenever the SaaS slows down or drops a packet. This package guarantees zero impact on response time by:

1. Collecting every signal in an in-memory request-scoped context.
2. Running the heavy serialization + queue dispatch in Laravel's `terminate()` phase — i.e. **after** the response has been sent to the client.
3. Doing all Splunk HTTP I/O on a separate queue worker, with retries and exponential backoff handled by Laravel's queue layer.

Features
--------

[](#features)

- HTTP request lifecycle: method, URL, route, headers, payload, response status/headers/body, IP, user agent, tenant id, authenticated user, duration, memory.
- Database queries via Laravel's `QueryExecuted` event: SQL, optional bindings, execution time, connection, slow-query detection.
- Exceptions: stack traces, exception metadata, request + query context.
- Queue jobs: per-job lifecycle, attempts, duration, failures.
- Application logs: a `splunk` log channel that correlates every line to the request's `trace_id`.
- Outbound HTTP: every call made through Laravel's HTTP client (method, URL, status, duration, sizes).
- Mail: every email sent (subject, recipients, mailer, attachment count).
- Custom events: `Splunk::event()`, `Splunk::metric()`, `Splunk::trace()`.
- Sampling (head-based, deterministic on trace id).
- Sanitization of passwords, tokens, authorization headers, card data.
- Configurable payload truncation, query caps, batch sizes.
- Splunk HEC client with gzip compression, batching, retry classification.
- Pluggable exporter — Splunk HEC today, swap in Datadog, Elastic, Loki, OpenTelemetry or Kafka tomorrow.
- Redis-backed queue with dedicated queue name so observability traffic is isolated from app workloads.

Installation
------------

[](#installation)

```
composer require konzume/splunk-observability-sdk
```

The package auto-discovers — no manual provider registration needed.

Publish the config:

```
php artisan vendor:publish --tag=splunk-observability-config
```

This creates `config/splunk-observability.php`.

Register the middleware (required, Laravel 11+)
-----------------------------------------------

[](#register-the-middleware-required-laravel-11)

The SDK ships a single global middleware that owns the request lifecycle. **You must register it** in `bootstrap/app.php` — auto-discovery alone is not enough on the Laravel 11+ skeleton, and the middleware should run *first* so it wraps every other middleware (including auth, CORS, and exception handling). Use `prepend`:

```
// bootstrap/app.php
use Konzume\SplunkObservability\Middleware\RequestLifecycleMiddleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(/* ... */)
    ->withMiddleware(function (Middleware $middleware): void {
        $middleware->prepend(RequestLifecycleMiddleware::class);
    })
    ->withExceptions(/* ... */)
    ->create();
```

Why `prepend` and not `append`?

- **`prepend`** puts the middleware *first* in the global stack — its `handle()` runs before every other middleware, so the captured duration spans the entire request (auth, body parsing, route dispatch, the controller, everything).
- **`append`** would only measure from the SDK middleware onwards and miss most of the request.

This mirrors how Sentry's tracing, Datadog APM and New Relic install their request span — first in, last out.

Environment variables
---------------------

[](#environment-variables)

Minimum config:

```
SPLUNK_OBS_ENABLED=true
SPLUNK_OBS_EXPORTER=splunk_hec
SPLUNK_OBS_QUEUE_CONNECTION=redis
SPLUNK_OBS_QUEUE_NAME=splunk

SPLUNK_HEC_URL=https://splunk.example.com:8088/services/collector
SPLUNK_HEC_TOKEN=00000000-0000-0000-0000-000000000000
SPLUNK_HEC_INDEX=main
SPLUNK_HEC_SOURCE=laravel
SPLUNK_HEC_SOURCETYPE=_json
SPLUNK_HEC_COMPRESSION=true
SPLUNK_HEC_RETRIES=3
```

For local dev, set `SPLUNK_OBS_EXPORTER=null` to discard everything.

Architecture
------------

[](#architecture)

```
HTTP request
   â†“
RequestLifecycleMiddleware (handle)
   â”œâ”€ ContextRepository.reset() / bootFromHeaders()
   â†“
Application controllers
   â”œâ”€ QueryCollector listens to QueryExecuted
   â”œâ”€ ExceptionCollector hooks Laravel exception handler
   â”œâ”€ Splunk::event() / Splunk::metric() / Splunk::trace()
   â†“
RequestLifecycleMiddleware (terminate, post-response)
   â”œâ”€ Sanitizer + PayloadTruncator
   â”œâ”€ Sampler decision
   â”œâ”€ SplunkManager.flush() â†’ Event[]
   â†“
Queue (Redis, "splunk")
   â†“
ExportObservabilityBatchJob (worker)
   â†“
SplunkHecExporter â†’ SplunkHecClient â†’ Splunk HEC

```

Usage
-----

[](#usage)

Custom events:

```
use Konzume\SplunkObservability\Facades\Splunk;

Splunk::event('payment_completed', [
    'tenant_id' => $tenantId,
    'amount'    => $amount,
    'currency'  => $currency,
]);

Splunk::metric('checkout_time', $durationMs, ['provider' => 'stripe']);

$result = Splunk::trace('payment_flow', function () use ($order) {
    return $paymentGateway->charge($order);
});
```

Setting the tenant / user context manually if you don't use auth:

```
Splunk::setTenantId((string) $request->header('X-Tenant-Id'));
Splunk::setUserId((string) $apiKey->user_id);
```

### Correlated logs (the `splunk` channel)

[](#correlated-logs-the-splunk-channel)

The SDK auto-registers a `splunk` log channel. Anything you write to it is buffered into the current request and shipped — correlated by `trace_id` — alongside the request, its queries, HTTP calls and mail. Search one `trace_id` in Splunk and you see the whole story.

```
use Illuminate\Support\Facades\Log;

Log::channel('splunk')->info('order placed', ['order_id' => $order->id]);
Log::channel('splunk')->error('payment declined', ['gateway' => 'stripe', 'code' => $e->getCode()]);
```

To mirror *every* application log into Splunk, add `splunk` to your stack in `config/logging.php`:

```
'channels' => [
    'stack' => [
        'driver'   => 'stack',
        'channels' => ['single', 'splunk'],
    ],
],
```

Log `context` arrays are run through the same sanitizer as request payloads (so `password`, `token`, etc. are redacted). Levels below `SPLUNK_OBS_LOG_LEVEL` (default `debug`) are dropped.

> Logs are buffered and flushed at the end of the request. A hard fatal (OOM, segfault) before `terminate()` loses the buffer — for guaranteed delivery of a critical line, also write it to a durable channel (file/stderr) via a stack.

### Outbound HTTP capture

[](#outbound-http-capture)

Every call made with Laravel's HTTP client is captured automatically — no code changes:

```
use Illuminate\Support\Facades\Http;

Http::withToken($token)->post('https://api.partner.com/charge', $payload);
// → captured as an http_client event: method, URL (sanitized), status, duration, sizes
```

URLs are always sanitized (userinfo stripped, sensitive query params filtered). Headers and bodies are **off by default** — enable with `SPLUNK_OBS_HTTP_CAPTURE_HEADERS=true` / `SPLUNK_OBS_HTTP_CAPTURE_BODIES=true` only on trusted indexes. The SDK's own export to Splunk uses Guzzle directly, so it is never captured (no recursion).

### Mail capture

[](#mail-capture)

Every email the app sends is captured (subject, recipients, mailer, attachment count — never the body):

```
Mail::to($user)->send(new OrderShipped($order));
// → captured as a mail event
```

Performance impact
------------------

[](#performance-impact)

The middleware's `handle()` phase only resets the context and reads request headers — measured at &lt;0.5ms on a small Laravel API. All heavy work (sanitization, JSON serialization, queue push) happens in `terminate()`, after the client has the response. There is **no** synchronous HTTP I/O on the request thread.

Sampling
--------

[](#sampling)

```
'sampling' => [
    'requests'   => 1.0,   // 100% of requests
    'queries'    => 1.0,
    'exceptions' => 1.0,   // never sample exceptions out
    'queues'     => 1.0,
    'force_sample_on_error'  => true,
    'force_sample_when_slow' => true,
],
```

Sampling is deterministic on the trace id, so a trace that gets sampled in at the request level keeps all its child events.

Documentation
-------------

[](#documentation)

- [Installation](docs/installation.md)
- [Configuration](docs/configuration.md)
- [Kubernetes deployment](docs/kubernetes.md)
- [Redis queue setup](docs/redis-queue.md)
- [Horizon setup](docs/horizon.md)
- [Splunk dashboards](docs/splunk-dashboards.md)
- [Splunk alerts](docs/splunk-alerts.md)

Testing
-------

[](#testing)

```
composer install
vendor/bin/pest
```

Suite layout:

- `tests/Unit/` — sampler, sanitizer, truncator, context, HEC client framing
- `tests/Feature/` — middleware lifecycle, custom events, query collection
- `tests/Integration/` — Splunk downtime, retry classification
- `tests/Queue/` — export job retry semantics
- `tests/Performance/` — throughput smoke tests

Extending — custom exporter
---------------------------

[](#extending--custom-exporter)

Implement [src/Contracts/Exporter.php](src/Contracts/Exporter.php) and bind it:

```
$this->app->singleton(\Konzume\SplunkObservability\Contracts\Exporter::class, MyDatadogExporter::class);
```

The export pipeline is exporter-agnostic — no other code changes are needed.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance89

Actively maintained with recent releases

Popularity5

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 66.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

3

Last Release

57d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/49175089?v=4)[Amritpal Singh](/maintainers/bhullarap)[@bhullarap](https://github.com/bhullarap)

---

Top Contributors

[![bvd-amritpal](https://avatars.githubusercontent.com/u/131275036?v=4)](https://github.com/bvd-amritpal "bvd-amritpal (4 commits)")[![bhullarap](https://avatars.githubusercontent.com/u/49175089?v=4)](https://github.com/bhullarap "bhullarap (2 commits)")

---

Tags

laravelapmtracingtelemetryobservabilitysplunkhec

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/konzume-splunk-observability-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/konzume-splunk-observability-sdk/health.svg)](https://phpackages.com/packages/konzume-splunk-observability-sdk)
```

###  Alternatives

[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9762.4M133](/packages/roots-acorn)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k95.4M321](/packages/laravel-horizon)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[simplestats-io/laravel-client

Server-side analytics for Laravel that follows the full funnel from visit to registration to payment, attributed to the channel that drove it. Revenue, MRR, churn and ad-spend profit (ROAS/CAC) per channel. GDPR compliant, ad-blocker proof.

5022.6k](/packages/simplestats-io-laravel-client)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1235.9k21](/packages/fleetbase-core-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
