Search by

tiny-owl-kit / observability

Regis011

TinyOwl PHP SDK — lightweight observability and event logging with enterprise-grade HMAC-SHA256 security

Package info

github.com/tiny-owl-kit/tiny-owl-php

Homepage

pkg:composer/tiny-owl-kit/observability

Statistics

Installs: 6

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.3.0 2026-11-02 20:28 UTC

This package is auto-updated.

Last update: 2026-11-02 20:28:56 UTC


README

Packagist PHP License: MIT

Official PHP SDK for TinyOwl — lightweight observability and event logging with enterprise-grade HMAC-SHA256 security.

Installation

composer require tiny-owl-kit/observability

Quick start

use TinyOwl\Observability\TinyOwl;

$client = new TinyOwl([
    'apiKey'        => getenv('TINYOWL_API_KEY'),
    'projectSecret' => getenv('TINYOWL_PROJECT_SECRET'),
]);

$client->info('App started', ['version' => '1.0.0']);
$client->warning('Disk space low', ['availableGb' => 1.2]);
$client->error('Payment failed', ['orderId' => 'ORD-9', 'reason' => 'declined']);

Configuration

Parameter Type Default Description
apiKey string required Your project API key from the TinyOwl dashboard.
projectSecret string required Your project secret for HMAC signing.
baseUrl string https://be.tiny-owl-kit.io/api TinyOwl API base URL.
timeout float 5.0 HTTP request timeout in seconds.
autoTraceId bool true Attach a stable UUID v4 trace ID to every event.
defaultContext array [] Key/value pairs merged into every log call.
service string unset Service name, sent top-level and included in the HMAC signature when set.
environment string unset Deployment environment (e.g. production), sent and signed when set.

Logging events

$client->info('User signed in', ['userId' => 'u-123']);
$client->warning('Rate limit approaching', ['pct' => 90]);
$client->error('Database unreachable', ['host' => 'db.prod']);

$client->log('Order created', 'info', ['orderId' => 'ORD-1']);

Scoped loggers with withContext()

$reqLogger = $client->withContext(['requestId' => 'req-xyz', 'userId' => 'u-123']);
$reqLogger->info('Request received');
$reqLogger->error('Validation failed', ['field' => 'email']);

The parent client is never modified. Each child gets a fresh trace ID.

Default context

$client = new TinyOwl([
    'apiKey'         => $apiKey,
    'projectSecret'  => $secret,
    'defaultContext' => ['service' => 'billing', 'env' => 'prod'],
]);
$client->info('Invoice generated');
// Sent with context: {"service":"billing","env":"prod"}

Call-site context keys override defaultContext on conflict.

Auto trace ID

By default each TinyOwl instance generates a UUID v4 on construction and attaches it as traceId to every event. Child instances created with withContext() receive their own fresh trace ID. Invalid trace IDs are dropped with a warning (E_USER_WARNING), never fatal.

Opt out:

$client = new TinyOwl(['apiKey' => $apiKey, 'projectSecret' => $secret, 'autoTraceId' => false]);

Error handling

use TinyOwl\Observability\Exception\TinyOwlAuthException;
use TinyOwl\Observability\Exception\TinyOwlNetworkException;
use TinyOwl\Observability\Exception\TinyOwlTimeoutException;

try {
    $client->info('Hello');
} catch (TinyOwlAuthException $e) {
    echo "Auth failed ({$e->statusCode}): {$e->getMessage()}";
} catch (TinyOwlTimeoutException $e) {
    echo 'Request timed out';
} catch (TinyOwlNetworkException $e) {
    echo "Network error: {$e->getMessage()}";
}

Framework middleware

The middleware adds method, endpoint (route template or path without query string), routeTemplate, statusCode and durationMs to the event context. It sends an event only for uncaught exceptions and responses with status >= 400. Request bodies, query strings, headers and cookies are never sent, and SDK errors never break the application.

PSR-15

use TinyOwl\Observability\Integration\Psr15Middleware;

$pipeline->pipe(new Psr15Middleware($client, static function ($request): ?string {
    $template = $request->getAttribute('routeTemplate');
    return is_string($template) ? $template : null;
}));

Place the middleware after your routing middleware, because the route resolver runs before the handler. The resolver is optional; without it, endpoint is the request path.

Laravel

The package registers TinyOwl\Observability\Laravel\TinyOwlServiceProvider automatically. Set TINYOWL_API_KEY, TINYOWL_PROJECT_SECRET, and optionally TINYOWL_SERVICE and TINYOWL_ENVIRONMENT (falls back to APP_ENV). Then append the middleware in bootstrap/app.php:

->withMiddleware(function (Middleware $middleware): void {
    $middleware->append(\TinyOwl\Observability\Laravel\TinyOwlMiddleware::class);
})

Publish the config with php artisan vendor:publish --tag=tinyowl-config (optional).

Introspection

$config = $client->getConfig();
// [
//   'baseUrl'          => 'https://be.tiny-owl-kit.io/api',
//   'timeout'          => 5.0,
//   'autoTraceId'      => true,
//   'hasApiKey'        => true,
//   'hasProjectSecret' => true,
//   'instanceTraceId'  => '550e8400-...',
// ]
// Note: API key and project secret are never included.

Security

Every request is signed with HMAC-SHA256:

  • A cryptographically-random 32-hex-char nonce is generated per request (random_bytes).
  • The current UTC timestamp (ISO-8601, milliseconds) is included to prevent replay attacks.
  • Canonical JSON uses JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE so / and unicode match Node's JSON.stringify (required for HMAC parity).
  • Empty context serializes as {}, not [].
  • The backend rejects requests outside a ±60-second window and rejects reused nonces.
  • projectSecret is never logged or included in getConfig().
  • Plain-HTTP baseUrl over a non-localhost host emits a warning (OWASP A02).

Requirements

  • PHP 8.1+
  • ext-curl, ext-json (no Composer runtime dependencies)

License

MIT — see LICENSE.

Links