Bring back stats collection
parent
2e273cdcde
commit
1c38067785
|
@ -71,6 +71,14 @@ If you are actively developing Spoticord, you can use the following command to b
|
||||||
cargo run
|
cargo run
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
As of now, Spoticord has one optional feature: `stats`. This feature enables collecting a few statistics, total and active servers. These statistics will be sent to a redis server, where they then can be read for whatever purpose. If you want to enable this feature, you can do so by running the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo build [--release] --features metrics
|
||||||
|
```
|
||||||
|
|
||||||
# MSRV
|
# MSRV
|
||||||
|
|
||||||
The current minimum supported rust version is `1.65.0`.
|
The current minimum supported rust version is `1.65.0`.
|
||||||
|
|
|
@ -72,9 +72,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.0.5"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783"
|
checksum = "0f2135563fb5c609d2b2b87c1e8ce7bc41b0b45430fa9661f457981503dd5bf0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
@ -301,6 +301,16 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "combine"
|
||||||
|
version = "4.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "command_attr"
|
name = "command_attr"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
@ -1801,6 +1811,21 @@ dependencies = [
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redis"
|
||||||
|
version = "0.23.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4f49cdc0bb3f412bf8e7d1bd90fe1d9eb10bc5c399ba90973c14662a27b3f8ba"
|
||||||
|
dependencies = [
|
||||||
|
"combine",
|
||||||
|
"itoa",
|
||||||
|
"percent-encoding",
|
||||||
|
"ryu",
|
||||||
|
"sha1_smol",
|
||||||
|
"socket2 0.4.9",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -2243,6 +2268,12 @@ dependencies = [
|
||||||
"digest 0.10.7",
|
"digest 0.10.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1_smol"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shannon"
|
name = "shannon"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2365,9 +2396,9 @@ version = "2.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dotenv",
|
"dotenv",
|
||||||
"env_logger 0.10.0",
|
"env_logger 0.10.0",
|
||||||
"lazy_static",
|
|
||||||
"librespot",
|
"librespot",
|
||||||
"log",
|
"log",
|
||||||
|
"redis",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"samplerate",
|
"samplerate",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2453,9 +2484,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termcolor"
|
name = "termcolor"
|
||||||
version = "1.2.0"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,12 +8,15 @@ rust-version = "1.65.0"
|
||||||
name = "spoticord"
|
name = "spoticord"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
stats = ["redis"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
env_logger = "0.10.0"
|
env_logger = "0.10.0"
|
||||||
lazy_static = { version = "1.4.0", optional = true }
|
|
||||||
librespot = { version = "0.4.2", default-features = false }
|
librespot = { version = "0.4.2", default-features = false }
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
|
redis = { version = "0.23.3", optional = true }
|
||||||
reqwest = "0.11.20"
|
reqwest = "0.11.20"
|
||||||
samplerate = "0.2.4"
|
samplerate = "0.2.4"
|
||||||
serde = "1.0.188"
|
serde = "1.0.188"
|
||||||
|
@ -28,4 +31,3 @@ zerocopy = "0.7.5"
|
||||||
[profile.release]
|
[profile.release]
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
lto = true
|
lto = true
|
||||||
debug = true
|
|
|
@ -7,7 +7,9 @@ WORKDIR /app
|
||||||
RUN apt-get update && apt-get install -y cmake
|
RUN apt-get update && apt-get install -y cmake
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN cargo install --path .
|
|
||||||
|
# Remove `--features stats` if you want to deploy without stats collection
|
||||||
|
RUN cargo install --path . --features stats
|
||||||
|
|
||||||
# Runtime
|
# Runtime
|
||||||
FROM debian:buster-slim
|
FROM debian:buster-slim
|
||||||
|
|
|
@ -16,6 +16,7 @@ Spoticord uses environment variables to configure itself. The following variable
|
||||||
|
|
||||||
Additionally you can configure the following variables:
|
Additionally you can configure the following variables:
|
||||||
- `GUILD_ID`: The ID of the Discord server where this bot will create commands for. This is used during testing to prevent the bot from creating slash commands in other servers, as well as getting the commands quicker. This variable is optional, and if not set, the bot will create commands in all servers it is in (this may take up to 15 minutes).
|
- `GUILD_ID`: The ID of the Discord server where this bot will create commands for. This is used during testing to prevent the bot from creating slash commands in other servers, as well as getting the commands quicker. This variable is optional, and if not set, the bot will create commands in all servers it is in (this may take up to 15 minutes).
|
||||||
|
- `KV_URL`: The connection URL of a redis-server instance used for storing realtime data. This variable is required when compiling with the `stats` feature.
|
||||||
|
|
||||||
#### Providing environment variables
|
#### Providing environment variables
|
||||||
You can provide environment variables in a `.env` file at the root of the working directory of Spoticord.
|
You can provide environment variables in a `.env` file at the root of the working directory of Spoticord.
|
||||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -18,6 +18,12 @@ mod player;
|
||||||
mod session;
|
mod session;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
|
#[cfg(feature = "stats")]
|
||||||
|
mod stats;
|
||||||
|
|
||||||
|
#[cfg(feature = "stats")]
|
||||||
|
use crate::stats::StatsManager;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
if std::env::var("RUST_LOG").is_err() {
|
if std::env::var("RUST_LOG").is_err() {
|
||||||
|
@ -51,6 +57,11 @@ async fn main() {
|
||||||
let token = env::var("DISCORD_TOKEN").expect("a token in the environment");
|
let token = env::var("DISCORD_TOKEN").expect("a token in the environment");
|
||||||
let db_url = env::var("DATABASE_URL").expect("a database URL in the environment");
|
let db_url = env::var("DATABASE_URL").expect("a database URL in the environment");
|
||||||
|
|
||||||
|
#[cfg(feature = "stats")]
|
||||||
|
let stats_manager =
|
||||||
|
StatsManager::new(env::var("KV_URL").expect("a redis URL in the environment"))
|
||||||
|
.expect("Failed to connect to redis");
|
||||||
|
|
||||||
let session_manager = SessionManager::new();
|
let session_manager = SessionManager::new();
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
|
@ -73,7 +84,9 @@ async fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let shard_manager = client.shard_manager.clone();
|
let shard_manager = client.shard_manager.clone();
|
||||||
let _cache = client.cache_and_http.cache.clone();
|
|
||||||
|
#[cfg(feature = "stats")]
|
||||||
|
let cache = client.cache_and_http.cache.clone();
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
let mut term: Option<Box<dyn Any + Send>> = Some(Box::new(
|
let mut term: Option<Box<dyn Any + Send>> = Some(Box::new(
|
||||||
|
@ -88,6 +101,22 @@ async fn main() {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
_ = tokio::time::sleep(std::time::Duration::from_secs(60)) => {
|
||||||
|
#[cfg(feature = "stats")]
|
||||||
|
{
|
||||||
|
let guild_count = cache.guilds().len();
|
||||||
|
let active_count = session_manager.get_active_session_count().await;
|
||||||
|
|
||||||
|
if let Err(why) = stats_manager.set_server_count(guild_count) {
|
||||||
|
error!("Failed to update server count: {why}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(why) = stats_manager.set_active_count(active_count) {
|
||||||
|
error!("Failed to update active count: {why}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ = tokio::signal::ctrl_c() => {
|
_ = tokio::signal::ctrl_c() => {
|
||||||
info!("Received interrupt signal, shutting down...");
|
info!("Received interrupt signal, shutting down...");
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
use redis::{Client, Commands, RedisResult as Result};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StatsManager {
|
||||||
|
redis: Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatsManager {
|
||||||
|
pub fn new(url: impl AsRef<str>) -> Result<Self> {
|
||||||
|
let redis = Client::open(url.as_ref())?;
|
||||||
|
|
||||||
|
Ok(StatsManager { redis })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_server_count(&self, count: usize) -> Result<()> {
|
||||||
|
let mut con = self.redis.get_connection()?;
|
||||||
|
|
||||||
|
con.set("sc-bot-total-servers", count.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_active_count(&self, count: usize) -> Result<()> {
|
||||||
|
let mut con = self.redis.get_connection()?;
|
||||||
|
|
||||||
|
con.set("sc-bot-active-servers", count.to_string())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue