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.
- 13 resource classes covering 22
/api/v3/*endpoints - Rich DTOs (
Node,MetricData,Alert,Context,AgentInfo) with automatic v3 response parsing MetricDatawithdimension(),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
NetdataFakefor easy testing with call assertions- Swappable HTTP client via
HttpClientInterface - Optional PSR-3 logger support
- PHPStan level 9 and PSR-12 compliant
composer require davit-vardanyan/netdata-phpuse 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";
}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) |
| 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 |
// 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();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().
$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$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.
$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 = $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.
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);$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();// List available functions
$functions = $netdata->functions()->list();
// Execute a function
$result = $netdata->functions()->execute('processes');$results = $netdata->search()->query('cpu');
// Returns raw array with keys: nodes, contexts, searches, etc.$svg = $netdata->badges()->svg('system.cpu', dimension: 'user');
// Returns raw SVG stringuse DavitVardanyan\Netdata\Enums\AllMetricsFormat;
// Prometheus format
$metrics = $netdata->allMetrics()->get(AllMetricsFormat::Prometheus);
// JSON format
$metrics = $netdata->allMetrics()->get(AllMetricsFormat::Json);// 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 info
$paths = $netdata->streamPath()->get();
// Claim info
$claim = $netdata->claim()->info();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(),
);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.
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 |
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$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$fake = NetdataFake::create()
->fakeRawResponse('/api/v3/badge.svg', '<svg>badge</svg>')
->fakeRawResponse('/api/v3/allmetrics', 'system_cpu{dim="user"} 12.5');$fake = NetdataFake::create()
->fakeResponse('/api/v3/alert_config', ['configs' => [...]]);- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Run the quality checks:
composer install vendor/bin/phpunit vendor/bin/phpstan analyse vendor/bin/php-cs-fixer fix
- Commit your changes
- Push to the branch
- Open a Pull Request
The MIT License (MIT). See LICENSE for more information.