Concepts
Organizations own projects; a project is one application and has one public key (lx_…). SDKs send events to the project. Events are one of four types:
| Type | What it is | Grouped into issues? |
|---|---|---|
error | An exception with stack trace | Yes, by exception type + message + in-app frames |
log | A log line (debug … emergency) from the server | Yes, by level + logger + normalized message |
console | Browser console output, failed resources, HTTP ≥ 500 from fetch/XHR | Yes, same as log |
transaction | A timed operation: HTTP request, page load, job, command, with spans | No, shown under Performance |
Issues live in MariaDB (status, assignee, counts). Raw events live in ClickHouse for the project’s retention window (default 30 days). Numbers, UUIDs, e-mails, dates and quoted strings are normalized before grouping so Order 4412 not found and Order 9981 not found become one issue. Send a custom fingerprint array to control grouping yourself.
Laravel SDK
Requires PHP 8.2+ and Laravel 10, 11 or 12.
composer config repositories.loggerxo vcs https://github.com/noneym/loggerxo-laravel composer require noneym/loggerxo-laravel:dev-main
LOGGERXO_DSN=https://lx_your_key@loggerxo.com
LOGGERXO_ENVIRONMENT=${APP_ENV}
LOGGERXO_RELEASE=2026.10.1
# log channel: add "loggerxo" to your stack to ship log lines
LOG_STACK=single,loggerxo
LOGGERXO_LOG_LEVEL=debug # minimum level sent as log events
LOGGERXO_TRACING=true # request / job / command transactions
LOGGERXO_TRACES_SAMPLE_RATE=1.0 # 0.0 – 1.0
LOGGERXO_SEND_DEFAULT_PII=false # include user e-mail / IP
LOGGERXO_QUEUE=false # true = send via your queue instead of at request end
What is captured automatically
- Every reported exception (via the exception handler) with source-code context, request data, authenticated user, and breadcrumbs (queries, log lines, dispatched jobs, HTTP client calls).
- Log lines through the
loggerxoMonolog channel, including context arrays. - Transactions for HTTP requests (
GET /orders/{order}), queue jobs and artisan commands, with DB query spans, status codes, memory and query counts.
Manual API
use Noneym\Loggerxo\Facades\Loggerxo;
Loggerxo::captureException($e, ['tags' => ['module' => 'billing']]);
Loggerxo::captureMessage('Payout batch finished', 'info', ['context' => ['count' => 42]]);
Loggerxo::setUser(['id' => $user->id, 'email' => $user->email]);
Loggerxo::setTag('tenant', $tenant->slug);
Loggerxo::addBreadcrumb('cache', 'warm products', ['took_ms' => 12]);
Loggerxo::flush(); // force send now (e.g. before exit in a long-running script)
Sensitive keys (password, token, authorization, cookies, …) are masked both in the SDK and again on the server.
Browser SDK
<script src="https://loggerxo.com/sdk/loggerxo.js" data-key="lx_your_key" data-env="production" data-release="1.0.0"></script>
Captures window.onerror, unhandled promise rejections, console.error/console.warn (configurable), failed resources, fetch/XHR failures and ≥ 500 responses, plus a page-load transaction with web vitals. Breadcrumbs: clicks, navigation, console, HTTP.
Loggerxo.init({
key: 'lx_your_key',
endpoint: 'https://loggerxo.com',
environment: 'production',
release: '1.0.0',
captureConsole: ['error', 'warn'], // [] to disable
captureHttpErrors: true,
httpErrorStatus: 500,
captureResourceErrors: true,
tracing: true,
sampleRate: 1,
maxEventsPerMinute: 60,
ignoreErrors: [/ResizeObserver loop/, 'Script error.'],
ignoreUrls: [/extensions\//],
beforeSend: (event) => event, // return null to drop
user: { id: '42' },
tags: { plan: 'pro' },
});
Data attributes map to options: data-key, data-endpoint, data-env, data-release, data-console="error,warn", data-tracing="false", data-debug="true".
Restrict which sites may use the key under Project → Settings → Allowed browser origins.
HTTP API
Anything that can POST JSON can send events. Authenticate with the project key in X-Loggerxo-Key (or Authorization: Bearer, or ?key=). Optional Content-Encoding: gzip.
POST https://loggerxo.com/api/v1/envelope # server-side events POST https://loggerxo.com/api/v1/browser?key=… # browser events (CORS, text/plain allowed) GET https://loggerxo.com/api/v1/health
{
"sdk": {"name": "my-app", "version": "1.0"},
"environment": "production",
"release": "2026.10.1",
"events": [ { "type": "log", "level": "warning", "message": "Disk at 91%", "logger": "ops",
"tags": {"host": "web-1"}, "context": {"free_gb": 4.2} } ]
}
| Field | Notes |
|---|---|
type | error, log, console, transaction. Defaults to error if exception is present, else log. |
level | debug, info, notice, warning, error, critical, alert, emergency (aliases like warn/fatal accepted). |
timestamp | ISO-8601 or unix seconds/milliseconds. Clamped to the last 30 days. |
exception | {type, value, module?, code?, frames: [{file, line, col?, function, class?, in_app, context?: {pre[], line, post[]}}], chain?: [...]}. Sentry-style {values: [...]} is accepted too. |
request | {url, method, headers, query, data, ip, route}; sensitive headers and fields are masked. |
user | {id, email, username, name, ip} |
tags | Flat string map, max 50 keys. Searchable with tag:key=value. |
context | Any JSON, shown on the event (truncated at 20 KB). |
breadcrumbs | [{timestamp, type, category, level, message, data}], last 50 kept. |
fingerprint | Array of strings to override grouping. |
| transaction fields | name, op, http_method, status_code, duration_ms, measurements (numeric map), spans ([{op, description, start_ms, duration_ms, data?}]). |
Limits: 500 events / request (50 for the browser endpoint), 2 MB body, 256 KB per event, project rate limit (default 6,000 events/min, 429 + Retry-After when exceeded). Response: 202 {"accepted": n, "dropped": n}.
Alerts
Under Project → Settings → Alerts create channels (e-mail recipients or a Telegram chat) and rules. Rule triggers:
- New issue – the first time a fingerprint is seen.
- Regression – a resolved issue happens again.
- Frequency – more than N events for one issue within M minutes.
- Log level – any event at or above a level (e.g.
critical), useful for ops logs that are not exceptions.
Each rule has a per-issue cooldown and can be limited to environments and event types. Telegram: create a bot with @BotFather, add it to a group, and use the group’s chat id. The server can also hold one global bot token (TELEGRAM_BOT_TOKEN) so projects only need a chat id.
Search syntax
| Query | Matches |
|---|---|
timeout | message, exception value, URL or transaction containing “timeout” |
url:/checkout | URL contains /checkout |
user:jane@example.com | events for that user (also matches id / IP in the user filter) |
tag:module=orders | exact tag match |
exception:TypeError | exception type contains TypeError |
transaction:orders, server:web-1, release:2026.10, logger:payments | field contains value |
Deploy your own instance
Loggerxo is open source (MIT). The repository ships a multi-stage Dockerfile (FrankenPHP + supervisord running the web server, ingest workers, queue worker and scheduler). Point it at MariaDB, Redis and ClickHouse via environment variables; migrations run on boot.
APP_KEY=base64:… APP_URL=https://loggerxo.example.com DB_HOST / DB_PORT / DB_DATABASE / DB_USERNAME / DB_PASSWORD REDIS_HOST / REDIS_PORT / REDIS_PASSWORD CLICKHOUSE_HOST / CLICKHOUSE_PORT (HTTP, 8123) / CLICKHOUSE_DB / CLICKHOUSE_USER / CLICKHOUSE_PASSWORD MAIL_MAILER=cloudflare + CLOUDFLARE_EMAIL_ACCOUNT_ID + CLOUDFLARE_EMAIL_API_TOKEN (or MAIL_MAILER=smtp …) MAIL_FROM_ADDRESS=no-reply@your-verified-domain INGEST_WORKERS=2 DEFAULT_RETENTION_DAYS=30 REGISTRATION_ENABLED=true SUPER_ADMIN_EMAILS=you@example.com
Useful commands: php artisan loggerxo:clickhouse-migrate, php artisan loggerxo:ingest, php artisan loggerxo:prune. The admin page (super admins only) shows ingest backlog, dead letters and ClickHouse disk usage.