v2 API Reference
Data Types
cpp
// V2 query variable
struct V2Query {
std::string name; // variable name, e.g. "q0"
std::string query; // metric DQL, e.g. "avg:system.cpu.user{*}"
std::string data_source = "metrics";
};
// Optional formula combining query variables
struct V2Formula {
std::string formula; // e.g. "q0 / q1"
std::string aggregator; // for scalar: "avg","sum","min","max","last"
};
// One series in a timeseries response
struct V2Series {
int32_t query_index;
std::vector<std::string> group_tags; // e.g. ["host:web01"]
std::vector<double> values; // parallel to V2Batch.times; NaN = no data
};
// One chunk of timeseries data
struct V2Batch {
std::vector<int64_t> times; // Unix milliseconds
std::vector<V2Series> series;
int64_t chunk_start_ms, chunk_end_ms;
bool is_last;
};
// One chunk of scalar aggregated data
struct V2ScalarBatch {
std::vector<V2ScalarColumn> columns; // {name, values[]}
int64_t chunk_start_ms, chunk_end_ms;
bool is_last;
};Multi-Query
The v2 API supports multiple named query variables in a single request. Each series
in the response carries a query_index indicating which query produced it, plus
optional group_tags from the Datadog group-by clause.
python
import _ddstream as dd, time
cfg = dd.DDStreamV2Config()
cfg.api_key = "YOUR_DD_API_KEY"
cfg.app_key = "YOUR_DD_APP_KEY"
cfg.range_start = int(time.time()) - 3600
cfg.range_end = int(time.time())
q0 = dd.V2Query(); q0.name = "q0"; q0.query = "avg:system.cpu.user{*}"
q1 = dd.V2Query(); q1.name = "q1"; q1.query = "avg:system.cpu.system{*}"
cfg.queries = [q0, q1]
ts = dd.DDStreamV2Timeseries(cfg)
for batch in ts:
for series in batch["series"]:
qi = series["query_index"]
tags = series["group_tags"]
vals = series["values"]
print(f"q{qi} {tags}: mean={vals.mean():.2f}")Formulas
Formulas let you combine query variables with arithmetic. For scalar endpoints,
each formula must specify an aggregator field.
python
q0 = dd.V2Query(); q0.name = "q0"; q0.query = "avg:system.cpu.user{*}"
q1 = dd.V2Query(); q1.name = "q1"; q1.query = "avg:system.cpu.system{*}"
f = dd.V2Formula()
f.formula = "q0 + q1"
f.aggregator = "avg" # required for scalar endpoint
cfg.queries = [q0, q1]
cfg.formulas = [f]Timeseries C API
c
// Handle lifecycle
DDStreamV2TSHandle* ddstream_v2_ts_create(const DDStreamV2Config_C* cfg);
void ddstream_v2_ts_destroy(DDStreamV2TSHandle* h);
void ddstream_v2_ts_reset(DDStreamV2TSHandle* h);
void ddstream_v2_ts_cancel(DDStreamV2TSHandle* h);
// State
int32_t ddstream_v2_ts_has_next(DDStreamV2TSHandle* h);
double ddstream_v2_ts_progress(DDStreamV2TSHandle* h);
const char* ddstream_v2_ts_last_error(DDStreamV2TSHandle* h);
// Fetch - returns 1=ready, 0=done, -1=error
int32_t ddstream_v2_ts_next_batch(DDStreamV2TSHandle* h,
DDStreamV2BatchInfo* info_out);
// Access current batch (valid until next next_batch call)
const int64_t* ddstream_v2_ts_get_times(DDStreamV2TSHandle* h);
int32_t ddstream_v2_ts_get_series(DDStreamV2TSHandle* h,
int32_t idx, int32_t* qi_out, const double** vals_out);
const char* ddstream_v2_ts_get_series_group_tags(DDStreamV2TSHandle* h,
int32_t idx); // returns JSON array string
// Credential probe
int32_t ddstream_v2_ts_validate(const DDStreamV2Config_C* cfg,
char* err_buf, int32_t err_buf_size);Scalar C API
c
DDStreamV2SCHandle* ddstream_v2_sc_create(const DDStreamV2Config_C* cfg);
void ddstream_v2_sc_destroy(DDStreamV2SCHandle* h);
void ddstream_v2_sc_reset(DDStreamV2SCHandle* h);
void ddstream_v2_sc_cancel(DDStreamV2SCHandle* h);
int32_t ddstream_v2_sc_has_next(DDStreamV2SCHandle* h);
double ddstream_v2_sc_progress(DDStreamV2SCHandle* h);
const char* ddstream_v2_sc_last_error(DDStreamV2SCHandle* h);
int32_t ddstream_v2_sc_next_batch(DDStreamV2SCHandle* h,
DDStreamV2ScalarBatchInfo* info_out);
// Access columns (valid until next next_batch call)
const char* ddstream_v2_sc_get_column_name(DDStreamV2SCHandle* h, int32_t col);
int32_t ddstream_v2_sc_get_column_values(DDStreamV2SCHandle* h, int32_t col,
const double** vals_out, int32_t* count_out);
int32_t ddstream_v2_sc_validate(const DDStreamV2Config_C* cfg,
char* err_buf, int32_t err_buf_size);Pointer Lifetime
Pointers are invalidated on next_batch()
All pointers returned by get_series, get_times, and get_column_values are
invalidated on the next call to next_batch() (or reset()). Language
bindings must copy the data before advancing the stream.
