Compare commits
No commits in common. "0971efa5948e603dd9dad52b216a6cd7472d45ad" and "bea205470915cfc5044d43c7bdebe343f1d323e9" have entirely different histories.
0971efa594
...
bea2054709
|
@ -1,20 +0,0 @@
|
||||||
when:
|
|
||||||
branch: ${CI_REPO_DEFAULT_BRANCH}
|
|
||||||
event: push
|
|
||||||
|
|
||||||
steps:
|
|
||||||
publish:
|
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
|
||||||
settings:
|
|
||||||
#platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/riscv64,linux/s390x
|
|
||||||
platforms: linux/amd64,linux/arm/v6,linux/arm64/v8
|
|
||||||
repo: ${CI_REPO_URL} # url to repository
|
|
||||||
registry: ${CI_FORGE_URL} # url of gitea
|
|
||||||
tags:
|
|
||||||
- ${CI_COMMIT_SHA:0:8} # first 8 characters of var
|
|
||||||
- rolling
|
|
||||||
- rolling@${CI_COMMIT_SHA:0:8}
|
|
||||||
username: ${CI_REPO_OWNER}
|
|
||||||
password:
|
|
||||||
from_secret: registry_token
|
|
||||||
|
|
|
@ -307,16 +307,6 @@ version = "0.8.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctrlc"
|
|
||||||
version = "3.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
|
|
||||||
dependencies = [
|
|
||||||
"nix",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
|
@ -795,17 +785,6 @@ dependencies = [
|
||||||
"tempfile",
|
"tempfile",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nix"
|
|
||||||
version = "0.27.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.2",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
@ -1325,7 +1304,6 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
"clap",
|
"clap",
|
||||||
"ctrlc",
|
|
||||||
"figment",
|
"figment",
|
||||||
"prometheus",
|
"prometheus",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
|
|
@ -9,7 +9,6 @@ edition = "2021"
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
axum = "0.7.4"
|
axum = "0.7.4"
|
||||||
clap = { version = "4.4.18", features = ["derive"] }
|
clap = { version = "4.4.18", features = ["derive"] }
|
||||||
ctrlc = "3.4.2"
|
|
||||||
figment = { version = "0.10.14", features = ["toml", "env"] }
|
figment = { version = "0.10.14", features = ["toml", "env"] }
|
||||||
prometheus = "0.13.3"
|
prometheus = "0.13.3"
|
||||||
reqwest = { version = "0.11.23", features = ["json"] }
|
reqwest = { version = "0.11.23", features = ["json"] }
|
||||||
|
|
|
@ -4,13 +4,15 @@ FROM rust:alpine3.17 as builder
|
||||||
RUN apk update
|
RUN apk update
|
||||||
RUN apk add build-base ca-certificates libressl-dev
|
RUN apk add build-base ca-certificates libressl-dev
|
||||||
|
|
||||||
|
# create root application folder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY ./ /app/src
|
||||||
|
|
||||||
# Install rust toolchains
|
# Install rust toolchains
|
||||||
RUN rustup toolchain install stable
|
RUN rustup toolchain install stable
|
||||||
RUN rustup default stable
|
RUN rustup default stable
|
||||||
|
|
||||||
# create root application folder
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./ /app/src
|
|
||||||
WORKDIR /app/src
|
WORKDIR /app/src
|
||||||
|
|
||||||
# Build dependencies only. Separate these for caches
|
# Build dependencies only. Separate these for caches
|
||||||
|
|
23
README.md
23
README.md
|
@ -1,23 +0,0 @@
|
||||||
# Tautulli Prometheus Exporter
|
|
||||||
This is a small application that can collect information from Tautulli and exports it in a Prometheus format.
|
|
||||||
|
|
||||||
## Config
|
|
||||||
```toml
|
|
||||||
# The full url of tautulli
|
|
||||||
tautulli_url = "https://tautulli.example.com/"
|
|
||||||
tautulli_apikey = ""
|
|
||||||
# The address to listen on. Default is 0.0.0.0
|
|
||||||
listen_address = "0.0.0.0"
|
|
||||||
# The port to listen on. Default is 3000
|
|
||||||
listen_port = "3000"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Docker image
|
|
||||||
Docker images are published [here](https://git.seanomik.net/SeanOMik/-/packages/container/tautulli-exporter/v0.1.0).
|
|
||||||
|
|
||||||
You can run the following command to run a docker container:
|
|
||||||
```shell
|
|
||||||
$ docker run -it --rm -v $PWD/config.toml:/app/config.toml -p 3000:3000 git.seanomik.net/seanomik/tautulli-exporter:v0.1.0
|
|
||||||
```
|
|
||||||
|
|
||||||
## Exported metrics
|
|
50
src/main.rs
50
src/main.rs
|
@ -23,7 +23,7 @@ use figment::{
|
||||||
providers::{Env, Format, Toml},
|
providers::{Env, Format, Toml},
|
||||||
Figment,
|
Figment,
|
||||||
};
|
};
|
||||||
use tokio::{sync::Mutex, signal};
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
mod dto;
|
mod dto;
|
||||||
use dto::*;
|
use dto::*;
|
||||||
|
@ -183,24 +183,12 @@ struct Config {
|
||||||
tautulli_apikey: String,
|
tautulli_apikey: String,
|
||||||
#[serde(default = "metrics_prefix_default")]
|
#[serde(default = "metrics_prefix_default")]
|
||||||
metrics_prefix: String,
|
metrics_prefix: String,
|
||||||
#[serde(default = "listen_address_default")]
|
|
||||||
listen_address: String,
|
|
||||||
#[serde(default = "listen_port_default")]
|
|
||||||
listen_port: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metrics_prefix_default() -> String {
|
fn metrics_prefix_default() -> String {
|
||||||
"tautulli".to_string()
|
"tautulli".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn listen_address_default() -> String {
|
|
||||||
"0.0.0.0".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn listen_port_default() -> String {
|
|
||||||
"3000".to_string()
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
/// Constructs an api endpoint for you
|
/// Constructs an api endpoint for you
|
||||||
fn api_endpoint(&self, command: &str) -> String {
|
fn api_endpoint(&self, command: &str) -> String {
|
||||||
|
@ -248,30 +236,6 @@ struct AppState {
|
||||||
metrics: Arc<Mutex<Metrics>>,
|
metrics: Arc<Mutex<Metrics>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown_signal() {
|
|
||||||
let ctrl_c = async {
|
|
||||||
signal::ctrl_c()
|
|
||||||
.await
|
|
||||||
.expect("failed to install Ctrl+C handler");
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
let terminate = async {
|
|
||||||
signal::unix::signal(signal::unix::SignalKind::terminate())
|
|
||||||
.expect("failed to install signal handler")
|
|
||||||
.recv()
|
|
||||||
.await;
|
|
||||||
};
|
|
||||||
|
|
||||||
#[cfg(not(unix))]
|
|
||||||
let terminate = std::future::pending::<()>();
|
|
||||||
|
|
||||||
tokio::select! {
|
|
||||||
_ = ctrl_c => { info!("Received ctrl+c, exiting...") },
|
|
||||||
_ = terminate => { info!("Received terminate signal, exiting...") },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
tracing_subscriber::registry()
|
tracing_subscriber::registry()
|
||||||
|
@ -290,7 +254,6 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.merge(Toml::file(args.config))
|
.merge(Toml::file(args.config))
|
||||||
.merge(Env::prefixed("TAUTEXP_"))
|
.merge(Env::prefixed("TAUTEXP_"))
|
||||||
.extract()?;
|
.extract()?;
|
||||||
let full_listen_address = format!("{}:{}", config.listen_address, config.listen_port);
|
|
||||||
|
|
||||||
// if the url ends with a `/` it can cause some issues
|
// if the url ends with a `/` it can cause some issues
|
||||||
if config.tautulli_url.ends_with("/") {
|
if config.tautulli_url.ends_with("/") {
|
||||||
|
@ -312,18 +275,17 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.with_state(state)
|
.with_state(state)
|
||||||
.layer(TraceLayer::new_for_http());
|
.layer(TraceLayer::new_for_http());
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind(&full_listen_address).await?;
|
let bind = "0.0.0.0:3000";
|
||||||
info!("Starting http server, listening on {}", full_listen_address);
|
let listener = tokio::net::TcpListener::bind(bind).await?;
|
||||||
axum::serve(listener, app)
|
info!("Starting http server, listening on {}", bind);
|
||||||
.with_graceful_shutdown(shutdown_signal())
|
axum::serve(listener, app).await?;
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
// basic handler that responds with a static string
|
// basic handler that responds with a static string
|
||||||
async fn root() -> &'static str {
|
async fn root() -> &'static str {
|
||||||
"Up"
|
"Hello, World!"
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn metrics(State(state): State<AppState>) -> Result<String, CollectionError> {
|
async fn metrics(State(state): State<AppState>) -> Result<String, CollectionError> {
|
||||||
|
|
Loading…
Reference in New Issue