Logs · Reference
Laravel SDK
mybeast/logs-laravel: a log channel that sends your app's lines to Logs, scrubbed, without slowing a request or losing a line. For Laravel 12 and 13 on PHP 8.2 or later.
Install
composer require mybeast/logs-laravelLaravel finds the package by itself. To change a setting that has no .env line, such as scrub or batch_size, publish the config to config/mybeast-logs.php:
php artisan vendor:publish --tag=mybeast-logs-configThe .env lines
LOG_STACK=single,mybeast
MYBEAST_LOGS_URL=https://services.my-beast.com/logs
MYBEAST_LOGS_SECRET=sk_…
MYBEAST_LOGS_ENVIRONMENT=production| Line | What it is |
|---|---|
LOG_STACK | The channels of your app's log. Keep your own (single, daily, …) and add mybeast. |
MYBEAST_LOGS_URL | The service's address. |
MYBEAST_LOGS_SECRET | The server secret that lets this server send its lines. Shown once, when it is made. |
MYBEAST_LOGS_ENVIRONMENT | Where this copy of the app runs: one of the project's environments. Left out, it is APP_ENV. |
Missing or malformed values switch the SDK off: without an http or https address and a server secret that looks like one, the channel takes lines and keeps none. It never throws at boot and never breaks a page.
Configuration
Every key of config/mybeast-logs.php, with the .env line that sets it where there is one:
| Key | Default | What it does |
|---|---|---|
enabledMYBEAST_LOGS_ENABLED | true | false switches everything off: the channel takes lines and keeps none. For your test suite. |
urlMYBEAST_LOGS_URL | none | The service's address, http:// or https://. Without it the SDK is off. |
secretMYBEAST_LOGS_SECRET | none | sk_…: this server's secret for sending its lines. Without one that looks like a server secret, the SDK is off. |
environmentMYBEAST_LOGS_ENVIRONMENT | APP_ENV, else production | Sent with every line. Made into lower-case letters, digits, - and _, up to 32: EU.prod is sent as eu-prod. |
releaseMYBEAST_LOGS_RELEASE | APP_RELEASE, else the git commit | The build this process runs. Unset, the SDK reads the commit from .git, without running git. |
hostMYBEAST_LOGS_HOST | the machine's host name | This machine's name, up to 120 characters. |
levelMYBEAST_LOGS_LEVEL | debug | The mildest level the mybeast channel takes. A level that isn't one is debug. |
spool_pathMYBEAST_LOGS_SPOOL_PATH | storage/app/private/mybeast-logs | Where lines wait to be sent: files, never the database. |
spool_max_mbMYBEAST_LOGS_SPOOL_MAX_MB | 100 | How big the spool may grow while the service can't be reached. Past it, new lines aren't kept until there is room. |
batch_size | 500 | Lines per upload, 1 to 1,000. |
ship_every_secondsMYBEAST_LOGS_SHIP_EVERY | 10 | How often the scheduler sends the spool: 1, 2, 5, 10, 15, 20, 30 or 60. Any other number is 10. |
ship_after_responseMYBEAST_LOGS_SHIP_AFTER_RESPONSE | true | Send right after a response or a job, at most every 2 seconds per server. false leaves every send to the scheduler. |
request_id_headerMYBEAST_LOGS_REQUEST_ID_HEADER | X-Request-Id | The header a request's id is taken from when a proxy sets one, and put on the response under. |
scrub | [] | Your own patterns, on top of the built-in ones: ['/\bCUST-\d{6}\b/' => '[customer]']. See Data and privacy. |
Channels and levels
The SDK adds a log channel called mybeast, unless config/logging.php has one of that name already. Put it in the stack with LOG_STACK=single,mybeast: each line goes to Logs and on to the stack's other channels, as before. Its level is MYBEAST_LOGS_LEVEL, the mildest it takes.
Lines of this channel arrive in Logs as channel app. For a channel of its own name, add one with the mybeast driver:
// config/logging.php, under 'channels'
'payments' => [
'driver' => 'mybeast',
'name' => 'payments',
'level' => 'info',
],Log::channel('payments')->error('The bank answered 503', ['invoice' => $invoice]);That line arrives as channel payments, which the search can narrow to. A channel's level is its mildest; left out, it is debug. A name may hold letters, digits and ._:/-, up to 64; anything else becomes -.
How lines are sent
- Written to the spool. A line is one append to a file in
spool_path: no network, no database. A request waits for nothing else. - Sent from there right after the response has gone out, after each queued job, and by the scheduler every
ship_every_seconds. After a response or a job it sends at most every 2 seconds per server, and not while the service is failing: then the scheduler alone keeps trying. - In batches of
batch_sizelines, gzipped, oldest first. A batch leaves the spool only once the service has said it has it, and each line carries an id the service stores once, so a batch sent twice is harmless. - While the service is away, the lines wait in order and go when it is back. The spool may grow to
spool_max_mb; past that, new lines aren't kept until there is room again, and a line then says from when to when.
The SDK says what it does in your app's other log channels, in lines that start with My Beast logs:: when sending starts to fail and when it works again, when the service refuses a line, and once a month when the project's lines for the month are used up. They stay out of Logs, except the line that says the spool was full, which arrives as channel mybeast-logs.
What each line carries
- Its level, its time to the microsecond, its message and its context, scrubbed.
- The environment, the release, the host and the channel, from the settings above. The release is
MYBEAST_LOGS_RELEASE, elseAPP_RELEASE, else the git commit read from.git. - The request id: the same on every line of one HTTP request and of the jobs it queued. See Read one request's lines.
- What was running, without values:
GET /invoices/{invoice}/send,job App\Jobs\SendInvoice,artisan invoices:remind.
In the context:
- An Eloquent model is its class and key only, never its attributes.
- An exception is its class, message, code, file and line, the first 15 frames of its trace and the exception before it. Your app's own paths are relative to its root.
- Dates are ISO 8601, enums their value or name, and an object that can't be turned into data is its class name.
- Over 16 KiB as JSON, the context is replaced by a note of its size, keeping the exception when it fits. A message over 32 KiB is cut.
Under Octane, each request starts with a request id of its own.
Artisan commands
| Command | What it does |
|---|---|
php artisan mybeast:logs-ship | Sends what waits in the spool now. The scheduler runs it every ship_every_seconds; run it yourself to send at once. It says how many lines went, or why the rest waits, and ends with a failure then. |
php artisan mybeast:logs-status | Says whether the SDK is on and where to, the environment, the spool's folder, what waits there, whether the spool is full, the last try, and since when sending fails and why. |
The SDK puts mybeast:logs-ship on the scheduler itself, without overlapping runs. What mybeast:logs-status shows, row by row, is in Troubleshooting.
The facade
The channel needs no code: Log::info() is all your app writes. The facade, MyBeast\Logs\Laravel\Facades\Logs, is for the rest:
| Method | Returns | What it does |
|---|---|---|
Logs::enabled() | bool | Whether the SDK is on: a URL and a server secret, and not switched off. |
Logs::requestId() | ?string | The id every line of this request, job or command run carries, for whatever else wants to send it along. |
Logs::scrubUsing(Closure $rule) | void | A rule of your own, fn (string $text): string, run on every text after the built-in patterns. |
Logs::ship() | ShipResult | Sends what waits now, as mybeast:logs-ship does. The result has sent, refused, waitingBytes, error, and busy when another process was sending. |
Logs::spool() | Spool | The spool: directory(), waitingBytes(), fullSince(). |
use MyBeast\Logs\Laravel\Facades\Logs;
$id = Logs::requestId();scrubUsing() belongs in a service provider's boot(). Its rules, and the patterns under scrub, are in Data and privacy.
Testing
Switch the SDK off in your test suite, so tests write no spool and send nothing:
<!-- phpunit.xml, in <php> -->
<env name="MYBEAST_LOGS_ENABLED" value="false"/>Off, the channel takes lines and keeps none, and LOG_STACK can stay as it is. The SDK has no fake of its own: to check what your code logs, use Laravel's Log facade in your tests as you would without it.
MYBEAST_LOGS_URL or MYBEAST_LOGS_SECRET is off too, so a developer's machine sends nothing until you give it a secret of its own.