Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add enhanced logging option #15

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ You can make use of the following environment variables / configurations:
| Environment variable | Default value | Description
|----------------------|---------------|------------|
| `GRAFANA_PORT` | `3000` | Port to bind Grafana webinterface on the host system |
| `SPEEDTEST_SPEEDTEST_INTERVAL` | `3600` | Interval/pause (in seconds) between speedtests |
| `SPEEDTEST_INTERVAL` | `3600` | Interval/pause (in seconds) between speedtests |
| `SPEEDTEST_HOST` | `local` | Display name of the client |
| `SPEEDTEST_SERVER` | none | Optionally set specific speedtest.net derver ID, otherwise use the closest |
| `INFLUXDB_DB` | `speedtest` | Database to save speedtest results |
| `SPEEDTEST_ENHANCED_LOGGING` | none | Optionally write all returned speedtest CLI metrics to a single InfluxDB measurement (INFLUXDB_MEASUREMENT), else use legacy logging to download, upload, ping measurements only |
| `INFLUXDB_HOST` | `influxdb` | Name of the InfluxDB host/containers |
| `INFLUXDB_USERNAME` | `root` | Username for InfluxDB authentication |
| `INFLUXDB_PASSWORD` | `root` | Password for InfluxDB authentication |
| `INFLUXDB_DB` | `speedtest` | Database to save speedtest results |
| `INFLUXDB_MEASUREMENT` | `results` | InfluxDB measurement to results to. Only valid if SPEEDTEST_ENHANCED_LOGGING is true |

## Usage

Expand Down Expand Up @@ -88,12 +90,18 @@ $ docker-compose logs -f grafana

By default the dashboard shows all speedtest results. To filter for a specifc host, simply add a `and host = 'local'` statement in the `WHERE` clause of the SQL select.

Example (Download Time Serie):
Example 1 - Download Time Series:

```
SELECT mean("value") FROM "download" WHERE $timeFilter and host = 'local' GROUP BY time($interval) fill(null)
```

Example 2 - Download Time Series (If using SPEEDTEST_ENHANCED_lOGGING):

```
SELECT mean("download_bandwidth") FROM "results" WHERE $timeFilter and host = 'local' GROUP BY time($interval) fill(null)
```

#### Administrative access

Access `http://${HOSTNAME}:${GRAFANA_PORT}` ([http://localhost:3000](`http://localhost:3000`) by default) and login using the following default credentials:
Expand Down
76 changes: 63 additions & 13 deletions docker/speedtest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ process.env.INFLUXDB_USERNAME = (process.env.INFLUXDB_DB) ? process.env.INFLUXDB
process.env.INFLUXDB_PASSWORD = (process.env.INFLUXDB_DB) ? process.env.INFLUXDB_DB : 'root';
process.env.SPEEDTEST_HOST = (process.env.SPEEDTEST_HOST) ? process.env.SPEEDTEST_HOST : 'local';
process.env.SPEEDTEST_INTERVAL = (process.env.SPEEDTEST_INTERVAL) ? process.env.SPEEDTEST_INTERVAL : 3600;
process.env.SPEEDTEST_ENHANCED_LOGGING = (process.env.SPEEDTEST_ENHANCED_LOGGING) ? process.env.SPEEDTEST_ENHANCED_LOGGING : 'false';
process.env.INFLUX_MEASUREMENT = (process.env.INFLUX_MEASUREMENT) ? process.env.INFLUX_MEASUREMENT : 'results';
const enhancedLogging = (process.env.SPEEDTEST_ENHANCED_LOGGING.toLowerCase() != 'false') ? true : false;

const bitToMbps = bit => (bit / 1000 / 1000) * 8;

Expand All @@ -21,19 +24,66 @@ const getSpeedMetrics = async () => {

const { stdout } = await execa("speedtest", args);
const result = JSON.parse(stdout);
return {
upload: bitToMbps(result.upload.bandwidth),
download: bitToMbps(result.download.bandwidth),
ping: result.ping.latency
};

return result;
};

const pushToInflux = async (influx, metrics) => {
const points = Object.entries(metrics).map(([measurement, value]) => ({
measurement,
tags: { host: process.env.SPEEDTEST_HOST },
fields: { value }
}));
var points = {};
if (enhancedLogging) {
// Enhanced Logging
// Create InfluxDB data point with all the JSON data in a single measurement. Note in enhanced logging the data is written as-is with no conversion from bitsToMbps
// There's likely a better way of just cycling through the JSON and converting to fields rather than specifying all fields directly below?

points = [{
measurement: process.env.INFLUX_MEASUREMENT,
tags: { host: process.env.SPEEDTEST_HOST },
fields: {
type: metrics.type,
timestamp: metrics.timestamp,
ping_jitter: metrics.ping.jitter,
ping_latency: metrics.ping.latency,
download_bandwidth: metrics.download.bandwidth,
download_bytes: metrics.download.bytes,
download_elapsed: metrics.download.elapsed,
upload_bandwidth: metrics.upload.bandwidth,
upload_bytes: metrics.upload.bytes,
upload_elapsed: metrics.upload.elapsed,
packetLoss: metrics.packetLoss,
isp: metrics.isp,
interface_internalIp: metrics.interface.internalIp,
interface_name: metrics.interface.name,
interface_macAddr: metrics.interface.macAddr,
interface_isVpn: metrics.interface.isVpn,
interface_externalIp: metrics.interface.externalIp,
server_id: metrics.server.id,
server_name: metrics.server.name,
server_location: metrics.server.location,
server_country: metrics.server.country,
server_host: metrics.server.host,
server_port: metrics.server.port,
server_ip: metrics.server.ip,
result_id: metrics.result.id,
result_url: metrics.result.url
}
}];

} else {
// Legacy logging

legacy_metrics = {
upload: bitToMbps(metrics.upload.bandwidth),
download: bitToMbps(metrics.download.bandwidth),
ping: metrics.ping.latency
};

points = Object.entries(legacy_metrics).map(([measurement, value]) => ({
measurement,
tags: { host: process.env.SPEEDTEST_HOST },
fields: { value }
}));

}

await influx.writePoints(points);
};
Expand All @@ -50,9 +100,9 @@ const pushToInflux = async (influx, metrics) => {
while (true) {
log("Starting speedtest...");
const speedMetrics = await getSpeedMetrics();
log(
`Speedtest results - Download: ${speedMetrics.download}, Upload: ${speedMetrics.upload}, Ping: ${speedMetrics.ping}`
);

log(`Speedtest results - Server: ${speedMetrics.server.name} (${speedMetrics.server.location}, ${speedMetrics.server.country}), Download: ${(bitToMbps(speedMetrics.download.bandwidth)).toFixed(2)}Mbps, Upload: ${(bitToMbps(speedMetrics.upload.bandwidth)).toFixed(2)}Mbps, Ping: ${(speedMetrics.ping.latency).toFixed(2)}ms`);

await pushToInflux(influx, speedMetrics);

log(`Sleeping for ${process.env.SPEEDTEST_INTERVAL} seconds...`);
Expand Down