mirror of https://github.com/sysown/proxysql
pull/5383/head
parent
f17e999830
commit
da877c378b
@ -1,224 +1,38 @@
|
||||
# TSDB Architecture
|
||||
|
||||
## System Design
|
||||
## Runtime Components
|
||||
|
||||
The TSDB subsystem is an extension of the existing `ProxySQL_Statistics` module, leveraging its proven SQLite-based storage infrastructure.
|
||||
- `ProxySQL_Admin` main loop triggers three TSDB schedulers:
|
||||
- sampler (`tsdb_sampler_loop`)
|
||||
- downsampler (`tsdb_downsample_metrics`)
|
||||
- backend monitor (`tsdb_monitor_loop`)
|
||||
- Data is stored in `statsdb_disk` SQLite tables.
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────────┐
|
||||
│ ProxySQL Core │
|
||||
├─────────────────────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────────────────────────────────────────────────────────────────┐ │
|
||||
│ │ ProxySQL_Statistics │ │
|
||||
│ │ (SQLite3DB *statsdb_disk) │ │
|
||||
│ ├──────────────────────────────────────────────────────────────────────┤ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │
|
||||
│ │ │ tsdb_metrics │ │tsdb_metrics_hour│ │tsdb_backend_ │ │ │
|
||||
│ │ │ │ │ │ │ health │ │ │
|
||||
│ │ │ • timestamp │ │ • bucket │ │ • timestamp │ │ │
|
||||
│ │ │ • metric_name │ │ • metric_name │ │ • hostgroup │ │ │
|
||||
│ │ │ • labels (JSON) │ │ • labels (JSON) │ │ • hostname │ │ │
|
||||
│ │ │ • value (REAL) │ │ • avg_value │ │ • port │ │ │
|
||||
│ │ │ │ │ • max_value │ │ • probe_up │ │ │
|
||||
│ │ │ PRIMARY KEY: │ │ • min_value │ │ • connect_ms │ │ │
|
||||
│ │ │ (timestamp, │ │ • count │ │ │ │ │
|
||||
│ │ │ metric_name) │ │ │ │ PRIMARY KEY: │ │ │
|
||||
│ │ │ │ │ PRIMARY KEY: │ │ (timestamp, │ │ │
|
||||
│ │ │ WITHOUT ROWID │ │ (bucket, │ │ hostgroup, │ │ │
|
||||
│ │ │ │ │ metric_name) │ │ hostname, port)│ │ │
|
||||
│ │ │ │ │ │ │ │ │ │
|
||||
│ │ │ Retention: 7d │ │ Retention: 1y │ │ Retention: 7d │ │ │
|
||||
│ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └──────────────────────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
## Data Path
|
||||
|
||||
## Components
|
||||
1. Sampler collects all metric families from `GloVars.prometheus_registry->Collect()`.
|
||||
2. Samples are normalized and inserted into `tsdb_metrics`.
|
||||
3. Hourly job aggregates into `tsdb_metrics_hour`.
|
||||
4. Backend monitor probes servers from `runtime_mysql_servers` and stores in `tsdb_backend_health`.
|
||||
5. Retention cleanup removes old raw/probe data using configured days.
|
||||
|
||||
### 1. Sampler Thread (`tsdb_sampler_loop()`)
|
||||
## Metric Family Handling
|
||||
|
||||
**Purpose:** Collect metrics from Prometheus registry
|
||||
|
||||
**Frequency:** Every `stats_tsdb_sample_interval` seconds
|
||||
|
||||
**Process:**
|
||||
1. Check if tsdb_sampler_timetoget() returns true
|
||||
2. If GloVars.prometheus_registry exists:
|
||||
- Collect all metric families
|
||||
- For each metric, extract labels
|
||||
- Insert into tsdb_metrics table
|
||||
3. Call tsdb_downsample_metrics()
|
||||
|
||||
### 2. Monitor Thread (`tsdb_monitor_loop()`)
|
||||
|
||||
**Purpose:** Active TCP probes to backend servers
|
||||
|
||||
**Frequency:** Every `stats_tsdb_monitor_interval` seconds
|
||||
|
||||
**Process:**
|
||||
1. Check if tsdb_monitor_timetoget() returns true
|
||||
2. Query runtime_mysql_servers for active backends
|
||||
3. For each backend:
|
||||
- Create TCP socket
|
||||
- Measure connect time
|
||||
- Record success/failure
|
||||
- Insert into tsdb_backend_health
|
||||
|
||||
### 3. Compactor (`tsdb_downsample_metrics()`)
|
||||
|
||||
**Purpose:** Automatic downsampling and retention enforcement
|
||||
|
||||
**Frequency:** Every hour (triggered during sampler loop)
|
||||
|
||||
**Process:**
|
||||
1. Get MAX(bucket) from tsdb_metrics_hour
|
||||
2. For each hour bucket not yet processed:
|
||||
- Aggregate raw data (AVG, MAX, MIN, COUNT)
|
||||
- Insert into tsdb_metrics_hour
|
||||
3. Delete raw data older than 7 days
|
||||
4. Delete hourly data older than 1 year
|
||||
|
||||
**SQL Operations:**
|
||||
```sql
|
||||
-- Downsample raw data to hourly aggregates
|
||||
INSERT OR REPLACE INTO tsdb_metrics_hour
|
||||
SELECT
|
||||
(timestamp/3600)*3600 as bucket,
|
||||
metric_name,
|
||||
labels,
|
||||
AVG(value) as avg_value,
|
||||
MAX(value) as max_value,
|
||||
MIN(value) as min_value,
|
||||
COUNT(*) as count
|
||||
FROM tsdb_metrics
|
||||
WHERE timestamp >= ? AND timestamp < ?
|
||||
GROUP BY bucket, metric_name, labels;
|
||||
|
||||
-- Enforce retention
|
||||
DELETE FROM tsdb_metrics WHERE timestamp < unixepoch() - 7*86400;
|
||||
DELETE FROM tsdb_metrics_hour WHERE bucket < unixepoch() - 365*86400;
|
||||
```
|
||||
|
||||
### 4. Query Engine
|
||||
|
||||
**Purpose:** Serve metric queries via SQL and HTTP API
|
||||
|
||||
**Key Methods:**
|
||||
- `query_tsdb_metrics()` - Query with label filters
|
||||
- `get_backend_health_metrics()` - Query backend health
|
||||
- `get_tsdb_status()` - Get TSDB statistics
|
||||
|
||||
**Label Filtering:**
|
||||
```sql
|
||||
-- Query with label filter using JSON_EXTRACT
|
||||
SELECT * FROM tsdb_metrics
|
||||
WHERE metric_name = 'mysql_connections'
|
||||
AND json_extract(labels, '$.hostgroup') = '1'
|
||||
AND timestamp BETWEEN 1704067200 AND 1704153600;
|
||||
```
|
||||
|
||||
## Data Flow Diagrams
|
||||
|
||||
### Metric Ingestion Flow
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ Metric Source │
|
||||
│ (Prometheus) │
|
||||
└────────┬─────────┘
|
||||
│ Collect()
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ tsdb_sampler_ │
|
||||
│ loop() │
|
||||
│ │
|
||||
│ • Extract labels│
|
||||
│ • Convert JSON │
|
||||
│ • Prepare stmt │
|
||||
└────────┬─────────┘
|
||||
│ INSERT
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ SQLite3 │
|
||||
│ (tsdb_metrics) │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
### Health Probe Flow
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ runtime_mysql_ │
|
||||
│ servers │
|
||||
└────────┬─────────┘
|
||||
│ SELECT
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ tsdb_monitor_ │
|
||||
│ loop() │
|
||||
│ │
|
||||
│ • TCP connect │
|
||||
│ • Measure time │
|
||||
│ • Record status │
|
||||
└────────┬─────────┘
|
||||
│ INSERT
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ SQLite3 │
|
||||
│ (tsdb_backend_ │
|
||||
│ health) │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## Thread Safety
|
||||
|
||||
The TSDB uses SQLite's built-in concurrency control:
|
||||
|
||||
1. **SQLite WAL Mode** - Write-Ahead Logging for concurrent reads/writes
|
||||
2. **Prepared Statements** - Pre-compiled SQL for thread-safe execution
|
||||
3. **No Additional Locks** - Relies on SQLite's internal locking
|
||||
- Counter/Gauge/Untyped/Info: one sample per metric point.
|
||||
- Summary: quantiles plus `_sum` and `_count` companion metrics.
|
||||
- Histogram: `_bucket{le=...}` plus `_sum` and `_count` companion metrics.
|
||||
|
||||
## Storage Schema
|
||||
|
||||
### tsdb_metrics Table
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| timestamp | INT | Unix timestamp (seconds) |
|
||||
| metric_name | TEXT | Metric identifier |
|
||||
| labels | TEXT | JSON object with label key-value pairs |
|
||||
| value | REAL | Metric value |
|
||||
|
||||
**Primary Key:** (timestamp, metric_name)
|
||||
**Storage:** WITHOUT ROWID
|
||||
|
||||
### tsdb_metrics_hour Table
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| bucket | INT | Hour bucket (unix timestamp rounded to hour) |
|
||||
| metric_name | TEXT | Metric identifier |
|
||||
| labels | TEXT | JSON labels |
|
||||
| avg_value | REAL | Average value in bucket |
|
||||
| max_value | REAL | Maximum value in bucket |
|
||||
| min_value | REAL | Minimum value in bucket |
|
||||
| count | INT | Number of samples in bucket |
|
||||
- `tsdb_metrics`: PK `(timestamp, metric_name, labels)`
|
||||
- `tsdb_metrics_hour`: PK `(bucket, metric_name, labels)`
|
||||
- `tsdb_backend_health`: PK `(timestamp, hostgroup, hostname, port)`
|
||||
|
||||
**Primary Key:** (bucket, metric_name)
|
||||
**Storage:** WITHOUT ROWID
|
||||
## Configuration Lifecycle
|
||||
|
||||
### tsdb_backend_health Table
|
||||
TSDB configuration is part of ADMIN variables (`admin-stats_tsdb_*`) and is applied with:
|
||||
|
||||
| Column | Type | Description |
|
||||
|--------|------|-------------|
|
||||
| timestamp | INT | Unix timestamp |
|
||||
| hostgroup | INT | Backend hostgroup ID |
|
||||
| hostname | TEXT | Backend hostname |
|
||||
| port | INT | Backend port |
|
||||
| probe_up | INT | 1=success, 0=failure |
|
||||
| connect_ms | INT | Connection time in milliseconds |
|
||||
- `LOAD ADMIN VARIABLES TO RUNTIME`
|
||||
- `SAVE ADMIN VARIABLES TO DISK`
|
||||
|
||||
**Primary Key:** (timestamp, hostgroup, hostname, port)
|
||||
**Storage:** WITHOUT ROWID
|
||||
No dedicated TSDB load/save command family is implemented.
|
||||
|
||||
@ -1,31 +1,26 @@
|
||||
# Embedded TSDB Metrics Catalog
|
||||
|
||||
The following metrics are curated and stored by the TSDB sampler.
|
||||
The TSDB sampler records all metric families exposed by the built-in Prometheus registry.
|
||||
|
||||
## Traffic / Latency
|
||||
| Metric | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `proxysql_queries_total` | Counter | Total number of queries processed. |
|
||||
| `proxysql_query_errors_total` | Counter | Total number of query errors. |
|
||||
| `proxysql_query_latency_ms` | Gauge | p50, p95, and p99 query latency (derived). |
|
||||
## Family Coverage
|
||||
|
||||
## Connections
|
||||
| Metric | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `proxysql_frontend_connections` | Gauge | Number of active client connections. |
|
||||
| `proxysql_backend_connections` | Gauge | Number of active backend connections (by hostgroup/backend). |
|
||||
| `proxysql_connection_pool_saturation` | Gauge | Percentage of pool usage. |
|
||||
- Counter
|
||||
- Gauge
|
||||
- Summary
|
||||
- Histogram
|
||||
- Info
|
||||
- Untyped
|
||||
|
||||
## Backend Health (Probes)
|
||||
| Metric | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `backend_probe_up` | Gauge | 1 if backend is reachable, 0 otherwise. |
|
||||
| `backend_probe_connect_ms` | Gauge | TCP connection latency in ms. |
|
||||
| `backend_state` | Gauge | Current state of the backend (Enum). |
|
||||
## Stored Series Conventions
|
||||
|
||||
## Proxy Health
|
||||
| Metric | Type | Description |
|
||||
| --- | --- | --- |
|
||||
| `proxysql_uptime_seconds` | Gauge | Uptime of the ProxySQL process. |
|
||||
| `proxysql_memory_bytes` | Gauge | Resident set size (RSS) memory usage. |
|
||||
| `tsdb_series_count` | Gauge | Number of active series in the TSDB. |
|
||||
- Counter/Gauge/Untyped/Info: stored as metric name exactly as exposed.
|
||||
- Summary:
|
||||
- quantiles in `<metric>` with `quantile` label
|
||||
- `<metric>_sum`
|
||||
- `<metric>_count`
|
||||
- Histogram:
|
||||
- buckets in `<metric>_bucket` with `le` label
|
||||
- `<metric>_sum`
|
||||
- `<metric>_count`
|
||||
|
||||
Because the source registry can evolve, there is no fixed hardcoded metric list in TSDB code.
|
||||
|
||||
@ -1,184 +1,43 @@
|
||||
# Embedded TSDB Overview
|
||||
|
||||
## What is the TSDB?
|
||||
## What It Is
|
||||
|
||||
The **ProxySQL TSDB** (Time Series Database) is an **embedded, lightweight time-series database** built directly into ProxySQL using SQLite. It provides:
|
||||
The ProxySQL TSDB is an embedded SQLite-based time-series store implemented in `ProxySQL_Statistics`.
|
||||
It records Prometheus metrics and optional backend TCP probe health into `statsdb_disk`.
|
||||
|
||||
- **Historical metric storage** - Persist query statistics, connection counts, backend health
|
||||
- **Built-in monitoring** - Active health checks for all backend servers
|
||||
- **SQL interface** - Query metrics using standard SQL
|
||||
- **HTTP API** - RESTful endpoints for metric retrieval
|
||||
- **Prometheus integration** - Sample Prometheus metrics into TSDB
|
||||
## What It Currently Implements
|
||||
|
||||
### Key Benefits
|
||||
- Storage in SQLite tables:
|
||||
- `tsdb_metrics` (raw samples)
|
||||
- `tsdb_metrics_hour` (hourly rollups)
|
||||
- `tsdb_backend_health` (backend probes)
|
||||
- Periodic sampling from the built-in Prometheus registry.
|
||||
- Sampling of all Prometheus metric families:
|
||||
- Counter, Gauge, Summary, Histogram, Info, Untyped.
|
||||
- Optional backend TCP probe loop for `runtime_mysql_servers`.
|
||||
- Hourly downsampling and retention cleanup.
|
||||
- Query access via SQL on `statsdb_disk.*` tables.
|
||||
|
||||
| Benefit | Description |
|
||||
|---------|-------------|
|
||||
| **Zero external dependencies** | Uses existing SQLite infrastructure, no additional services required |
|
||||
| **Always-on monitoring** | Built-in backend health checks |
|
||||
| **Historical analysis** | Debug past performance issues |
|
||||
| **Simple setup** | Enable with a single SQL command |
|
||||
| **Production-ready** | Leverages battle-tested ProxySQL_Statistics system |
|
||||
| **SQL queries** | Query metrics using familiar SQL syntax |
|
||||
## Configuration Model
|
||||
|
||||
## Architecture Overview
|
||||
TSDB settings are standard ADMIN variables and use the normal ADMIN load/save lifecycle:
|
||||
|
||||
The TSDB subsystem extends the existing `ProxySQL_Statistics` module with three SQLite tables:
|
||||
- `SET admin-stats_tsdb_...`
|
||||
- `LOAD ADMIN VARIABLES TO RUNTIME`
|
||||
- `SAVE ADMIN VARIABLES TO DISK`
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ ProxySQL_Statistics │
|
||||
│ (SQLite) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌──────────────────┐ ┌──────────────────┐ │
|
||||
│ │ tsdb_metrics │ │ tsdb_metrics_hour│ │
|
||||
│ │ (raw data) │ │ (downsampled) │ │
|
||||
│ └──────────────────┘ └──────────────────┘ │
|
||||
│ ┌──────────────────┐ │
|
||||
│ │tsdb_backend_health│ │
|
||||
│ │ (health probes) │ │
|
||||
│ └──────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
There is no separate `LOAD/SAVE TSDB VARIABLES ...` command set.
|
||||
|
||||
### Data Flow
|
||||
## Variables
|
||||
|
||||
```
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ Prometheus │ │ Backend Servers │
|
||||
│ Registry │ │ │
|
||||
└────────┬─────────┘ └────────┬─────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────────┐ ┌──────────────────┐
|
||||
│ tsdb_sampler_ │ │ tsdb_monitor_ │
|
||||
│ loop() │ │ loop() │
|
||||
└────────┬─────────┘ └────────┬─────────┘
|
||||
│ │
|
||||
└──────────┬─────────────┘
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ SQLite Tables │
|
||||
│ (tsdb_metrics) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
▼ ▼ ▼
|
||||
┌──────────┐ ┌────────┐ ┌──────────┐
|
||||
│ HTTP API │ │ Admin │ │ Automatic│
|
||||
│ │ │Commands│ │Compaction│
|
||||
└──────────┘ └────────┘ └──────────┘
|
||||
```
|
||||
- `admin-stats_tsdb_enabled` (0/1)
|
||||
- `admin-stats_tsdb_sample_interval` (1..3600 seconds)
|
||||
- `admin-stats_tsdb_retention_days` (1..3650)
|
||||
- `admin-stats_tsdb_monitor_enabled` (0/1)
|
||||
- `admin-stats_tsdb_monitor_interval` (1..3600 seconds)
|
||||
|
||||
### Storage Architecture
|
||||
## Retention
|
||||
|
||||
| Table | Purpose | Retention |
|
||||
|-------|---------|-----------|
|
||||
| `tsdb_metrics` | Raw metric samples | 7 days |
|
||||
| `tsdb_metrics_hour` | Hourly aggregates (avg, max, min, count) | 1 year |
|
||||
| `tsdb_backend_health` | Backend health probe results | 7 days |
|
||||
|
||||
### Automatic Downsampling
|
||||
|
||||
```
|
||||
Raw Data (tsdb_metrics) Hourly Aggregates (tsdb_metrics_hour)
|
||||
┌─────────────────────┐ ┌──────────────────────────────────────┐
|
||||
│ Time │ Metric │ Val│ │ Bucket │ Metric │ Avg │ Max │ Min │ N│
|
||||
├─────────────────────┤ ├──────────────────────────────────────┤
|
||||
│ 10:01│ cpu │ 50│ ──▶ │ 10:00 │ cpu │ 52 │ 80 │ 20 │12│
|
||||
│ 10:05│ cpu │ 55│ ──▶ │ 11:00 │ cpu │ 48 │ 75 │ 25 │12│
|
||||
│ 10:10│ cpu │ 60│ ──▶ │ ... │ │ │ │ │ │
|
||||
│ ... │ │ │ └──────────────────────────────────────┘
|
||||
└─────────────────────┘
|
||||
7 days 1 year
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```sql
|
||||
-- Enable TSDB
|
||||
SET admin-stats_tsdb_enabled='true';
|
||||
LOAD ADMIN VARIABLES TO RUNTIME;
|
||||
|
||||
-- Access metrics via SQL
|
||||
SELECT * FROM statsdb_disk.tsdb_metrics
|
||||
WHERE metric_name = 'mysql_connections'
|
||||
AND timestamp > unixepoch() - 3600;
|
||||
|
||||
-- Query via HTTP API
|
||||
-- curl "http://admin:admin@localhost:6032/api/tsdb/query?metric=mysql_connections&from=-1h"
|
||||
```
|
||||
|
||||
## What Gets Monitored?
|
||||
|
||||
### 1. Traffic Metrics (from Prometheus Registry)
|
||||
- Query counts and latency
|
||||
- Frontend connections
|
||||
- Backend connections
|
||||
- Query cache stats
|
||||
|
||||
### 2. Backend Health (active probes)
|
||||
- TCP connect success/failure
|
||||
- Connection latency (milliseconds)
|
||||
- Per-hostgroup, per-host, per-port tracking
|
||||
|
||||
### 3. System Health
|
||||
- TSDB internal stats
|
||||
- Storage usage
|
||||
|
||||
## Design Principles
|
||||
|
||||
### SQLite-Based Storage
|
||||
|
||||
- **ACID compliance** - Transactions ensure data integrity
|
||||
- **Indexed queries** - Fast time-range lookups
|
||||
- **JSON labels** - Flexible label storage with JSON extraction
|
||||
- **SQL interface** - Query using standard SQL
|
||||
|
||||
### Bounded Resources
|
||||
|
||||
| Limit | Default | Purpose |
|
||||
|-------|---------|---------|
|
||||
| `stats_tsdb_retention_days` | 7 | Raw data retention |
|
||||
| `stats_tsdb_sample_interval` | 5 sec | Metric sampling rate |
|
||||
| `stats_tsdb_monitor_interval` | 10 sec | Health probe interval |
|
||||
|
||||
### Thread Safety
|
||||
|
||||
- Uses existing `ProxySQL_Statistics` locking
|
||||
- SQLite prepared statements for concurrent access
|
||||
- Atomic configuration updates
|
||||
|
||||
## Configuration at a Glance
|
||||
|
||||
| Variable | Default | Description |
|
||||
|----------|---------|-------------|
|
||||
| `stats_tsdb_enabled` | `0` | Master switch (0=off, 1=on) |
|
||||
| `stats_tsdb_sample_interval` | `5` | How often to sample metrics (seconds) |
|
||||
| `stats_tsdb_retention_days` | `7` | How long to keep raw data |
|
||||
| `stats_tsdb_monitor_enabled` | `0` | Enable backend health monitoring |
|
||||
| `stats_tsdb_monitor_interval` | `10` | How often to probe backends (seconds) |
|
||||
|
||||
See the [Reference Manual](./embedded_tsdb_reference.md) for complete configuration documentation.
|
||||
|
||||
## When to Use TSDB
|
||||
|
||||
| Use Case | Recommended |
|
||||
|----------|-------------|
|
||||
| **Quick troubleshooting** | Ideal - last 7 days of data |
|
||||
| **Performance analysis** | Identify slow queries, bottlenecks |
|
||||
| **Backend monitoring** | Track backend health over time |
|
||||
| **Long-term analytics** | Use external system (Prometheus/Grafana) |
|
||||
|
||||
## When NOT to Use TSDB
|
||||
|
||||
- **Long-term retention** (> 1 week) - Use external TSDB
|
||||
- **High-cardinality data** - Thousands of unique series may impact performance
|
||||
- **Complex analytics** - Use external query/BI tools
|
||||
- **Cross-server aggregation** - Use external monitoring
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Read the Architecture** - [architecture.md](./embedded_tsdb_architecture.md)
|
||||
2. **Explore the API** - [reference.md](./embedded_tsdb_reference.md)
|
||||
3. **Check the Specs** - [specs.md](./embedded_tsdb_specs.md)
|
||||
- Raw metrics (`tsdb_metrics`): `admin-stats_tsdb_retention_days`
|
||||
- Backend probes (`tsdb_backend_health`): `admin-stats_tsdb_retention_days`
|
||||
- Hourly rollups (`tsdb_metrics_hour`): fixed 365 days
|
||||
|
||||
@ -1,168 +1,58 @@
|
||||
# TSDB Quickstart Guide
|
||||
|
||||
## Enable TSDB
|
||||
## 1. Enable TSDB
|
||||
|
||||
```sql
|
||||
-- Enable TSDB
|
||||
SET admin-stats_tsdb_enabled='1';
|
||||
LOAD ADMIN VARIABLES TO RUNTIME;
|
||||
SAVE ADMIN VARIABLES TO DISK;
|
||||
```
|
||||
|
||||
## Verify Tables Created
|
||||
Optional backend probe collection:
|
||||
|
||||
```sql
|
||||
-- Check TSDB tables exist
|
||||
SELECT name FROM statsdb_disk.sqlite_master
|
||||
WHERE type='table' AND name LIKE 'tsdb%';
|
||||
```
|
||||
|
||||
Expected output:
|
||||
```
|
||||
+----------------------+
|
||||
| name |
|
||||
+----------------------+
|
||||
| tsdb_metrics |
|
||||
| tsdb_metrics_hour |
|
||||
| tsdb_backend_health |
|
||||
+----------------------+
|
||||
SET admin-stats_tsdb_monitor_enabled='1';
|
||||
LOAD ADMIN VARIABLES TO RUNTIME;
|
||||
SAVE ADMIN VARIABLES TO DISK;
|
||||
```
|
||||
|
||||
## Query Metrics
|
||||
|
||||
### View Recent Metrics
|
||||
## 2. Verify Tables
|
||||
|
||||
```sql
|
||||
-- Last hour of metrics
|
||||
SELECT
|
||||
datetime(timestamp, 'unixepoch') as time,
|
||||
metric_name,
|
||||
json_extract(labels, '$.hostgroup') as hg,
|
||||
value
|
||||
FROM statsdb_disk.tsdb_metrics
|
||||
WHERE timestamp > unixepoch() - 3600
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 10;
|
||||
SELECT name
|
||||
FROM statsdb_disk.sqlite_master
|
||||
WHERE type='table' AND name LIKE 'tsdb_%';
|
||||
```
|
||||
|
||||
### Query with Filters
|
||||
## 3. Query Raw Samples
|
||||
|
||||
```sql
|
||||
-- Filter by metric name and label
|
||||
SELECT * FROM statsdb_disk.tsdb_metrics
|
||||
WHERE metric_name = 'mysql_connections'
|
||||
AND json_extract(labels, '$.hostgroup') = '1'
|
||||
AND timestamp > unixepoch() - 3600;
|
||||
SELECT datetime(timestamp,'unixepoch') AS ts, metric_name, labels, value
|
||||
FROM statsdb_disk.tsdb_metrics
|
||||
WHERE timestamp > unixepoch() - 300
|
||||
ORDER BY timestamp DESC
|
||||
LIMIT 50;
|
||||
```
|
||||
|
||||
### Hourly Aggregates
|
||||
## 4. Query Hourly Rollups
|
||||
|
||||
```sql
|
||||
-- Daily averages
|
||||
SELECT
|
||||
datetime(bucket, 'unixepoch') as hour,
|
||||
metric_name,
|
||||
avg_value,
|
||||
max_value,
|
||||
count
|
||||
SELECT datetime(bucket,'unixepoch') AS hour, metric_name, avg_value, max_value, min_value, count
|
||||
FROM statsdb_disk.tsdb_metrics_hour
|
||||
WHERE bucket > unixepoch() - 86400
|
||||
ORDER BY bucket;
|
||||
```
|
||||
|
||||
## Enable Backend Health Monitoring
|
||||
## 5. Query Backend Probe Health
|
||||
|
||||
```sql
|
||||
-- Enable health probes
|
||||
SET admin-stats_tsdb_monitor_enabled='1';
|
||||
LOAD ADMIN VARIABLES TO RUNTIME;
|
||||
SAVE ADMIN VARIABLES TO DISK;
|
||||
|
||||
-- Query health status
|
||||
SELECT
|
||||
datetime(timestamp, 'unixepoch') as time,
|
||||
hostgroup,
|
||||
hostname,
|
||||
port,
|
||||
CASE probe_up WHEN 1 THEN 'UP' ELSE 'DOWN' END as status,
|
||||
connect_ms
|
||||
SELECT datetime(timestamp,'unixepoch') AS ts, hostgroup, hostname, port, probe_up, connect_ms
|
||||
FROM statsdb_disk.tsdb_backend_health
|
||||
WHERE timestamp > unixepoch() - 3600
|
||||
ORDER BY timestamp DESC;
|
||||
```
|
||||
|
||||
## Common Queries
|
||||
|
||||
### Connection Count Over Time
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
datetime(timestamp, 'unixepoch') as time,
|
||||
value as connections
|
||||
FROM statsdb_disk.tsdb_metrics
|
||||
WHERE metric_name = 'mysql_connections'
|
||||
AND timestamp > unixepoch() - 3600
|
||||
ORDER BY timestamp;
|
||||
```
|
||||
|
||||
### Backend Availability
|
||||
## Notes
|
||||
|
||||
```sql
|
||||
-- Success rate by backend
|
||||
SELECT
|
||||
hostname,
|
||||
port,
|
||||
SUM(probe_up) as up_count,
|
||||
COUNT(*) as total,
|
||||
ROUND(100.0 * SUM(probe_up) / COUNT(*), 2) as uptime_pct
|
||||
FROM statsdb_disk.tsdb_backend_health
|
||||
WHERE timestamp > unixepoch() - 86400
|
||||
GROUP BY hostname, port;
|
||||
```
|
||||
|
||||
### Top Metrics
|
||||
|
||||
```sql
|
||||
-- Most frequent metrics
|
||||
SELECT
|
||||
metric_name,
|
||||
COUNT(*) as samples
|
||||
FROM statsdb_disk.tsdb_metrics
|
||||
WHERE timestamp > unixepoch() - 3600
|
||||
GROUP BY metric_name
|
||||
ORDER BY samples DESC;
|
||||
```
|
||||
|
||||
## Disable TSDB
|
||||
|
||||
```sql
|
||||
SET admin-stats_tsdb_enabled='0';
|
||||
SET admin-stats_tsdb_monitor_enabled='0';
|
||||
LOAD ADMIN VARIABLES TO RUNTIME;
|
||||
SAVE ADMIN VARIABLES TO DISK;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check if Tables Exist
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM statsdb_disk.sqlite_master WHERE name='tsdb_metrics') as metrics_exists,
|
||||
(SELECT COUNT(*) FROM statsdb_disk.sqlite_master WHERE name='tsdb_metrics_hour') as hourly_exists,
|
||||
(SELECT COUNT(*) FROM statsdb_disk.sqlite_master WHERE name='tsdb_backend_health') as health_exists;
|
||||
```
|
||||
|
||||
### Check Recent Activity
|
||||
|
||||
```sql
|
||||
-- Metrics in last 5 minutes
|
||||
SELECT COUNT(*) as recent_metrics
|
||||
FROM statsdb_disk.tsdb_metrics
|
||||
WHERE timestamp > unixepoch() - 300;
|
||||
|
||||
-- Health probes in last 5 minutes
|
||||
SELECT COUNT(*) as recent_probes
|
||||
FROM statsdb_disk.tsdb_backend_health
|
||||
WHERE timestamp > unixepoch() - 300;
|
||||
```
|
||||
- TSDB settings are ADMIN variables (`admin-stats_tsdb_*`).
|
||||
- There are no `LOAD/SAVE TSDB VARIABLES` commands.
|
||||
|
||||
@ -1,223 +1,47 @@
|
||||
# TSDB Technical Specifications
|
||||
|
||||
## Overview
|
||||
|
||||
The TSDB (Time Series Database) subsystem extends ProxySQL_Statistics with time-series metric storage using SQLite.
|
||||
|
||||
## Design Goals
|
||||
|
||||
1. **Zero External Dependencies** - Uses existing SQLite infrastructure
|
||||
2. **Production Ready** - Leverages battle-tested ProxySQL_Statistics
|
||||
3. **Automatic Maintenance** - Built-in downsampling and retention
|
||||
4. **SQL Interface** - Query using standard SQL
|
||||
|
||||
## Storage Engine
|
||||
|
||||
### SQLite Configuration
|
||||
|
||||
- **Journal Mode**: WAL (Write-Ahead Logging)
|
||||
- **Synchronous**: NORMAL
|
||||
- **Page Size**: 4096 bytes
|
||||
- **Cache Size**: -2000 (2MB)
|
||||
|
||||
### Table Schema
|
||||
|
||||
#### tsdb_metrics
|
||||
|
||||
```sql
|
||||
CREATE TABLE tsdb_metrics (
|
||||
timestamp INT NOT NULL,
|
||||
metric_name TEXT NOT NULL,
|
||||
labels TEXT, -- JSON object
|
||||
value REAL,
|
||||
PRIMARY KEY (timestamp, metric_name)
|
||||
) WITHOUT ROWID;
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- `WITHOUT ROWID` for efficient time-range scans
|
||||
- Composite PK on (timestamp, metric_name) for fast lookups
|
||||
- JSON labels for flexible metadata
|
||||
## Scope
|
||||
|
||||
#### tsdb_metrics_hour
|
||||
Embedded time-series storage in SQLite for ProxySQL runtime metrics and backend probe health.
|
||||
|
||||
```sql
|
||||
CREATE TABLE tsdb_metrics_hour (
|
||||
bucket INT NOT NULL,
|
||||
metric_name TEXT NOT NULL,
|
||||
labels TEXT,
|
||||
avg_value REAL,
|
||||
max_value REAL,
|
||||
min_value REAL,
|
||||
count INT,
|
||||
PRIMARY KEY (bucket, metric_name)
|
||||
) WITHOUT ROWID;
|
||||
```
|
||||
## Table Definitions
|
||||
|
||||
**Rationale:**
|
||||
- Pre-aggregated data for fast historical queries
|
||||
- Statistical summary (avg, max, min, count)
|
||||
### `tsdb_metrics`
|
||||
|
||||
#### tsdb_backend_health
|
||||
- Columns: `timestamp`, `metric_name`, `labels`, `value`
|
||||
- PK: `(timestamp, metric_name, labels)`
|
||||
- `labels` is JSON text, default `'{}'`
|
||||
|
||||
```sql
|
||||
CREATE TABLE tsdb_backend_health (
|
||||
timestamp INT NOT NULL,
|
||||
hostgroup INT NOT NULL,
|
||||
hostname TEXT NOT NULL,
|
||||
port INT NOT NULL,
|
||||
probe_up INT NOT NULL,
|
||||
connect_ms INT,
|
||||
PRIMARY KEY (timestamp, hostgroup, hostname, port)
|
||||
) WITHOUT ROWID;
|
||||
```
|
||||
|
||||
**Rationale:**
|
||||
- Tracks backend availability over time
|
||||
- Composite PK for efficient per-backend queries
|
||||
|
||||
## Downsampling Algorithm
|
||||
|
||||
### Hourly Aggregation
|
||||
|
||||
```sql
|
||||
INSERT OR REPLACE INTO tsdb_metrics_hour
|
||||
SELECT
|
||||
(timestamp/3600)*3600 as bucket,
|
||||
metric_name,
|
||||
labels,
|
||||
AVG(value) as avg_value,
|
||||
MAX(value) as max_value,
|
||||
MIN(value) as min_value,
|
||||
COUNT(*) as count
|
||||
FROM tsdb_metrics
|
||||
WHERE timestamp >= :last_processed AND timestamp < :current_hour
|
||||
GROUP BY bucket, metric_name, labels;
|
||||
```
|
||||
|
||||
### Retention Enforcement
|
||||
|
||||
```sql
|
||||
-- Raw data: 7 days
|
||||
DELETE FROM tsdb_metrics WHERE timestamp < unixepoch() - 7*86400;
|
||||
|
||||
-- Hourly: 1 year
|
||||
DELETE FROM tsdb_metrics_hour WHERE bucket < unixepoch() - 365*86400;
|
||||
|
||||
-- Health: 7 days
|
||||
DELETE FROM tsdb_backend_health WHERE timestamp < unixepoch() - 7*86400;
|
||||
```
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### Insert Performance
|
||||
|
||||
- **Raw metrics**: ~10,000 inserts/second
|
||||
- **Health probes**: ~5,000 inserts/second
|
||||
- **Batched**: No (individual prepared statements)
|
||||
|
||||
### Query Performance
|
||||
|
||||
- **Time-range scan**: O(log n) with index
|
||||
- **Label filter**: Full scan (JSON extraction)
|
||||
- **Aggregated query**: O(log n) on tsdb_metrics_hour
|
||||
|
||||
### Storage Overhead
|
||||
|
||||
| Data Type | Per-Row Size |
|
||||
|-----------|--------------|
|
||||
| Raw metric | ~50 bytes + label JSON |
|
||||
| Hourly aggregate | ~60 bytes + label JSON |
|
||||
| Health probe | ~40 bytes |
|
||||
|
||||
## Memory Usage
|
||||
|
||||
- **Prepared statements**: 3 cached statements
|
||||
- **JSON parsing**: Temporary during insert/query
|
||||
- **Result sets**: Streamed to client
|
||||
|
||||
## Concurrency
|
||||
|
||||
### Thread Safety
|
||||
|
||||
- SQLite handles concurrency via WAL mode
|
||||
- Multiple readers, single writer
|
||||
- No additional application-level locks
|
||||
|
||||
### Connection Model
|
||||
|
||||
- Uses existing `statsdb_disk` connection
|
||||
- Prepared statements cached per-thread
|
||||
|
||||
## API Specification
|
||||
|
||||
### C++ Interface
|
||||
|
||||
```cpp
|
||||
class ProxySQL_Statistics {
|
||||
public:
|
||||
// Metric insertion
|
||||
void insert_tsdb_metric(const std::string& metric_name,
|
||||
const std::map<std::string, std::string>& labels,
|
||||
double value, time_t timestamp);
|
||||
|
||||
// Health insertion
|
||||
void insert_backend_health(int hostgroup, const std::string& hostname,
|
||||
int port, bool probe_up, int connect_ms,
|
||||
time_t timestamp);
|
||||
|
||||
// Downsampling
|
||||
void tsdb_downsample_metrics();
|
||||
|
||||
// Query
|
||||
SQLite3_result* query_tsdb_metrics(const std::string& metric_name,
|
||||
const std::map<std::string, std::string>& label_filters,
|
||||
time_t from, time_t to,
|
||||
const std::string& aggregation);
|
||||
|
||||
// Status
|
||||
struct tsdb_status_t {
|
||||
size_t total_series;
|
||||
size_t total_datapoints;
|
||||
size_t disk_size_bytes;
|
||||
time_t oldest_datapoint;
|
||||
time_t newest_datapoint;
|
||||
};
|
||||
tsdb_status_t get_tsdb_status();
|
||||
};
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Variables
|
||||
|
||||
| Variable | Type | Default | Description |
|
||||
|----------|------|---------|-------------|
|
||||
| stats_tsdb_enabled | bool | false | Master switch |
|
||||
| stats_tsdb_sample_interval | int | 5 | Sampling interval (seconds) |
|
||||
| stats_tsdb_retention_days | int | 7 | Raw retention (days) |
|
||||
| stats_tsdb_monitor_enabled | bool | false | Health monitoring |
|
||||
| stats_tsdb_monitor_interval | int | 10 | Probe interval (seconds) |
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
1. **Insert/Query roundtrip**
|
||||
2. **Label filtering**
|
||||
3. **Downsampling accuracy**
|
||||
4. **Retention enforcement**
|
||||
|
||||
### Integration Tests
|
||||
|
||||
1. **Backend health monitoring**
|
||||
2. **Prometheus metrics sampling**
|
||||
3. **Concurrent access**
|
||||
4. **Resource limits**
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Label indexing** - Add GIN index on labels JSON
|
||||
2. **Continuous queries** - User-defined aggregations
|
||||
3. **Export formats** - CSV, JSON output
|
||||
4. **Alerting** - Basic threshold alerts
|
||||
### `tsdb_metrics_hour`
|
||||
|
||||
- Columns: `bucket`, `metric_name`, `labels`, `avg_value`, `max_value`, `min_value`, `count`
|
||||
- PK: `(bucket, metric_name, labels)`
|
||||
|
||||
### `tsdb_backend_health`
|
||||
|
||||
- Columns: `timestamp`, `hostgroup`, `hostname`, `port`, `probe_up`, `connect_ms`
|
||||
- PK: `(timestamp, hostgroup, hostname, port)`
|
||||
|
||||
## Sampling and Rollup
|
||||
|
||||
- Sampler interval: `admin-stats_tsdb_sample_interval`
|
||||
- Rollup interval: hourly
|
||||
- Rollup SQL: `INSERT OR REPLACE ... GROUP BY bucket, metric_name, labels`
|
||||
|
||||
## Retention
|
||||
|
||||
- Raw metrics retention: `admin-stats_tsdb_retention_days`
|
||||
- Backend probe retention: `admin-stats_tsdb_retention_days`
|
||||
- Hourly rollup retention: 365 days
|
||||
|
||||
## Variable Semantics
|
||||
|
||||
- All TSDB variables are ADMIN variables (`admin-stats_tsdb_*`).
|
||||
- Applied through standard ADMIN commands only.
|
||||
- No dedicated `LOAD/SAVE TSDB VARIABLES` command set.
|
||||
|
||||
## Current API Surface
|
||||
|
||||
- C++ methods in `ProxySQL_Statistics` for insert, query, status, sampler/monitor loops.
|
||||
- SQL querying through `statsdb_disk.tsdb_*` tables.
|
||||
- No dedicated HTTP TSDB endpoint implementation at this time.
|
||||
|
||||
@ -1,19 +1,6 @@
|
||||
# TSDB HTTP API Endpoints
|
||||
# TSDB UI / HTTP Endpoints
|
||||
|
||||
The TSDB exposes a JSON API for the built-in UI and external queries. All endpoints require Admin authentication.
|
||||
No dedicated TSDB REST endpoints are currently implemented in ProxySQL.
|
||||
|
||||
## `GET /api/tsdb/metrics`
|
||||
Returns a list of all metrics currently stored in the TSDB.
|
||||
|
||||
## `GET /api/tsdb/query`
|
||||
Retrieves time series data for a specific metric.
|
||||
**Parameters:**
|
||||
- `metric`: (Required) Name of the metric.
|
||||
- `from`: (Required) Start timestamp (Unix ms).
|
||||
- `to`: (Required) End timestamp (Unix ms).
|
||||
- `step`: (Required) Resolution in seconds.
|
||||
- `labels`: (Optional) Filter by labels (e.g., `hostgroup=10`).
|
||||
- `agg`: (Optional) Aggregation function (`avg`, `max`, `rate`).
|
||||
|
||||
## `GET /api/tsdb/status`
|
||||
Returns runtime statistics for the TSDB subsystem, including disk usage and series cardinality.
|
||||
Current access path is SQL via admin connection, querying `statsdb_disk.tsdb_*` tables.
|
||||
Any future TSDB HTTP API should be documented here once endpoint handlers are added.
|
||||
|
||||
@ -0,0 +1,123 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "mysql.h"
|
||||
|
||||
#include "tap.h"
|
||||
#include "command_line.h"
|
||||
#include "utils.h"
|
||||
|
||||
using std::map;
|
||||
using std::string;
|
||||
|
||||
static bool fetch_single_string(MYSQL* mysql, const string& query, string& out) {
|
||||
if (mysql_query(mysql, query.c_str())) {
|
||||
return false;
|
||||
}
|
||||
MYSQL_RES* res = mysql_store_result(mysql);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
MYSQL_ROW row = mysql_fetch_row(res);
|
||||
if (!row || !row[0]) {
|
||||
mysql_free_result(res);
|
||||
return false;
|
||||
}
|
||||
out = row[0];
|
||||
mysql_free_result(res);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CommandLine cl;
|
||||
if (cl.getEnv()) {
|
||||
diag("Failed to get the required environmental variables.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
plan(12);
|
||||
|
||||
MYSQL* admin = mysql_init(NULL);
|
||||
if (!admin) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (!mysql_real_connect(admin, cl.host, cl.admin_username, cl.admin_password, NULL, cl.admin_port, NULL, 0)) {
|
||||
mysql_close(admin);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int rc = mysql_query(admin, "LOAD TSDB VARIABLES TO RUNTIME");
|
||||
ok(rc != 0, "`LOAD TSDB VARIABLES TO RUNTIME` is rejected");
|
||||
|
||||
rc = mysql_query(admin, "SAVE TSDB VARIABLES TO DISK");
|
||||
ok(rc != 0, "`SAVE TSDB VARIABLES TO DISK` is rejected");
|
||||
|
||||
MYSQL_QUERY_T(admin, "SET admin-stats_tsdb_enabled='1'");
|
||||
MYSQL_QUERY_T(admin, "SET admin-stats_tsdb_sample_interval='11'");
|
||||
MYSQL_QUERY_T(admin, "SET admin-stats_tsdb_retention_days='30'");
|
||||
MYSQL_QUERY_T(admin, "SET admin-stats_tsdb_monitor_enabled='1'");
|
||||
MYSQL_QUERY_T(admin, "SET admin-stats_tsdb_monitor_interval='13'");
|
||||
MYSQL_QUERY_T(admin, "LOAD ADMIN VARIABLES TO RUNTIME");
|
||||
|
||||
string count;
|
||||
bool count_ok = fetch_single_string(
|
||||
admin,
|
||||
"SELECT COUNT(*) FROM runtime_global_variables WHERE variable_name LIKE 'admin-stats_tsdb_%'",
|
||||
count
|
||||
);
|
||||
ok(count_ok, "Read runtime TSDB variable count from runtime_global_variables");
|
||||
ok(count == "5", "Exactly five admin-stats_tsdb runtime variables are present");
|
||||
|
||||
const map<string, string> expected_runtime_values{
|
||||
{"admin-stats_tsdb_enabled", "1"},
|
||||
{"admin-stats_tsdb_sample_interval", "11"},
|
||||
{"admin-stats_tsdb_retention_days", "30"},
|
||||
{"admin-stats_tsdb_monitor_enabled", "1"},
|
||||
{"admin-stats_tsdb_monitor_interval", "13"},
|
||||
};
|
||||
|
||||
for (const auto& kv : expected_runtime_values) {
|
||||
string value;
|
||||
bool ok_fetch = fetch_single_string(
|
||||
admin,
|
||||
"SELECT variable_value FROM runtime_global_variables WHERE variable_name='" + kv.first + "'",
|
||||
value
|
||||
);
|
||||
ok(ok_fetch && value == kv.second, "Runtime value matches for %s", kv.first.c_str());
|
||||
}
|
||||
|
||||
MYSQL_QUERY_T(admin, "SAVE ADMIN VARIABLES TO DISK");
|
||||
string disk_enabled;
|
||||
bool disk_ok = fetch_single_string(
|
||||
admin,
|
||||
"SELECT variable_value FROM global_variables WHERE variable_name='admin-stats_tsdb_enabled'",
|
||||
disk_enabled
|
||||
);
|
||||
ok(disk_ok && disk_enabled == "1", "TSDB admin variable is persisted to disk via SAVE ADMIN VARIABLES");
|
||||
|
||||
string metrics_schema;
|
||||
bool schema_metrics_ok = fetch_single_string(
|
||||
admin,
|
||||
"SELECT sql FROM statsdb_disk.sqlite_master WHERE type='table' AND name='tsdb_metrics'",
|
||||
metrics_schema
|
||||
);
|
||||
ok(
|
||||
schema_metrics_ok && metrics_schema.find("PRIMARY KEY (timestamp, metric_name, labels)") != string::npos,
|
||||
"tsdb_metrics schema uses labels in primary key"
|
||||
);
|
||||
|
||||
string metrics_hour_schema;
|
||||
bool schema_hour_ok = fetch_single_string(
|
||||
admin,
|
||||
"SELECT sql FROM statsdb_disk.sqlite_master WHERE type='table' AND name='tsdb_metrics_hour'",
|
||||
metrics_hour_schema
|
||||
);
|
||||
ok(
|
||||
schema_hour_ok && metrics_hour_schema.find("PRIMARY KEY (bucket, metric_name, labels)") != string::npos,
|
||||
"tsdb_metrics_hour schema uses labels in primary key"
|
||||
);
|
||||
|
||||
mysql_close(admin);
|
||||
return exit_status();
|
||||
}
|
||||
Loading…
Reference in new issue