Skip to content
Jeroen Claassens edited this page Aug 17, 2021 · 6 revisions


Table of contents

What is InfluxDB?

InfluxDB is a way to keep track of Skyra's metrics in real-time on an awesome dashboard.

Why do we use InfluxDB?

We wanted a good platform to keep track of our metrics that also integrates well with the Skyra development stack. InfluxDB was just that. It provides both a dashboard as well as the API to feed the data. We also considered solutions such as Grafana, however the lack of a good API to provide data to Grafana and the need to store the data inside Skyra's PostgreSQL database turned us away.

Setting up InfluxDB

Prerequisites

You will need to install Docker if you want to easily create and manage the InfluxDB instance. You should also be sure to install docker-compose to make the process easiest.

Lastly we recommend you install PowerShell Core as we provide a PowerShell script to call various docker-compose commands. This is optional however, if you know your way around docker-compose or have an extension such as Docker for VSCode.

Starting your InfluxDB instance

The following commands can be used in succession to do the initial launch of the InfluxDB instance and setting up the queries.

First create a Docker volume:

docker volume create --name=influx-data

Then start an Influx container:

# When using Powershell
yarn dockerps start influx

# When not using Powershell
docker-compose -p skyra -f ./.docker/docker-compose.yml up -d influx

Influx queries

Skyra can keep track of various metrics. Each of these metrics require writing queries in the Flux language. This section will list all the supported Flux queries.

Total Guild Count

A query to display the total amount of guilds Skyra is in

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "guilds")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> aggregateWindow(every: v.windowPeriod, fn: last)
  |> yield(name: "last")

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "guilds")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> skew()
  |> yield(name: "skew")

Panel configuration

Click here to expand for screenshot

Guild Difference over Time

A query to display the difference of guilds over a span of time

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "guilds")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> difference(nonNegative: false, columns: ["_value"])

Panel configuration

Click here to expand for screenshot

Total Command Uses

A query to the total amount of commands used with Skyra

Query

from(bucket: "analytics") // Get all published measurements. In Skyra's case, all of their names are defined in the const enum present in "AnalyticsSchema".
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop) // Here we define the range/(time frame) for which we wish to see the entries. Due to the precision specified in getWriteApi the lowest time frame is a second.
  |> filter(fn: (r) => r["_measurement"] == "commands") // Here we get all the aforementioned time specified values and filter out anything that isn't "AnalyticsSchema.Points.Commands".
  |> sum(column: "_value") // The way I did storage was by setting the "_field" to the command name and "_value" to 1. Because of that design quick each command comes in its own column which are defined by their "_field" value. After that, we sum them all up so that there's only one entry per "_field" column.
  |> group(mode: "by") // Now since they are still in their own "_field" sorted columns we need to join them into a single one.
  |> sum(column: "_value") // And finally since we have all the commands in one place we can sum their "_value" up and get the total amount on used commands in a specified time frame.

Panel configuration

Click here to expand for screenshot

Total User Count

A query to display the total amount users Skyra services

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "users")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> aggregateWindow(every: v.windowPeriod, fn: last)
  |> yield(name: "last")

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "users")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> skew()
  |> yield(name: "skew")

Panel configuration

Click here to expand for screenshot

Total Active Voice Connection

A query to display the total amount voice connections Skyra has - as a single stat

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "voice_connections")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> skew()
  |> yield(name: "skew")

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "voice_connections")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])
  |> aggregateWindow(every: v.windowPeriod, fn: last)
  |> yield(name: "last")

Panel configuration

Click here to expand for screenshot

Active Voice Connections - Gauge

A query to display the total amount voice connections Skyra has - as a gauge

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "voice_connections")
  |> filter(fn: (r) => r["_field"] == "value")
  |> group(columns: ["_field"])

Panel configuration

Click here to expand for screenshot

All command uses - table

A query to display the total uses of a command, per command

Query

from(bucket: "analytics")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "commands")
  |> sum(column: "_value")
  |> group(mode:"by")

Panel configuration

Click here to expand for screenshot