feat: mise en place tracing
This commit is contained in:
parent
7711df3274
commit
8af7c67a00
1922
Cargo.lock
generated
1922
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
30
Cargo.toml
30
Cargo.toml
@ -13,15 +13,8 @@ uuid = { version = "1.4", features = ["v4", "serde"] }
|
|||||||
chrono = { version = "0.4", features = ["serde"] }
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] }
|
utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tokio-postgres = { version = "0.7", features = [
|
|
||||||
"with-uuid-1",
|
|
||||||
"with-chrono-0_4",
|
|
||||||
"with-serde_json-1",
|
|
||||||
] }
|
|
||||||
reqwest = { version = "0.11", features = ["json"] }
|
reqwest = { version = "0.11", features = ["json"] }
|
||||||
deadpool-postgres = { version = "0.11", features = ["serde"] }
|
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
openssl = { version = "0.10", features = ["vendored"] }
|
||||||
postgres-openssl = "0.5.0"
|
|
||||||
toml = "0.8"
|
toml = "0.8"
|
||||||
actix-web = "4"
|
actix-web = "4"
|
||||||
actix-cors = "0.6.4"
|
actix-cors = "0.6.4"
|
||||||
@ -30,22 +23,23 @@ regex = "1.10.0"
|
|||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
actix = "0.13.1"
|
actix = "0.13.1"
|
||||||
serial_test = "2.0.0"
|
serial_test = "2.0.0"
|
||||||
|
tokio = { version = "1.38", features = ["macros", "rt-multi-thread"] }
|
||||||
serenity = { version = "0.12", default-features = false, features = [
|
|
||||||
"client",
|
|
||||||
"gateway",
|
|
||||||
"rustls_backend",
|
|
||||||
"model",
|
|
||||||
"framework",
|
|
||||||
"standard_framework",
|
|
||||||
"cache",
|
|
||||||
] }
|
|
||||||
tokio = { version = "1.35", features = ["macros", "rt-multi-thread"] }
|
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
walkdir = "2.4.0"
|
walkdir = "2.4.0"
|
||||||
surrealdb = "1.1.1"
|
surrealdb = "1.1.1"
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
poise = "0.6.1"
|
poise = "0.6.1"
|
||||||
|
tracing = "0.1"
|
||||||
|
tracing-actix-web = "0.7.9"
|
||||||
|
serde_repr = "0.1"
|
||||||
|
tracing-subscriber = { version = "0.3", features = ["registry", "env-filter","time"] }
|
||||||
|
time = "0.3.36"
|
||||||
|
tracing-bunyan-formatter = "0.3"
|
||||||
|
opentelemetry = "0.23"
|
||||||
|
opentelemetry_sdk = { version = "0.23", features = ["rt-tokio"] }
|
||||||
|
opentelemetry-otlp = { version = "0.16"}
|
||||||
|
tracing-opentelemetry = "0.24"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
@ -14,6 +14,15 @@ services:
|
|||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
volumes:
|
volumes:
|
||||||
- db:/appdata
|
- db:/appdata
|
||||||
|
jaeger:
|
||||||
|
image: jaegertracing/all-in-one:${JAEGER_VERSION:-latest}
|
||||||
|
ports:
|
||||||
|
- "16686:16686"
|
||||||
|
- "4318:4318"
|
||||||
|
- "14268:14268"
|
||||||
|
- "4317:4317"
|
||||||
|
environment:
|
||||||
|
- LOG_LEVEL=debug
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db:
|
db:
|
@ -15,3 +15,18 @@ tls_insecure = false
|
|||||||
|
|
||||||
[image]
|
[image]
|
||||||
path = "/projects/base-image"
|
path = "/projects/base-image"
|
||||||
|
|
||||||
|
[[tracing]]
|
||||||
|
kind = "Console"
|
||||||
|
name = "console"
|
||||||
|
level = 1
|
||||||
|
|
||||||
|
[tracing.additional]
|
||||||
|
|
||||||
|
[[tracing]]
|
||||||
|
kind = "Otel"
|
||||||
|
name = "otel"
|
||||||
|
level = 2
|
||||||
|
|
||||||
|
[tracing.additional]
|
||||||
|
endpoint = "http://localhost:4317"
|
@ -6,7 +6,7 @@ use serenity::{
|
|||||||
model::colour,
|
model::colour,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::db::user_image::UserImage;
|
use crate::db::user_image::User;
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
#[description = "Enable/Disable the auto meme answer"]
|
#[description = "Enable/Disable the auto meme answer"]
|
||||||
@ -19,11 +19,11 @@ pub async fn enable(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu
|
|||||||
let embed = CreateEmbed::new()
|
let embed = CreateEmbed::new()
|
||||||
.title("Enable/Disable auto meme answer")
|
.title("Enable/Disable auto meme answer")
|
||||||
.footer(footer);
|
.footer(footer);
|
||||||
let mut user_in_db: UserImage =
|
let mut user_in_db: User =
|
||||||
match UserImage::find_by_server_id_user_id(&guild.get(), &msg.author.id.get()).await {
|
match User::find_by_server_id_user_id(&guild.get(), &msg.author.id.get()).await {
|
||||||
Ok(Some(user_in_db)) => user_in_db.clone(),
|
Ok(Some(user_in_db)) => user_in_db.clone(),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
let user_in_db = UserImage::new(guild.get(), msg.author.id.get(), false).unwrap();
|
let user_in_db = User::new(guild.get(), msg.author.id.get(), false).unwrap();
|
||||||
match user_in_db.create().await {
|
match user_in_db.create().await {
|
||||||
Ok(_) => user_in_db,
|
Ok(_) => user_in_db,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -10,7 +10,7 @@ use tokio::fs::File;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::ConfigGlobal,
|
config::ConfigGlobal,
|
||||||
db::user_image::UserImage,
|
db::user_image::User,
|
||||||
img::config_file::{ConfigImgGlobal, KeyWordItem},
|
img::config_file::{ConfigImgGlobal, KeyWordItem},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -27,12 +27,12 @@ impl EventHandler for Handler {
|
|||||||
Some(guild) => guild,
|
Some(guild) => guild,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
let user_in_db: UserImage =
|
let user_in_db: User =
|
||||||
match UserImage::find_by_server_id_user_id(&guild.get(), &msg.author.id.get()).await {
|
match User::find_by_server_id_user_id(&guild.get(), &msg.author.id.get()).await {
|
||||||
Ok(Some(user_in_db)) => user_in_db.clone(),
|
Ok(Some(user_in_db)) => user_in_db.clone(),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
let user_in_db =
|
let user_in_db =
|
||||||
UserImage::new(guild.get(), msg.author.id.get(), false).unwrap();
|
User::new(guild.get(), msg.author.id.get(), false).unwrap();
|
||||||
match user_in_db.create().await {
|
match user_in_db.create().await {
|
||||||
Ok(_) => user_in_db,
|
Ok(_) => user_in_db,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
use poise::samples::HelpConfiguration;
|
use poise::samples::HelpConfiguration;
|
||||||
|
use tracing::instrument;
|
||||||
use crate::botv2::init::{Context,Error};
|
use crate::botv2::init::{Context,Error};
|
||||||
|
|
||||||
/// Show help message
|
/// Show help message
|
||||||
#[poise::command(prefix_command, track_edits, category = "Utility")]
|
#[poise::command(prefix_command, track_edits, category = "Utility")]
|
||||||
|
#[instrument(skip(ctx),level="info")]
|
||||||
pub async fn help(
|
pub async fn help(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "Command to get help for"]
|
#[description = "Command to get help for"]
|
||||||
#[rest]
|
#[rest]
|
||||||
mut command: Option<String>,
|
mut command: Option<String>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
|
tracing::info!(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get(),"Help command called");
|
||||||
// This makes it possible to just make `help` a subcommand of any command
|
// This makes it possible to just make `help` a subcommand of any command
|
||||||
// `/fruit help` turns into `/help fruit`
|
// `/fruit help` turns into `/help fruit`
|
||||||
// `/fruit help apple` turns into `/help fruit apple`
|
// `/fruit help apple` turns into `/help fruit apple`
|
||||||
|
43
src/botv2/cmd/meme/enable.rs
Normal file
43
src/botv2/cmd/meme/enable.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
use crate::botv2::init::{Context,Error};
|
||||||
|
use poise::{serenity_prelude::{CreateEmbed, CreateEmbedFooter, CreateMessage}, CreateReply};
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
|
/// Enable/Disable auto answer available meme keywords
|
||||||
|
#[instrument(skip(ctx),level="info")]
|
||||||
|
#[poise::command(
|
||||||
|
slash_command,
|
||||||
|
prefix_command,
|
||||||
|
category = "meme"
|
||||||
|
)]
|
||||||
|
pub async fn enable(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
tracing::info!(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get(),"Enable command called");
|
||||||
|
let config_img = ctx.data().config_img.clone();
|
||||||
|
let list_value: Vec<(String, String, bool)> = config_img
|
||||||
|
.keyword
|
||||||
|
.iter()
|
||||||
|
.map(|x| (x.value.clone().join(", "), String::new(), true))
|
||||||
|
.collect();
|
||||||
|
if list_value.is_empty() {
|
||||||
|
let builder = CreateMessage::new().content("No meme keyword found");
|
||||||
|
if let Err(why) = ctx.channel_id().send_message(ctx.http(), builder).await {
|
||||||
|
tracing::error!("Error sending message: {:?}", why);
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let embed_vec = list_value.chunks(25).map(|chunks| {
|
||||||
|
let footer = CreateEmbedFooter::new("WeeboBot");
|
||||||
|
CreateEmbed::new()
|
||||||
|
.title("Meme List")
|
||||||
|
.fields(chunks.to_vec())
|
||||||
|
.footer(footer)
|
||||||
|
});
|
||||||
|
let mut reply = CreateReply::default();
|
||||||
|
reply.embeds = embed_vec.collect();
|
||||||
|
if let Err(why) = ctx.send(reply).await {
|
||||||
|
tracing::error!("Error sending message: {:?}", why);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/serenity-rs/poise/blob/current/examples/fluent_localization/main.rs
|
@ -1,12 +1,16 @@
|
|||||||
use crate::botv2::init::{Context,Error};
|
use crate::botv2::init::{Context,Error};
|
||||||
use poise::{serenity_prelude::{CreateEmbed, CreateEmbedFooter, CreateMessage}, CreateReply};
|
use poise::{serenity_prelude::{CreateEmbed, CreateEmbedFooter, CreateMessage}, CreateReply};
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
/// List available meme keywords
|
/// List available meme keywords
|
||||||
|
#[instrument(skip(ctx),level="info")]
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
prefix_command,
|
prefix_command,
|
||||||
category = "meme"
|
category = "meme"
|
||||||
)]
|
)]
|
||||||
pub async fn list(ctx: Context<'_>) -> Result<(), Error> {
|
pub async fn list(ctx: Context<'_>) -> Result<(), Error> {
|
||||||
|
tracing::info!(channel = ctx.channel_id().get(), guild = ?ctx.guild_id().unwrap().get(),"List command called");
|
||||||
let config_img = ctx.data().config_img.clone();
|
let config_img = ctx.data().config_img.clone();
|
||||||
let list_value: Vec<(String, String, bool)> = config_img
|
let list_value: Vec<(String, String, bool)> = config_img
|
||||||
.keyword
|
.keyword
|
||||||
@ -16,7 +20,7 @@ pub async fn list(ctx: Context<'_>) -> Result<(), Error> {
|
|||||||
if list_value.is_empty() {
|
if list_value.is_empty() {
|
||||||
let builder = CreateMessage::new().content("No meme keyword found");
|
let builder = CreateMessage::new().content("No meme keyword found");
|
||||||
if let Err(why) = ctx.channel_id().send_message(ctx.http(), builder).await {
|
if let Err(why) = ctx.channel_id().send_message(ctx.http(), builder).await {
|
||||||
println!("Error sending message: {:?}", why)
|
tracing::error!("Error sending message: {:?}", why);
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@ -30,7 +34,7 @@ pub async fn list(ctx: Context<'_>) -> Result<(), Error> {
|
|||||||
let mut reply = CreateReply::default();
|
let mut reply = CreateReply::default();
|
||||||
reply.embeds = embed_vec.collect();
|
reply.embeds = embed_vec.collect();
|
||||||
if let Err(why) = ctx.send(reply).await {
|
if let Err(why) = ctx.send(reply).await {
|
||||||
println!("Error sending message: {:?}", why)
|
tracing::error!("Error sending message: {:?}", why);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1 +1,2 @@
|
|||||||
pub mod list;
|
pub mod list;
|
||||||
|
pub mod enable;
|
@ -2,7 +2,7 @@ use tokio::fs::File;
|
|||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
use serenity::all::{CreateAttachment,CreateMessage};
|
use serenity::all::{CreateAttachment,CreateMessage};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::{db::user_image::UserImage, img::config_file::KeyWordItem};
|
use crate::{db::user_image::User, img::config_file::KeyWordItem};
|
||||||
use super::init::{Data, Error};
|
use super::init::{Data, Error};
|
||||||
|
|
||||||
pub async fn event_handler(
|
pub async fn event_handler(
|
||||||
@ -25,10 +25,10 @@ pub async fn event_handler(
|
|||||||
Some(guild) => guild,
|
Some(guild) => guild,
|
||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
let user_in_db = match UserImage::find_by_server_id_user_id(&guild.get(), &new_message.author.id.get()).await {
|
let user_in_db = match User::find_by_server_id_user_id(&guild.get(), &new_message.author.id.get()).await {
|
||||||
Ok(Some(user_in_db)) => user_in_db.clone(),
|
Ok(Some(user_in_db)) => user_in_db.clone(),
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
let user_in_db = UserImage::new(guild.get(), new_message.author.id.get(), false).unwrap();
|
let user_in_db = User::new(guild.get(), new_message.author.id.get(), false).unwrap();
|
||||||
match user_in_db.create().await {
|
match user_in_db.create().await {
|
||||||
Ok(_) => user_in_db,
|
Ok(_) => user_in_db,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use poise::serenity_prelude as serenity;
|
use poise::serenity_prelude as serenity;
|
||||||
|
use tracing::instrument;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use serenity::GatewayIntents;
|
use serenity::GatewayIntents;
|
||||||
|
use crate::botv2::cmd::meme::enable::enable;
|
||||||
use crate::botv2::cmd::{ping::ping,help::help, meme::list::list};
|
use crate::botv2::cmd::{ping::ping,help::help, meme::list::list};
|
||||||
use crate::{botv2::handler::event_handler, img::config_file::ConfigFile};
|
use crate::{botv2::handler::event_handler, img::config_file::ConfigFile};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
@ -15,6 +17,8 @@ pub struct Data{
|
|||||||
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
pub type Error = Box<dyn std::error::Error + Send + Sync>;
|
||||||
pub type Context<'a> = poise::Context<'a, Data, Error>;
|
pub type Context<'a> = poise::Context<'a, Data, Error>;
|
||||||
|
|
||||||
|
|
||||||
|
#[instrument(skip(ctx),level="info")]
|
||||||
#[poise::command(slash_command, prefix_command)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
async fn age(
|
async fn age(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
@ -26,8 +30,6 @@ async fn age(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub fn start_bot(config: Config, rx: oneshot::Receiver<()>){
|
pub fn start_bot(config: Config, rx: oneshot::Receiver<()>){
|
||||||
if config.token != "" {
|
if config.token != "" {
|
||||||
spawn_blocking(move||{
|
spawn_blocking(move||{
|
||||||
@ -64,7 +66,7 @@ pub fn start_bot(config: Config, rx: oneshot::Receiver<()>){
|
|||||||
let prefix = config.prefix.clone();
|
let prefix = config.prefix.clone();
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands: vec![age(), ping(),help(), list()],
|
commands: vec![age(), ping(), help(), list(), enable()],
|
||||||
prefix_options: poise::PrefixFrameworkOptions {
|
prefix_options: poise::PrefixFrameworkOptions {
|
||||||
prefix: Some(prefix.into()),
|
prefix: Some(prefix.into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serenity::prelude::TypeMapKey;
|
use poise::serenity_prelude::prelude::TypeMapKey;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use crate::tracing::tracing_kind::Tracing;
|
||||||
|
|
||||||
const DB_URL: &str = "DB_URL";
|
const DB_URL: &str = "DB_URL";
|
||||||
const DB_USER: &str = "DB_USER";
|
const DB_USER: &str = "DB_USER";
|
||||||
@ -38,6 +39,7 @@ pub struct Config {
|
|||||||
pub token: String,
|
pub token: String,
|
||||||
pub prefix: String,
|
pub prefix: String,
|
||||||
pub image: ImageConfig,
|
pub image: ImageConfig,
|
||||||
|
pub tracing: Vec<Tracing>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
@ -120,6 +122,7 @@ fn override_config_with_env_vars(config: Config) -> Config {
|
|||||||
image: ImageConfig {
|
image: ImageConfig {
|
||||||
path: env::var(IMAGE_PATH).unwrap_or(config.image.path),
|
path: env::var(IMAGE_PATH).unwrap_or(config.image.path),
|
||||||
},
|
},
|
||||||
|
tracing: config.tracing,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ use super::init::DB;
|
|||||||
const USERIMAGE: &str = "userimage";
|
const USERIMAGE: &str = "userimage";
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct UserImage {
|
pub struct User {
|
||||||
pub server_id: u64,
|
pub server_id: u64,
|
||||||
pub user_id: u64,
|
pub user_id: u64,
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserImage {
|
impl User {
|
||||||
pub fn new(server_id: u64, user_id: u64, enable: bool) -> Result<Self, surrealdb::Error> {
|
pub fn new(server_id: u64, user_id: u64, enable: bool) -> Result<Self, surrealdb::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
server_id,
|
server_id,
|
||||||
@ -50,7 +50,7 @@ impl UserImage {
|
|||||||
pub async fn find_by_server_id_user_id(
|
pub async fn find_by_server_id_user_id(
|
||||||
server_id: &u64,
|
server_id: &u64,
|
||||||
user_id: &u64,
|
user_id: &u64,
|
||||||
) -> Result<Option<UserImage>, surrealdb::Error> {
|
) -> Result<Option<User>, surrealdb::Error> {
|
||||||
let sql = format!(
|
let sql = format!(
|
||||||
"SELECT * FROM {} WHERE server_id = {} AND user_id = {}",
|
"SELECT * FROM {} WHERE server_id = {} AND user_id = {}",
|
||||||
USERIMAGE, server_id, user_id
|
USERIMAGE, server_id, user_id
|
||||||
@ -61,7 +61,7 @@ impl UserImage {
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let user_image: UserImage = match results.take(0) {
|
let user_image: User = match results.take(0) {
|
||||||
Ok(Some(user_image)) => user_image,
|
Ok(Some(user_image)) => user_image,
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
|
8
src/domain/meme/change_auto_meme.rs
Normal file
8
src/domain/meme/change_auto_meme.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
pub enum MemeChangeAutoMemeError {
|
||||||
|
UserNotFound,
|
||||||
|
UserCreateError,
|
||||||
|
UserUpdateError,
|
||||||
|
UserFindError,
|
||||||
|
UnknownError(String),
|
||||||
|
}
|
1
src/domain/meme/mod.rs
Normal file
1
src/domain/meme/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod change_auto_meme;
|
1
src/domain/mod.rs
Normal file
1
src/domain/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod meme;
|
@ -1,6 +1,6 @@
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serenity::prelude::TypeMapKey;
|
use poise::serenity_prelude::prelude::TypeMapKey;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use walkdir::{DirEntry, WalkDir};
|
use walkdir::{DirEntry, WalkDir};
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
pub mod bot;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod db;
|
pub mod db;
|
||||||
pub mod img;
|
pub mod img;
|
||||||
pub mod botv2;
|
pub mod botv2;
|
||||||
|
pub mod domain;
|
||||||
|
pub mod tracing;
|
@ -2,7 +2,7 @@ extern crate botdiscord;
|
|||||||
use std::{process, time::Duration};
|
use std::{process, time::Duration};
|
||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
use actix_web::{App, HttpServer};
|
use actix_web::{App, HttpServer};
|
||||||
use botdiscord::botv2::init::start_bot;
|
use botdiscord::{botv2::init::start_bot, tracing};
|
||||||
use botdiscord::config::parse_local_config;
|
use botdiscord::config::parse_local_config;
|
||||||
use tokio::{sync::oneshot, time::sleep};
|
use tokio::{sync::oneshot, time::sleep};
|
||||||
use botdiscord::db;
|
use botdiscord::db;
|
||||||
@ -11,6 +11,7 @@ use botdiscord::db;
|
|||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let config = parse_local_config();
|
let config = parse_local_config();
|
||||||
let port = config.port;
|
let port = config.port;
|
||||||
|
tracing::init::init_tracing(config.tracing.clone(), config.bot_name.clone());
|
||||||
match db::init::init_db(config.persistence.clone()).await {
|
match db::init::init_db(config.persistence.clone()).await {
|
||||||
Ok(_) => {}
|
Ok(_) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -32,6 +33,7 @@ async fn main() -> std::io::Result<()> {
|
|||||||
.await?;
|
.await?;
|
||||||
println!("API Server stopped.");
|
println!("API Server stopped.");
|
||||||
tx.send(()).unwrap();
|
tx.send(()).unwrap();
|
||||||
|
tracing::init::stop_tracing(config.tracing.clone(), config.bot_name.clone());
|
||||||
println!("Signal sent to bot.");
|
println!("Signal sent to bot.");
|
||||||
sleep(Duration::from_secs(2)).await;
|
sleep(Duration::from_secs(2)).await;
|
||||||
process::exit(1); // This is a workaround to stop the bot, it should be replaced by a better solution
|
process::exit(1); // This is a workaround to stop the bot, it should be replaced by a better solution
|
||||||
|
73
src/tracing/init.rs
Normal file
73
src/tracing/init.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
use std::{vec,fs::File,sync::Arc};
|
||||||
|
|
||||||
|
use opentelemetry::KeyValue;
|
||||||
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
|
use opentelemetry_sdk::{runtime, trace, Resource};
|
||||||
|
use time::format_description;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
use tracing::subscriber;
|
||||||
|
use tracing_bunyan_formatter::{BunyanFormattingLayer, JsonStorageLayer};
|
||||||
|
use tracing_opentelemetry::OpenTelemetryLayer;
|
||||||
|
use tracing_subscriber::{filter, fmt, Layer, Registry};
|
||||||
|
use super::tracing_kind::{Tracing, TracingKind};
|
||||||
|
use tracing_subscriber::fmt::time::UtcTime;
|
||||||
|
use tracing_subscriber::prelude::__tracing_subscriber_SubscriberExt;
|
||||||
|
|
||||||
|
pub fn init_tracing(tracing_config: Vec<Tracing>,name: String){
|
||||||
|
let mut layers = vec![];
|
||||||
|
for config in tracing_config {
|
||||||
|
match config.kind {
|
||||||
|
TracingKind::File => {
|
||||||
|
let file = File::options()
|
||||||
|
.create(true)
|
||||||
|
.truncate(false)
|
||||||
|
.append(true)
|
||||||
|
.open("trace.log")
|
||||||
|
.expect("Failed to create trace.log");
|
||||||
|
let formating_layer = BunyanFormattingLayer::new(name.clone(), Arc::new(file)).boxed();
|
||||||
|
layers.push(JsonStorageLayer.boxed());
|
||||||
|
layers.push(formating_layer);
|
||||||
|
}
|
||||||
|
TracingKind::Console => {
|
||||||
|
let time_format = format_description::parse("[hour]:[minute]:[second]")
|
||||||
|
.expect("format string should be valid!");
|
||||||
|
let timer = UtcTime::new(time_format);
|
||||||
|
|
||||||
|
let terminal_out = fmt::layer()
|
||||||
|
.with_thread_names(true)
|
||||||
|
.with_timer(timer)
|
||||||
|
.with_target(false)
|
||||||
|
.with_filter(LevelFilter::from(config.level)).boxed();
|
||||||
|
layers.push(terminal_out);
|
||||||
|
}
|
||||||
|
TracingKind::Otel => {
|
||||||
|
let endpoint = match config.additional.get("endpoint"){
|
||||||
|
Some(endpoint) => endpoint.to_string(),
|
||||||
|
None => "http://localhost:4317".to_string()
|
||||||
|
};
|
||||||
|
let pod_name = std::env::var("POD_NAME").unwrap_or_else(|_| "not_a_pod".to_string());
|
||||||
|
let telemetry = opentelemetry_otlp::new_pipeline()
|
||||||
|
.tracing()
|
||||||
|
.with_exporter(opentelemetry_otlp::new_exporter().tonic().with_endpoint(endpoint))
|
||||||
|
.with_trace_config(trace::config().with_resource(Resource::new(vec![
|
||||||
|
KeyValue::new("service.name", name.clone()),
|
||||||
|
KeyValue::new("service.pod", pod_name.clone()),
|
||||||
|
])))
|
||||||
|
.install_batch(runtime::Tokio)
|
||||||
|
.expect("Failed to install opentelemetry");
|
||||||
|
let tele_layer = OpenTelemetryLayer::new(telemetry).with_filter(filter::LevelFilter::from(config.level));
|
||||||
|
layers.push(tele_layer.boxed());
|
||||||
|
println!("Otel Tracing not implemented yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subscriber::set_global_default(Registry::default().with(layers))
|
||||||
|
.expect("setting default subscriber failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn stop_tracing(tracing_config: Vec<Tracing>,_name: String){
|
||||||
|
if tracing_config.iter().any(|x| x.kind == TracingKind::Otel){
|
||||||
|
opentelemetry::global::shutdown_tracer_provider();
|
||||||
|
}
|
||||||
|
}
|
61
src/tracing/level.rs
Normal file
61
src/tracing/level.rs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
use std::fmt::{Debug, Display};
|
||||||
|
use tracing::Level;
|
||||||
|
|
||||||
|
#[derive(Serialize_repr, Deserialize_repr, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum VerboseLevel {
|
||||||
|
ERROR = 4,
|
||||||
|
WARN = 3,
|
||||||
|
INFO = 2,
|
||||||
|
DEBUG = 1,
|
||||||
|
TRACE = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VerboseLevel> for Level {
|
||||||
|
fn from(level: VerboseLevel) -> Self {
|
||||||
|
match level {
|
||||||
|
VerboseLevel::ERROR => Level::ERROR,
|
||||||
|
VerboseLevel::WARN => Level::WARN,
|
||||||
|
VerboseLevel::INFO => Level::INFO,
|
||||||
|
VerboseLevel::DEBUG => Level::DEBUG,
|
||||||
|
VerboseLevel::TRACE => Level::TRACE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<VerboseLevel> for tracing_subscriber::filter::LevelFilter {
|
||||||
|
fn from(level: VerboseLevel) -> Self {
|
||||||
|
match level {
|
||||||
|
VerboseLevel::ERROR => tracing_subscriber::filter::LevelFilter::ERROR,
|
||||||
|
VerboseLevel::WARN => tracing_subscriber::filter::LevelFilter::WARN,
|
||||||
|
VerboseLevel::INFO => tracing_subscriber::filter::LevelFilter::INFO,
|
||||||
|
VerboseLevel::DEBUG => tracing_subscriber::filter::LevelFilter::DEBUG,
|
||||||
|
VerboseLevel::TRACE => tracing_subscriber::filter::LevelFilter::TRACE,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for VerboseLevel {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ERROR => write!(f, "ERROR"),
|
||||||
|
Self::WARN => write!(f, "WARN"),
|
||||||
|
Self::INFO => write!(f, "INFO"),
|
||||||
|
Self::DEBUG => write!(f, "DEBUG"),
|
||||||
|
Self::TRACE => write!(f, "TRACE"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for VerboseLevel{
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::ERROR => write!(f, "ERROR"),
|
||||||
|
Self::WARN => write!(f, "WARN"),
|
||||||
|
Self::INFO => write!(f, "INFO"),
|
||||||
|
Self::DEBUG => write!(f, "DEBUG"),
|
||||||
|
Self::TRACE => write!(f, "TRACE"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
src/tracing/mod.rs
Normal file
3
src/tracing/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod level;
|
||||||
|
pub mod tracing_kind;
|
||||||
|
pub mod init;
|
20
src/tracing/tracing_kind.rs
Normal file
20
src/tracing/tracing_kind.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::level::VerboseLevel;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||||
|
pub enum TracingKind {
|
||||||
|
File,
|
||||||
|
Console,
|
||||||
|
Otel,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, PartialEq, Debug)]
|
||||||
|
pub struct Tracing {
|
||||||
|
pub kind: TracingKind,
|
||||||
|
pub name: String,
|
||||||
|
pub level: VerboseLevel,
|
||||||
|
pub additional: HashMap<String,String>
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user