Download the PHP package timewave/laravel-logger without Composer

On this page you can find all versions of the php package timewave/laravel-logger. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-logger

Timewave\Logger

Custom logger package for PHP applications with opinionated log levels.

Usage

There will always be output to stdout. If Open Telemetry is configured, it will be pushed there to.

Basic usage:

If you don't pass an OtlpSender, the logger only writes to stdout — OTLP is opt-in by construction. Wiring is constructor-only; the sender cannot be swapped on a live logger.

Standing context

A logger can carry context that rides along on every line it emits, so recurring fields don't have to be repeated per call. It reaches both stdout and the OTLP log record, exactly like per-call context.

addContext() mutates the logger in place. Keep it for values that hold for the whole process — under a long-running worker (Octane, RoadRunner, Swoole) a per-request value set this way outlives the request and misattributes later lines. Per-request values belong on a child span, which snapshots instead of mutating.

On a key collision per-call context beats standing context, and an active span's traceId/spanId beat both. getContext() returns what a line from that logger carries, per-call context aside.

Child spans

Nesting a logger and opening a span are the same act: createChildSpan() opens a child span and returns a logger for it, seeded with a copy of the parent's standing context. Set a parent's context before creating its children — context added afterwards reaches only the parent.

Log context and span attributes are separate arguments: the second lands on every log line, the third only on the span in Tempo.

withChildSpan() does the same but ends the span for you, including when the closure throws, and returns whatever the closure returns:

Keep child spans to one per request, job, or comparable unit of work. Every ended span is its own OTLP POST and shares a queue holding 10 000 entries per sender, so opening one per row of a large import discards the telemetry that would have explained the import.

With an OtlpSender wired, a span that is never ended is still sent: the shutdown hook closes any span left open before draining, and a span dropped mid-request is closed by its destructor. A span closed that way reports a duration running to the moment it was collected rather than to the end of the work, and writes one stderr line naming it — so prefer withChildSpan(), or call endSpan() yourself, wherever the lifetime is yours to control.

An explicit OtlpSender::flushAll() only drains queues and leaves running spans alone, so it is safe to call mid-request.

Linking to an incoming trace (traceparent)

When a reverse-proxy (e.g. nginx ngx_otel_module with otel_trace_context propagate) injects a W3C traceparent header, root your request span on it so PHP spans join the proxy's trace instead of starting a detached one:

The header (version-traceId-spanId-flags) is parsed and validated (32-hex trace-id, 16-hex span-id, both non-zero). On a valid header the span adopts the incoming trace-id and uses the proxy's span-id as its parent. A missing or malformed header falls back to a fresh trace without throwing. Nested createChildSpan calls inherit the parent's trace-id, so the whole request shares one trace.

Propagating the trace outwards (traceparent)

Send the current span on as a traceparent header so the service you call joins the same trace, with your span as the parent of its spans:

Span::toTraceparent() returns 00-{traceId}-{spanId}-01. Use it instead of formatting the header at each call site, so honouring the incoming sampling flag later is one change here rather than one per consumer.

Deprecated methods

createSpanLogger() and createSpanLoggerFromTraceparent() still work and delegate to createChildSpan() and createRootSpanFromTraceparent(). Their second/third $context argument keeps its old meaning of span attributes. Each writes one E_USER_DEPRECATED per process the first time it is called.

Log levels

Log formats

Open Telemetry Collector endpoint

OtlpSender takes a DSN string in its constructor — e.g. new OtlpSender('http://localhost:4318'). The target must be an OTLP/HTTP endpoint. Payloads are sent JSON-encoded (Content-Type: application/json); most collectors (e.g. otelcol's HTTP receiver) accept this on :4318 alongside the protobuf encoding.

The library expects a low-latency OTLP collector — typically otelcol running on the same VM/pod as the application. That local collector handles batching, retries, and outbound wire traffic. This assumption shapes the design choices below.

If OTLP is enabled, sender wiring is mandatory: construct one in your composition root and pass it into every Logger (and any directly-constructed Span) that needs OTLP. There is no library-level singleton or implicit lookup — sharing is the caller's responsibility, which keeps lifetimes explicit. One sender keeps one cURL handle, queue, and shutdown-hook entry, so reusing a single instance across the request keeps host resolution + TLS state warm and bounds resource use in long-running workers.

OTLP sending is fire-and-forget

Every call to OtlpSender::http() (and every Span::end() / log line emitted via Logger) appends the payload to an in-memory queue rather than blocking on the collector. The queue is drained either:

Practical consequences:

OTLP stopwatch (per-call latency)

Every send() measures its own latency, but only writes a record to stdout when the call took longer than OtlpSender::STOPWATCH_THRESHOLD_MS (200 ms). That gives you a production-safe signal for slow OTLP without flooding the log stream on every span.

When the threshold is exceeded the sender writes a JSON line:

For a healthy local collector this should be effectively silent; sustained stopwatch lines mean the local collector pipeline is misbehaving.

Local development

Everything runs through Docker via docker-compose.yml; no host-side PHP or composer needed.

Install dependencies:

Run the test suite (PHP 7.4):

Run against PHP 8.3 and 8.5 as well (the package supports ^7.4 || ^8.0):

Ad-hoc PHP invocations (e.g. trying a snippet, running a single test file):

All image tags are pinned to exact patch versions in docker-compose.yml; bump them deliberately rather than relying on rolling tags.

composer.json also pins config.platform.php = "7.4" so dependency resolution always targets the lowest supported PHP. Without that pin, running composer install under PHP 8 (as the composer:2.9.8 image does) would pull dev deps that drop PHP 7.4 support — e.g. doctrine/instantiator ≥ 2.x uses PHP 8.3 typed-constant syntax and silently breaks the PHPUnit run on 7.4.

Register an autoloader, or explicitly require the PHP files in src/, to consume the library from another project.

Releasing

The package is published on Packagist as timewave/logger. The version is taken from the git tag — there is no version field in composer.json.

To cut a release:

  1. Add a changelog entry below for the new version.
  2. Create a GitHub release with a semver tag vX.Y.Z (e.g. v0.6.0). On 0.x, bump the minor for breaking changes and the patch otherwise.

A GitHub webhook notifies Packagist on every push, so the new version appears within a minute or two — no manual step.

The webhook is already configured; this is only documented in case it needs re-creating (repo → Settings → Webhooks): payload URL https://packagist.org/api/github?username=timewave, content type application/json, secret = the timewave Packagist account's API token, subscribed to the push event.

Changelog

0.7.1

0.7.0

0.6.1

0.6.0

0.5.0

0.4.0

0.3.0

0.2.2

0.2.1

0.2.0

0.1.0


All versions of laravel-logger with dependencies

PHP Build Version
Package Version
Requires php Version ^7.4 || ^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package timewave/laravel-logger contains the following files

Loading the files please wait ...