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: 4

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.2 2026-09-08 19:34 UTC

This package is auto-updated.

Last update: 2026-09-08 19:47:35 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.

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()}";
}

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