定制 mathiasgrimm/netwatch 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mathiasgrimm/netwatch

Composer 安装命令:

composer require mathiasgrimm/netwatch

包简介

Network service latency probing tool for PHP — measures Redis, PostgreSQL, MySQL, S3, HTTP endpoints with statistical analysis

README 文档

README

Network service latency probing tool for PHP. Measures connectivity and response times to Redis, PostgreSQL, MySQL, S3, HTTP endpoints, and raw TCP services with statistical analysis.

Alpha version — This package is under active development. The API may change at any time, including breaking changes, without prior notice. Use at your own risk.

TODO

  • Include hostname/identification on the output
  • Running php artisan netwatch:run creates file called host=;port=;dbname=

Maybe

  • Post results to some endpoint after php artisan netwatch:run
  • Detect env/cached config. Maybe boot application once and cache it with a md5(.env)
  • Maybe Concurrency::driver(’queue’) for async when calling /netwatch/health
  • Store & Cleanup of metrics to view on a dashboard
  • Use Inertia (3) for the dashboard with polling

Features

  • Multiple probe types — HTTP, TCP/IP, Redis (php-redis), MySQL/PostgreSQL/SQLite (PDO), AWS S3
  • Statistical analysis — min, max, avg, p50, p95, p99 for connect, request, and total latency
  • Parallel execution — probes run concurrently via subprocesses (default in CLI)
  • Per-probe configuration — individual iteration counts, enable/disable flags, serializable probe definitions
  • Laravel integration — service provider with auto-discovery, Artisan command, and health dashboard
  • Standalone CLI — works with any PHP project via Symfony Console
  • Fail-fast — stops probing after 3 consecutive failures

Requirements

  • PHP 8.3+
  • ext-curl (for S3 probe)
  • ext-redis (for Redis probe, optional)
  • ext-pdo (for database probes, optional)

Installation

composer require mathiasgrimm/netwatch

Laravel Integration

Netwatch auto-registers via Laravel package discovery. No manual provider registration needed.

Install

php artisan netwatch:install

This publishes the config file and service provider, and registers the provider in bootstrap/providers.php.

To overwrite previously published files:

php artisan netwatch:install --force

You can also publish assets individually:

php artisan vendor:publish --tag=netwatch-config
php artisan vendor:publish --tag=netwatch-provider

The config file (config/netwatch.php) contains pre-configured probes that read from your existing Laravel environment variables (DB_*, REDIS_*, AWS_*, APP_URL). The config uses the serializable [Class::class => [args]] array format, so it is fully compatible with php artisan config:cache.

<?php

use Mathiasgrimm\Netwatch\Laravel\Http\Middleware\Authorize;
use Mathiasgrimm\Netwatch\Probe\HttpProbe;
use Mathiasgrimm\Netwatch\Probe\PdoProbe;
use Mathiasgrimm\Netwatch\Probe\PhpRedisProbe;
use Mathiasgrimm\Netwatch\Probe\S3Probe;
use Mathiasgrimm\Netwatch\Probe\TcpPingProbe;

return [
    'iterations' => (int) env('NETWATCH_ITERATIONS', 10),

    'health_route' => [
        'enabled' => (bool) env('NETWATCH_HEALTH_ENABLED', false),
        'domain' => env('NETWATCH_DOMAIN'),
        'path' => env('NETWATCH_PATH', 'netwatch'),
        'middleware' => ['web', Authorize::class],
        'token' => env('NETWATCH_HEALTH_TOKEN'),
    ],

    'probes' => [

        'database' => [
            'enabled' => env('NETWATCH_PROBE_DATABASE_ENABLED', false),
            'probe' => [
                PdoProbe::class => [
                    env('DB_CONNECTION').':host='.env('DB_HOST').';port='.env('DB_PORT').';dbname='.env('DB_DATABASE'),
                    env('DB_USERNAME'),
                    env('DB_PASSWORD'),
                ],
            ],
        ],

        'redis' => [
            'enabled' => env('NETWATCH_PROBE_REDIS_ENABLED', false),
            'probe' => [
                PhpRedisProbe::class => [
                    env('REDIS_HOST').':'.env('REDIS_PORT'),
                    env('REDIS_USERNAME'),
                    env('REDIS_PASSWORD'),
                ],
            ],
        ],

        's3' => [
            'enabled' => env('NETWATCH_PROBE_S3_ENABLED', false),
            'probe' => [
                S3Probe::class => [
                    env('AWS_BUCKET'),
                    env('AWS_DEFAULT_REGION'),
                    env('AWS_ACCESS_KEY_ID'),
                    env('AWS_SECRET_ACCESS_KEY'),
                    env('AWS_ENDPOINT'),
                ],
            ],
        ],

        'app' => [
            'enabled' => env('NETWATCH_PROBE_APP_ENABLED', false),
            'probe' => [
                HttpProbe::class => [
                    env('APP_URL'),
                ],
            ],
        ],

        'cloudflare-dns' => [
            'enabled' => env('NETWATCH_PROBE_CLOUDFLARE_DNS_ENABLED', false),
            'probe' => [
                TcpPingProbe::class => [
                    '1.1.1.1',
                    53,
                ],
            ],
        ],

        'google-dns' => [
            'enabled' => env('NETWATCH_PROBE_GOOGLE_DNS_ENABLED', false),
            'probe' => [
                TcpPingProbe::class => [
                    '8.8.8.8',
                    53,
                ],
            ],
        ],

    ],
];

Artisan Command

php artisan netwatch:run
php artisan netwatch:run --probe=redis --iterations=20 --json
php artisan netwatch:run --json --without-results
Option Description
--iterations=N Override iteration count for all probes
--probe=NAME Run only a specific probe by name (e.g. --probe=redis)
--json Output results as JSON instead of a table
--without-results Exclude individual iteration results from JSON output

CLI Table Output

Health Dashboard

Enable the health dashboard route by setting NETWATCH_HEALTH_ENABLED=true in your .env:

NETWATCH_HEALTH_ENABLED=true
NETWATCH_PATH=netwatch

Access the dashboard at /netwatch/health.

Query Parameters

Parameter Example Description
format ?format=json Force response format: json or html. Without this parameter, the format is determined by the Accept header (defaults to HTML for browsers).
probes ?probes=redis,database Comma-separated list of probe names to run. Only the specified probes are executed; others are skipped.
without_results ?without_results=1 Exclude individual iteration results from the response, returning only aggregate stats. Useful for smaller payloads.

Parameters can be combined: /netwatch/health?probes=redis,database&format=json&without_results=1

HTML view — interactive dashboard with per-probe latency stats:

Health Dashboard

JSON panel — view raw JSON data directly within the dashboard:

Health Dashboard - JSON Panel

JSON API response — append ?format=json for a raw JSON endpoint:

Health Dashboard - JSON API Response

Authorization

Token-based auth (for monitoring tools)

Monitoring tools (Datadog, uptime checkers, etc.) that can't use session-based auth can authenticate with a query-parameter token:

NETWATCH_HEALTH_TOKEN=your-secret-token

Then access the endpoint as /netwatch/health?token=your-secret-token. When a valid token is provided, session/gate-based auth is bypassed. If the token is not set, regular auth applies unchanged.

Gate-based auth

By default, the health route is accessible only in local environments. To configure access in other environments, publish the service provider:

php artisan vendor:publish --tag=netwatch-provider

Then edit app/Providers/NetwatchServiceProvider.php:

protected function gate(): void
{
    Gate::define('viewNetwatch', function ($user = null) {
        return in_array(optional($user)->email, [
            'admin@example.com',
        ]);
    });
}

You can also use the static auth callback:

Netwatch::auth(function ($request) {
    return $request->user()?->isAdmin();
});

Environment Variables

NETWATCH_ITERATIONS=10                        # Default probe iterations
NETWATCH_HEALTH_ENABLED=false                 # Enable health dashboard route
NETWATCH_DOMAIN=null                          # Domain for health route
NETWATCH_PATH=netwatch                        # URL path prefix for health route
NETWATCH_HEALTH_TOKEN=null                       # Token for monitoring-tool access (null = disabled)

NETWATCH_PROBE_DATABASE_ENABLED=false         # Enable database (PDO) probe
NETWATCH_PROBE_REDIS_ENABLED=false            # Enable Redis probe
NETWATCH_PROBE_S3_ENABLED=false               # Enable S3 probe
NETWATCH_PROBE_APP_ENABLED=false              # Enable HTTP probe for APP_URL
NETWATCH_PROBE_CLOUDFLARE_DNS_ENABLED=false   # Enable Cloudflare DNS (1.1.1.1) TCP probe
NETWATCH_PROBE_GOOGLE_DNS_ENABLED=false       # Enable Google DNS (8.8.8.8) TCP probe

Standalone (without Laravel)

CLI

Generate a config file and run:

# Generate config
vendor/bin/netwatch netwatch:init

# Run all probes
vendor/bin/netwatch netwatch:run

# Run a specific probe with 20 iterations
vendor/bin/netwatch netwatch:run --probe redis --iterations 20

# JSON output
vendor/bin/netwatch netwatch:run --json

Programmatic

use Mathiasgrimm\Netwatch\Netwatch;
use Mathiasgrimm\Netwatch\Probe\HttpProbe;
use Mathiasgrimm\Netwatch\Probe\TcpPingProbe;

$netwatch = new Netwatch([
    'example' => ['probe' => new HttpProbe('https://example.com')],
    'dns'     => ['probe' => new TcpPingProbe('8.8.8.8', 53)],
], iterations: 10);

$results = $netwatch->run();

foreach ($results as $name => $aggregate) {
    echo "$name: avg={$aggregate->stats['total_ms']['avg']}ms p99={$aggregate->stats['total_ms']['p99']}ms\n";
}

Configuration

Standalone Config File

Create a netwatch.php in your project root (or use netwatch:init to generate one):

<?php

use Mathiasgrimm\Netwatch\Probe\PhpRedisProbe;
use Mathiasgrimm\Netwatch\Probe\PdoProbe;
use Mathiasgrimm\Netwatch\Probe\HttpProbe;
use Mathiasgrimm\Netwatch\Probe\TcpPingProbe;

return [
    'iterations' => 10,

    'probes' => [
        'redis' => [
            'enabled' => true,
            'probe' => new PhpRedisProbe('tcp://127.0.0.1:6379'),
        ],
        'mysql' => [
            'enabled' => true,
            'probe' => new PdoProbe('mysql:host=127.0.0.1;port=3306', 'root', ''),
        ],
        'pgsql' => [
            'enabled' => true,
            'probe' => new PdoProbe('pgsql:host=127.0.0.1;port=5432;dbname=postgres', 'postgres', ''),
        ],
        'app' => [
            'enabled' => true,
            'probe' => new HttpProbe('https://example.com'),
        ],
        'cloudflare' => [
            'enabled' => true,
            'probe' => new TcpPingProbe('1.1.1.1', 443),
        ],
    ],
];

Per-Probe Options

Each probe entry supports:

Key Type Default Description
probe ProbeInterface|string|array required Probe instance, class string, or [Class::class => [args]] array
enabled bool false Probe is skipped unless explicitly set to true
iterations int global default Override iteration count for this probe
'redis' => [
    'enabled' => true,
    'probe' => new PhpRedisProbe('tcp://127.0.0.1:6379'),
    'iterations' => 20,
],

The probe value supports three formats:

  • Instance — a ProbeInterface object, used as-is
  • Class string — e.g. PhpRedisProbe::class, instantiated with no arguments
  • Array[Class::class => [arg1, arg2, ...]], instantiated with the given arguments. This format is serializable, making it compatible with php artisan config:cache.
// Array format (serializable)
'database' => [
    'enabled' => true,
    'probe' => [
        PdoProbe::class => ['mysql:host=127.0.0.1;port=3306', 'root', ''],
    ],
],

Available Probes

HttpProbe

Measures HTTP endpoint latency using cURL. Reports connect time and request time separately.

new HttpProbe(
    url: 'https://example.com',
    method: 'GET',          // HTTP method (default: GET)
    headers: [],            // Custom headers
    timeout: 3.0,           // Timeout in seconds
    expectedCode: null,     // Expected HTTP status code (null = 200-399)
)

TcpPingProbe

Measures raw TCP connection latency via fsockopen.

new TcpPingProbe(
    host: '8.8.8.8',
    port: 53,
    timeout: 3.0,
)

PdoProbe

Measures database connectivity by opening a PDO connection and running SELECT 1.

new PdoProbe(
    dsn: 'mysql:host=127.0.0.1;port=3306;dbname=mydb',
    username: 'root',
    password: 'secret',
    timeout: 3,
)

Supports any PDO driver: MySQL, PostgreSQL, SQLite, etc.

PhpRedisProbe

Measures Redis latency using the php-redis extension. Connects, authenticates, and runs PING.

new PhpRedisProbe(
    address: 'tcp://127.0.0.1:6379',
    username: null,
    password: null,
    timeout: 3.0,
)

S3Probe

Measures AWS S3 bucket latency by performing a HEAD request with AWS Signature V4 authentication (no SDK required).

new S3Probe(
    bucket: 'my-bucket',
    region: 'us-east-1',
    key: 'AKIAIOSFODNN7EXAMPLE',
    secret: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
    endpoint: null,         // Custom endpoint (e.g., MinIO)
    timeout: 3.0,
)

Custom Probes

Implement ProbeInterface to create your own:

use Mathiasgrimm\Netwatch\Contract\ProbeInterface;
use Mathiasgrimm\Netwatch\Result\ProbeResult;

class MyProbe implements ProbeInterface
{
    public function probe(): ProbeResult
    {
        $start = hrtime(true);
        // ... your logic ...
        $elapsed = (hrtime(true) - $start) / 1e6;

        return new ProbeResult(
            connectMs: $elapsed,
            requestMs: 0,
            totalMs: $elapsed,
            success: true,
        );
    }

    public function name(): string
    {
        return 'my-probe';
    }
}

CLI Reference

netwatch:run

Run probes and display latency statistics.

vendor/bin/netwatch netwatch:run [options]
Option Short Description
--config -c Config file path (default: netwatch.php)
--iterations -i Override iteration count for all probes
--probe -p Run only a specific probe by name
--sequential Run probes sequentially (default: parallel)
--json Output results as JSON
--without-results Exclude individual iteration results from JSON

netwatch:init

Generate a starter config file.

vendor/bin/netwatch netwatch:init [options]
Option Short Description
--force -f Overwrite existing netwatch.php

Output

Table Output (default)

+--------+------------+----------+---------+----------+----------+----------+----------+----------+----------+
| Probe  | Iterations | Failures | Metric  | Min (ms) | Max (ms) | Avg (ms) | P50 (ms) | P95 (ms) | P99 (ms) |
+--------+------------+----------+---------+----------+----------+----------+----------+----------+----------+
| redis  | 10         | 0        | connect | 0.312    | 0.891    | 0.523    | 0.487    | 0.856    | 0.884    |
|        |            |          | request | 0.098    | 0.234    | 0.142    | 0.131    | 0.221    | 0.231    |
|        |            |          | total   | 0.421    | 1.102    | 0.665    | 0.618    | 1.054    | 1.092    |
+--------+------------+----------+---------+----------+----------+----------+----------+----------+----------+

JSON Output

{
  "redis": {
    "name": "redis:tcp://127.0.0.1:6379",
    "iterations": 10,
    "stats": {
      "connect_ms": { "min": 0.312, "max": 0.891, "avg": 0.523, "p50": 0.487, "p95": 0.856, "p99": 0.884 },
      "request_ms": { "min": 0.098, "max": 0.234, "avg": 0.142, "p50": 0.131, "p95": 0.221, "p99": 0.231 },
      "total_ms":   { "min": 0.421, "max": 1.102, "avg": 0.665, "p50": 0.618, "p95": 1.054, "p99": 1.092 }
    },
    "failures": 0,
    "results": [ ... ]
  }
}

CLI JSON Output

Statistical Analysis

For each probe, Netwatch runs the configured number of iterations and computes statistics over successful runs. Three timing metrics are tracked:

Metric Description
connect_ms Time to establish the connection
request_ms Time to complete the request after connection
total_ms End-to-end latency (connect + request)

For each metric, the following statistics are computed:

Stat Description
min Minimum observed value
max Maximum observed value
avg Arithmetic mean
p50 50th percentile (median)
p95 95th percentile
p99 99th percentile

Percentiles use linear interpolation between nearest-rank values.

Testing

composer install
vendor/bin/pest

License

MIT

统计信息

  • 总下载量: 159
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 3
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-03-13

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固