Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Server Status Laravel Package

innmind/server-status

Innmind/server-status is a lightweight PHP package for exposing server health-check endpoints. It reports application and dependency status in a simple, monitor-friendly format, making it easy to integrate with load balancers, uptime checks, and operational dashboards.

View on GitHub
Deep Wiki
Context7

Getting Started

innmind/server-status is a framework-agnostic library that reads host metrics (CPU load, memory, disk usage, processes) and exposes them as immutable value objects. There is no service provider, no config file, no facade, and no Laravel auto-discovery — it is a plain Composer dependency you glue into your app yourself. That is the whole point: it does one job, and the HTTP/routing/caching layer is yours.

Install and verify

composer require innmind/server-status
composer show innmind/server-status   # confirm PHP constraint against your runtime

Where to look first

  1. README.md — the canonical construction snippet for the Server implementation you need (Unix/Linux).
  2. src/ — the Server interface and the Status tree. Innmind packages are heavily interface-driven; the interfaces tell you what you can fake in tests.
  3. tests/ — the most reliable usage documentation for this ecosystem, more so than the README.

First use case: an artisan command before a route. Print the tree, learn the shape of the value objects, then expose it.

// app/Console/Commands/ServerStatusCommand.php
public function handle(): int
{
    $status = $this->server->status(); // your wrapper, see below

    $this->table(['metric', 'value'], [
        ['load (1m)',  $status->cpu()->loadAverage()->lastMinute()],
        ['memory used', $status->memory()->used()->toFloat()],
        ['disk used',  $status->disk()->used()->toFloat()],
    ]);

    return self::SUCCESS;
}

Exact accessor names vary between releases — treat the snippet as the shape, not a contract. Once the command output looks sane on your host, promote it to a route.

Implementation Patterns

Wrap it, never call it from a controller. Create one small service that owns construction, error handling and formatting. This is your seam for faking metrics in tests and for swapping the library out later (see the risk note in Gotchas).

// app/Support/Health/ServerMetrics.php
final class ServerMetrics
{
    public function snapshot(): array
    {
        try {
            $status = $this->server->status();
        } catch (\Throwable $e) {
            report($e);
            return ['available' => false];
        }

        return [
            'available' => true,
            'load_1m'   => $status->cpu()->loadAverage()->lastMinute(),
            'memory'    => $status->memory()->used()->toFloat(),
        ];
    }
}

Bind ServerMetrics as a singleton in a service provider (the Server itself is stateless enough to be a singleton too), and inject it.

Separate liveness from readiness. Liveness probes should be dirt cheap and never touch /proc. Readiness/metrics probes can be expensive:

Route::get('/healthz', fn () => response('ok'));                 // no disk, no DB
Route::get('/readyz',  ReadyController::class);                 // DB + Redis + metrics

Cache the metric collection. Reading /proc, statvfs on network mounts, and process tables is not free. A probe hitting every 5 seconds from three environments will add up:

$metrics = Cache::remember('server-metrics', now()->addSeconds(15), fn () => $this->metrics->snapshot());

Cache the raw snapshot, not the HTTP response — thresholds and auth may differ per route.

Compose with app-level checks into one report. The package covers the host; it knows nothing about your queue or database. Build a single array in your own class and add checks alongside:

$checks = [
    'host'   => $metrics,
    'db'     => $this->dbPing(),
    'queue'  => ['lag' => Queue::size('default')],
];

Encode severity in the status code, not the body. 200 when all checks pass, 503 otherwise — orchestrators and load balancers only read the code. Use response()->json($report, $healthy ? 200 : 503).

Prefer scheduled collection over per-request collection. For dashboards and alerting, run an artisan command every minute, write the snapshot to cache/Redis/StatsD, and let the HTTP endpoint read the cached value. This decouples probe frequency from filesystem cost and gives you history.

Protect the endpoint. These metrics leak hostnames, process names and load — useful reconnaissance. Gate with a bearer token middleware or an IP allowlist, and register the route outside the web group so session/CSRF middleware doesn't interfere.

Testing. Never let tests touch the real host. Type-hint your ServerMetrics wrapper (or the package interface, if it's narrow enough) and bind a fake returning fixed arrays. Assert the 200/503 boundary, not the numbers.

Gotchas and Tips

  • No PSR-7/HttpFoundation bridge. You get value objects, not responses. Convert explicitly in your controller; don't expect Response or JsonSerializable to be there.
  • Immutability means exceptions. These libraries throw on invalid input rather than returning nulls. A failed read can surface as an exception mid-request — always catch around ->status() and degrade to 'available' => false with a 503, never let it become a 500.
  • Containers lie about the host. sys_getloadavg(), /proc/meminfo and /proc/cpuinfo report the host, not your cgroup limit. A pod with a 512Mi limit will look healthy while being OOM-killed. Cross-check against memory_limit / cgroup values, or prefer app-level checks in containerised deployments.
  • Filesystem calls can hang. disk() on NFS/EFS mounts or a saturated volume can block for seconds. Keep disk checks out of liveness, and consider skipping them entirely on the request path.
  • Permissions and platform. Reading process tables or /proc fails on hardened hosts, Alpine/BusyBox images, and macOS/Windows dev machines. Guard with feature detection and expect available: false locally — don't let that fail CI.
  • No config publishing. All thresholds live in your own config/health.php. Don't call env() from the wrapper class — config:cache will silently return null in production.
  • Octane / long-running workers. A singleton caching the last Status object will serve stale metrics forever. Cache the serialised array with an explicit TTL instead of holding the object graph.
  • Debugging. dd($status) is genuinely useful — it's a tree of small value objects, so you can see exactly which metric is missing. For quick inspection in a command, var_export the derived scalars rather than the tree.
  • Extension points. Implement the package's Server interface (or your wrapper contract) to fake metrics in tests, and decorate your wrapper to bolt on caching, timing and error capture without touching call sites.
  • Dependency risk is real. 7 stars, 0 dependents, and a release date that needs verifying against your PHP version mean you are the QA team. Keep the package behind your ServerMetrics wrapper so replacing it with spatie/laravel-health or 40 lines of /proc parsing is a one-file change. Pin the version in composer.json and re-run your command against the new release before deploying.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums