davit-vardanyan/netdata-php

PHP SDK for the Netdata API v3 — query metrics, nodes, alerts, contexts, and more

Maintainers

Package info

github.com/davit-vardanyan/netdata-php

pkg:composer/davit-vardanyan/netdata-php

Statistics

Installs: 25

Dependents: 1

Suggesters: 1

Stars: 0

Open Issues: 0

1.0.0 2026-03-13 09:53 UTC

This package is auto-updated.

Last update: 2026-03-13 09:58:22 UTC


README

Tests Code Style Latest Stable Version PHP Version License

A production-ready PHP SDK for the Netdata API v3. Covers 22 endpoints across 13 resources with rich DTOs, an immutable query builder, automatic retries, and a testing fake. Zero framework dependencies — works in any PHP 8.2+ project.

Features

  • 13 resource classes covering 22 /api/v3/* endpoints
  • Rich DTOs (Node, MetricData, Alert, Context, AgentInfo) with automatic v3 response parsing
  • MetricData with dimension(), latest(), average(), max(), min(), sum(), toTimeSeries()
  • Immutable fluent query builders (DataQueryRequest, WeightsRequest)
  • Automatic retry with exponential backoff and jitter on 429/5xx errors
  • Full exception hierarchy mapped to HTTP status codes
  • NetdataFake for easy testing with call assertions
  • Swappable HTTP client via HttpClientInterface
  • Optional PSR-3 logger support
  • PHPStan level 9 and PSR-12 compliant

Installation

composer require davit-vardanyan/netdata-php

Quick Start

use DavitVardanyan\Netdata\NetdataClient;

// Connect to Netdata Cloud
$netdata = NetdataClient::make('your-bearer-token');

// Get CPU metrics from the last 10 minutes
$cpu = $netdata->data()->cpu();
echo "Current CPU: " . $cpu->latest('user') . "%\n";
echo "Average CPU: " . round($cpu->average('user'), 2) . "%\n";

// List all monitored nodes
$nodes = $netdata->nodes()->list();
foreach ($nodes as $node) {
    echo "{$node->name} ({$node->os})\n";
}

Configuration

use DavitVardanyan\Netdata\NetdataClient;
use DavitVardanyan\Netdata\Support\Config;

$netdata = new NetdataClient(
    config: new Config(
        token: 'your-bearer-token',              // Required
        baseUrl: 'https://app.netdata.cloud',     // Default
        connectTimeout: 30,                       // Seconds
        readTimeout: 60,                          // Seconds
        maxRetries: 3,                            // Retry on 429/5xx
        retryBaseDelayMs: 1000,                   // Exponential backoff base
    ),
);
Option Type Default Description
token string required Netdata API bearer token
baseUrl string https://app.netdata.cloud API base URL
connectTimeout int 30 Connection timeout in seconds
readTimeout int 60 Read timeout in seconds
maxRetries int 3 Max retry attempts on 429/5xx errors
retryBaseDelayMs int 1000 Base delay for exponential backoff (ms)

Available Resources

Accessor Endpoints Description
data() /api/v3/data Query metric data with convenience shortcuts
weights() /api/v3/weights Metric weight/correlation analysis
contexts() /api/v3/contexts, /api/v3/context Browse and inspect metric contexts
nodes() /api/v3/nodes, /api/v3/node_instances List nodes and node instances
alerts() /api/v3/alerts, /api/v3/alert_transitions, /api/v3/alert_config Alert summaries, transitions, and configuration
functions() /api/v3/functions, /api/v3/function List and execute agent functions
info() /api/v3/info, /api/v3/versions, /api/v3/me, /api/v3/settings Agent and version information
search() /api/v3/q Search across metrics, nodes, and contexts
badges() /api/v3/badge.svg Generate badge SVGs
allMetrics() /api/v3/allmetrics Export all metrics (Prometheus, JSON, Shell)
config() /api/v3/config, /api/v3/variable Agent configuration and variables
streamPath() /api/v3/stream_path Streaming path information
claim() /api/v3/claim Agent claiming

Usage

Querying Metrics

Convenience Shortcuts

// CPU metrics (last 10 minutes by default)
$cpu = $netdata->data()->cpu();
$cpu = $netdata->data()->cpu(afterSeconds: -3600); // last hour

// Memory metrics
$memory = $netdata->data()->memory();

// Disk metrics
$disk = $netdata->data()->disk();

// Network metrics
$network = $netdata->data()->network();

Full Query Builder

use DavitVardanyan\Netdata\Requests\DataQueryRequest;
use DavitVardanyan\Netdata\Enums\GroupMethod;

$request = DataQueryRequest::make()
    ->contexts('system.cpu')           // required — pipe-separated if multiple
    ->nodes('my-node-id')              // scope to specific nodes
    ->dimensions(['user', 'system'])   // filter dimensions
    ->labels(['env:production'])       // filter by labels
    ->after(-3600)                     // 1 hour ago
    ->before(0)                        // now
    ->points(60)                       // 60 data points
    ->group(GroupMethod::Average)
    ->groupBy('dimension')
    ->aggregation('avg');

$data = $netdata->data()->query($request);

The builder also supports scopeInstances(), filterContexts(), filterNodes(), filterInstances(), filterAlerts(), format(), options(), tier(), and timeoutMs().

Working with MetricData

$cpu = $netdata->data()->cpu();

// Get values for a single dimension
$userValues = $cpu->dimension('user'); // [12.5, 15.8, ...]

// Get the latest value
$current = $cpu->latest('user'); // 18.3

// Statistical methods
$cpu->average('user'); // 16.38
$cpu->max('user');     // 25.1
$cpu->min('user');     // 10.2
$cpu->sum('user');     // 81.9

// Convert to charting format
$timeSeries = $cpu->toTimeSeries();
// [['timestamp' => 1709550000, 'user' => 12.5, 'system' => 3.2, ...], ...]

// Metadata
$cpu->labels;     // ['guest_nice', 'guest', 'steal', 'softirq', 'irq', 'user', ...]
$cpu->timestamps; // [1709550000, 1709550020, ...]
$cpu->points;     // 60
$cpu->after;      // 1709549400
$cpu->before;     // 1709550000
$cpu->isEmpty();  // false

Listing Nodes

$nodes = $netdata->nodes()->list();

foreach ($nodes as $node) {
    echo "{$node->name} (OS: {$node->os})\n";
    echo "  Version: {$node->version}\n";
    echo "  Arch: {$node->architecture}, CPUs: {$node->cpus}\n";
}

// With scoping
$nodes = $netdata->nodes()->list(scopeNodes: 'node-1|node-2');

// Node instances
$instances = $netdata->nodes()->instances();

The Node DTO provides: id, name, os, osName, osVersion, kernelName, kernelVersion, architecture, cpus, memory, diskSpace, version, machineGuid, services.

Browsing Contexts

$contexts = $netdata->contexts()->list();

foreach ($contexts as $context) {
    echo "{$context->id} ({$context->family}) - {$context->units}\n";
}

// Get a single context
$ctx = $netdata->contexts()->get('system.cpu');
echo "Priority: {$ctx->priority}, Units: {$ctx->units}\n";

The Context DTO provides: id, name, family, chartType, units, priority, firstEntry, lastEntry.

Alerts

$alerts = $netdata->alerts()->list();

foreach ($alerts as $alert) {
    echo "{$alert->name}: {$alert->status->value} ({$alert->chart})\n";
}

// Filter by status
$critical = $netdata->alerts()->list(status: 'CRITICAL');

// Alert transitions (history)
$transitions = $netdata->alerts()->transitions(after: -86400);

// Alert configuration by hash ID
$config = $netdata->alerts()->config();

The Alert DTO provides: name, chart, status (enum: critical, warning, clear, undefined, uninitialized), value, units, info, lastStatusChange.

Weights Analysis

use DavitVardanyan\Netdata\Requests\WeightsRequest;
use DavitVardanyan\Netdata\Enums\WeightsMethod;

$request = WeightsRequest::make()
    ->contexts('system.cpu')
    ->after(-600)
    ->before(0)
    ->method(WeightsMethod::Ks2)
    ->baseline(-1200, -600);

$weights = $netdata->weights()->query($request);

Agent Info

$info = $netdata->info()->get();
echo "Agent {$info->version} on {$info->hostname}\n";
echo "OS: {$info->os}, Arch: {$info->architecture}, CPUs: {$info->cpus}\n";

// Other info endpoints
$versions = $netdata->info()->versions();
$me = $netdata->info()->me();
$settings = $netdata->info()->settings();

Functions

// List available functions
$functions = $netdata->functions()->list();

// Execute a function
$result = $netdata->functions()->execute('processes');

Search

$results = $netdata->search()->query('cpu');
// Returns raw array with keys: nodes, contexts, searches, etc.

Badges

$svg = $netdata->badges()->svg('system.cpu', dimension: 'user');
// Returns raw SVG string

All Metrics Export

use DavitVardanyan\Netdata\Enums\AllMetricsFormat;

// Prometheus format
$metrics = $netdata->allMetrics()->get(AllMetricsFormat::Prometheus);

// JSON format
$metrics = $netdata->allMetrics()->get(AllMetricsFormat::Json);

Configuration

// Get full config tree
$tree = $netdata->config()->tree();

// Get specific config
$item = $netdata->config()->get('some-config-id');

// Update config
$result = $netdata->config()->update(['key' => 'value']);

// Get variables
$vars = $netdata->config()->variable(chart: 'system.cpu');

Stream Path & Claiming

// Stream path info
$paths = $netdata->streamPath()->get();

// Claim info
$claim = $netdata->claim()->info();

Custom HTTP Client

Implement HttpClientInterface to use your own HTTP client:

use DavitVardanyan\Netdata\Contracts\HttpClientInterface;

class MyHttpClient implements HttpClientInterface
{
    public function get(string $uri, array $query = [], array $headers = []): array
    {
        // Must return ['status' => int, 'headers' => array, 'body' => array]
    }

    public function post(string $uri, array $data = [], array $headers = []): array
    {
        // Must return ['status' => int, 'headers' => array, 'body' => array]
    }

    public function getRaw(string $uri, array $query = [], array $headers = []): string
    {
        // Must return raw response body as string
    }
}

$netdata = new NetdataClient(
    config: new Config(token: 'your-token'),
    httpClient: new MyHttpClient(),
);

Logging

Pass any PSR-3 compatible logger:

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

$logger = new Logger('netdata');
$logger->pushHandler(new StreamHandler('php://stderr', Logger::DEBUG));

$netdata = new NetdataClient(
    config: new Config(token: 'your-token'),
    logger: $logger,
);

Requests and responses are logged at debug level. Retry attempts are logged at warning level.

Error Handling

All exceptions extend NetdataException:

use DavitVardanyan\Netdata\Exceptions\AuthenticationException;
use DavitVardanyan\Netdata\Exceptions\NotFoundException;
use DavitVardanyan\Netdata\Exceptions\RateLimitException;
use DavitVardanyan\Netdata\Exceptions\ValidationException;
use DavitVardanyan\Netdata\Exceptions\ApiException;
use DavitVardanyan\Netdata\Exceptions\NetdataException;

try {
    $nodes = $netdata->nodes()->list();
} catch (AuthenticationException $e) {
    // 401 - Invalid or expired token
} catch (NotFoundException $e) {
    // 404 - Resource not found
} catch (RateLimitException $e) {
    // 429 - Rate limited (auto-retried by default)
    $retryAfter = $e->retryAfter; // seconds until retry is safe
} catch (ValidationException $e) {
    // 422 - Invalid request parameters
} catch (ApiException $e) {
    // 5xx - Server errors (auto-retried by default)
} catch (NetdataException $e) {
    // Base exception - catches all of the above
    $responseBody = $e->responseBody; // raw API response
}
Exception HTTP Status Auto-Retry
AuthenticationException 401 No
NotFoundException 404 No
ValidationException 422 No
RateLimitException 429 Yes
ApiException 5xx Yes

Testing

Use NetdataFake to mock API calls in your tests:

use DavitVardanyan\Netdata\Testing\NetdataFake;

$fake = NetdataFake::create()
    ->fakeNodes([
        ['id' => 'node-1', 'name' => 'web-server', 'os' => 'linux'],
        ['id' => 'node-2', 'name' => 'db-server', 'os' => 'linux'],
    ])
    ->fakeAlerts([
        'alerts' => [
            ['nm' => 'cpu_high', 'sum' => 'CPU usage is high', 'cr' => 0, 'wr' => 1, 'cl' => 0, 'ctx' => ['system.cpu']],
        ],
    ])
    ->fakeInfo([
        'version' => 'v2.9.0', 'uid' => 'uid', 'hostname' => 'host',
        'os' => 'linux', 'architecture' => 'x86_64', 'cpus' => 4, 'host_labels' => [],
    ]);

$client = $fake->toClient();

// Use in your tests
$nodes = $client->nodes()->list();
assert($nodes->count() === 2);

// Assert calls were made
$fake->assertCalled('/api/v3/nodes');
$fake->assertCalledTimes('/api/v3/nodes', 1);
$fake->assertNothingSent(); // fails if any calls were recorded

Convenience Fake Methods

$fake = NetdataFake::create()
    ->fakeData([...])           // /api/v3/data
    ->fakeNodes([...])          // /api/v3/nodes
    ->fakeAlerts([...])         // /api/v3/alerts
    ->fakeContexts([...])       // /api/v3/contexts
    ->fakeWeights([...])        // /api/v3/weights
    ->fakeInfo([...])           // /api/v3/info
    ->fakeFunctions([...])      // /api/v3/functions
    ->fakeSearch([...]);        // /api/v3/q

Faking Raw Responses

$fake = NetdataFake::create()
    ->fakeRawResponse('/api/v3/badge.svg', '<svg>badge</svg>')
    ->fakeRawResponse('/api/v3/allmetrics', 'system_cpu{dim="user"} 12.5');

Faking Arbitrary Responses

$fake = NetdataFake::create()
    ->fakeResponse('/api/v3/alert_config', ['configs' => [...]]);

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Run the quality checks:
    composer install
    vendor/bin/phpunit
    vendor/bin/phpstan analyse
    vendor/bin/php-cs-fixer fix
  4. Commit your changes
  5. Push to the branch
  6. Open a Pull Request

License

The MIT License (MIT). See LICENSE for more information.