Make Logging configurable
This commit is contained in:
parent
9ac4bdbd50
commit
bcbde20623
@ -4,11 +4,15 @@ use serde::{Deserialize, Serialize};
|
|||||||
pub struct CommandsConfig {
|
pub struct CommandsConfig {
|
||||||
/// Are commands from the Console accepted ?
|
/// Are commands from the Console accepted ?
|
||||||
pub use_console: bool,
|
pub use_console: bool,
|
||||||
// TODO: commands...
|
/// Should be commands from players be logged in console?
|
||||||
|
pub log_console: bool, // TODO: commands...
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CommandsConfig {
|
impl Default for CommandsConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self { use_console: true }
|
Self {
|
||||||
|
use_console: true,
|
||||||
|
log_console: true,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
|
use logging::LoggingConfig;
|
||||||
use pumpkin_core::{Difficulty, GameMode};
|
use pumpkin_core::{Difficulty, GameMode};
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||||
|
|
||||||
@ -10,6 +11,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
|
pub mod logging;
|
||||||
pub mod proxy;
|
pub mod proxy;
|
||||||
pub mod resource_pack;
|
pub mod resource_pack;
|
||||||
|
|
||||||
@ -46,6 +48,7 @@ pub struct AdvancedConfiguration {
|
|||||||
pub commands: CommandsConfig,
|
pub commands: CommandsConfig,
|
||||||
pub rcon: RCONConfig,
|
pub rcon: RCONConfig,
|
||||||
pub pvp: PVPConfig,
|
pub pvp: PVPConfig,
|
||||||
|
pub logging: LoggingConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
|||||||
40
pumpkin-config/src/logging.rs
Normal file
40
pumpkin-config/src/logging.rs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct LoggingConfig {
|
||||||
|
pub enabled: bool,
|
||||||
|
pub level: LevelFilter,
|
||||||
|
pub env: bool,
|
||||||
|
pub threads: bool,
|
||||||
|
pub color: bool,
|
||||||
|
pub timestamp: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for LoggingConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: true,
|
||||||
|
level: LevelFilter::Info,
|
||||||
|
env: false,
|
||||||
|
threads: true,
|
||||||
|
color: true,
|
||||||
|
timestamp: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
|
pub enum LevelFilter {
|
||||||
|
/// A level lower than all log levels.
|
||||||
|
Off,
|
||||||
|
/// Corresponds to the `Error` log level.
|
||||||
|
Error,
|
||||||
|
/// Corresponds to the `Warn` log level.
|
||||||
|
Warn,
|
||||||
|
/// Corresponds to the `Info` log level.
|
||||||
|
Info,
|
||||||
|
/// Corresponds to the `Debug` log level.
|
||||||
|
Debug,
|
||||||
|
/// Corresponds to the `Trace` log level.
|
||||||
|
Trace,
|
||||||
|
}
|
||||||
@ -13,6 +13,31 @@ pub struct RCONConfig {
|
|||||||
/// The maximum number of concurrent RCON connections allowed.
|
/// The maximum number of concurrent RCON connections allowed.
|
||||||
/// If 0 there is no limit
|
/// If 0 there is no limit
|
||||||
pub max_connections: u32,
|
pub max_connections: u32,
|
||||||
|
/// RCON Logging
|
||||||
|
pub logging: RCONLogging,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone, Debug)]
|
||||||
|
pub struct RCONLogging {
|
||||||
|
/// Whether successful RCON logins should be logged.
|
||||||
|
pub log_logged_successfully: bool,
|
||||||
|
/// Whether failed RCON login attempts with incorrect passwords should be logged.
|
||||||
|
pub log_wrong_password: bool,
|
||||||
|
/// Whether all RCON commands, regardless of success or failure, should be logged.
|
||||||
|
pub log_commands: bool,
|
||||||
|
/// Whether RCON quit commands should be logged.
|
||||||
|
pub log_quit: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RCONLogging {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
log_logged_successfully: true,
|
||||||
|
log_wrong_password: true,
|
||||||
|
log_commands: true,
|
||||||
|
log_quit: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RCONConfig {
|
impl Default for RCONConfig {
|
||||||
@ -22,6 +47,7 @@ impl Default for RCONConfig {
|
|||||||
address: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 25575),
|
address: SocketAddr::new(Ipv4Addr::new(0, 0, 0, 0).into(), 25575),
|
||||||
password: "".to_string(),
|
password: "".to_string(),
|
||||||
max_connections: 0,
|
max_connections: 0,
|
||||||
|
logging: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,7 @@ base64 = "0.22.1"
|
|||||||
png = "0.17.14"
|
png = "0.17.14"
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
simple_logger = "5.0.0"
|
simple_logger = { version = "5.0.0", features = ["threads"] }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
|
||||||
# networking
|
# networking
|
||||||
|
|||||||
@ -227,6 +227,13 @@ impl Player {
|
|||||||
pub fn handle_chat_command(&self, server: &Arc<Server>, command: SChatCommand) {
|
pub fn handle_chat_command(&self, server: &Arc<Server>, command: SChatCommand) {
|
||||||
let dispatcher = server.command_dispatcher.clone();
|
let dispatcher = server.command_dispatcher.clone();
|
||||||
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
|
dispatcher.handle_command(&mut CommandSender::Player(self), server, &command.command);
|
||||||
|
if ADVANCED_CONFIG.commands.log_console {
|
||||||
|
log::info!(
|
||||||
|
"Player ({}): executed command /{}",
|
||||||
|
self.gameprofile.name,
|
||||||
|
command.command
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_player_ground(&self, _server: &Arc<Server>, ground: SSetPlayerGround) {
|
pub fn handle_player_ground(&self, _server: &Arc<Server>, ground: SSetPlayerGround) {
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
#[cfg(target_os = "wasi")]
|
#[cfg(target_os = "wasi")]
|
||||||
compile_error!("Compiling for WASI targets is not supported!");
|
compile_error!("Compiling for WASI targets is not supported!");
|
||||||
|
|
||||||
|
use log::LevelFilter;
|
||||||
use mio::net::TcpListener;
|
use mio::net::TcpListener;
|
||||||
use mio::{Events, Interest, Poll, Token};
|
use mio::{Events, Interest, Poll, Token};
|
||||||
|
|
||||||
@ -38,6 +39,38 @@ pub mod server;
|
|||||||
pub mod util;
|
pub mod util;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
|
||||||
|
fn init_logger() {
|
||||||
|
use pumpkin_config::ADVANCED_CONFIG;
|
||||||
|
if ADVANCED_CONFIG.logging.enabled {
|
||||||
|
let mut logger = simple_logger::SimpleLogger::new();
|
||||||
|
|
||||||
|
if !ADVANCED_CONFIG.logging.timestamp {
|
||||||
|
logger = logger.without_timestamps();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ADVANCED_CONFIG.logging.env {
|
||||||
|
logger = logger.env();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger = logger.with_level(convert_logger_filter(ADVANCED_CONFIG.logging.level));
|
||||||
|
|
||||||
|
logger = logger.with_colors(ADVANCED_CONFIG.logging.color);
|
||||||
|
logger = logger.with_threads(ADVANCED_CONFIG.logging.threads);
|
||||||
|
logger.init().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_logger_filter(level: pumpkin_config::logging::LevelFilter) -> LevelFilter {
|
||||||
|
match level {
|
||||||
|
pumpkin_config::logging::LevelFilter::Off => LevelFilter::Off,
|
||||||
|
pumpkin_config::logging::LevelFilter::Error => LevelFilter::Error,
|
||||||
|
pumpkin_config::logging::LevelFilter::Warn => LevelFilter::Warn,
|
||||||
|
pumpkin_config::logging::LevelFilter::Info => LevelFilter::Info,
|
||||||
|
pumpkin_config::logging::LevelFilter::Debug => LevelFilter::Debug,
|
||||||
|
pumpkin_config::logging::LevelFilter::Trace => LevelFilter::Trace,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@ -46,10 +79,7 @@ fn main() -> io::Result<()> {
|
|||||||
use pumpkin_core::text::{color::NamedColor, TextComponent};
|
use pumpkin_core::text::{color::NamedColor, TextComponent};
|
||||||
use rcon::RCONServer;
|
use rcon::RCONServer;
|
||||||
|
|
||||||
simple_logger::SimpleLogger::new()
|
init_logger();
|
||||||
.with_level(log::LevelFilter::Info)
|
|
||||||
.init()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io::{self, Read, Write},
|
io::{self, Read, Write},
|
||||||
|
net::SocketAddr,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -9,7 +10,7 @@ use mio::{
|
|||||||
Events, Interest, Poll, Token,
|
Events, Interest, Poll, Token,
|
||||||
};
|
};
|
||||||
use packet::{ClientboundPacket, Packet, PacketError, ServerboundPacket};
|
use packet::{ClientboundPacket, Packet, PacketError, ServerboundPacket};
|
||||||
use pumpkin_config::RCONConfig;
|
use pumpkin_config::{RCONConfig, ADVANCED_CONFIG};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::server::Server;
|
use crate::server::Server;
|
||||||
@ -71,11 +72,9 @@ impl RCONServer {
|
|||||||
return Err(e);
|
return Err(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
log::info!("Accepted connection from: {}", address);
|
|
||||||
if config.max_connections != 0
|
if config.max_connections != 0
|
||||||
&& connections.len() >= config.max_connections as usize
|
&& connections.len() >= config.max_connections as usize
|
||||||
{
|
{
|
||||||
log::warn!("Max RCON connections reached");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +86,7 @@ impl RCONServer {
|
|||||||
Interest::READABLE.add(Interest::WRITABLE),
|
Interest::READABLE.add(Interest::WRITABLE),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
connections.insert(token, RCONClient::new(connection));
|
connections.insert(token, RCONClient::new(connection, address));
|
||||||
},
|
},
|
||||||
|
|
||||||
token => {
|
token => {
|
||||||
@ -98,6 +97,13 @@ impl RCONServer {
|
|||||||
};
|
};
|
||||||
if done {
|
if done {
|
||||||
if let Some(mut client) = connections.remove(&token) {
|
if let Some(mut client) = connections.remove(&token) {
|
||||||
|
let config = &ADVANCED_CONFIG.rcon;
|
||||||
|
if config.logging.log_quit {
|
||||||
|
log::info!(
|
||||||
|
"RCON ({}): Client closed connection",
|
||||||
|
client.address
|
||||||
|
);
|
||||||
|
}
|
||||||
poll.registry().deregister(&mut client.connection)?;
|
poll.registry().deregister(&mut client.connection)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -116,15 +122,17 @@ impl RCONServer {
|
|||||||
|
|
||||||
pub struct RCONClient {
|
pub struct RCONClient {
|
||||||
connection: TcpStream,
|
connection: TcpStream,
|
||||||
|
address: SocketAddr,
|
||||||
logged_in: bool,
|
logged_in: bool,
|
||||||
incoming: Vec<u8>,
|
incoming: Vec<u8>,
|
||||||
closed: bool,
|
closed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RCONClient {
|
impl RCONClient {
|
||||||
pub const fn new(connection: TcpStream) -> Self {
|
pub const fn new(connection: TcpStream, address: SocketAddr) -> Self {
|
||||||
Self {
|
Self {
|
||||||
connection,
|
connection,
|
||||||
|
address,
|
||||||
logged_in: false,
|
logged_in: false,
|
||||||
incoming: Vec::new(),
|
incoming: Vec::new(),
|
||||||
closed: false,
|
closed: false,
|
||||||
@ -147,7 +155,7 @@ impl RCONClient {
|
|||||||
}
|
}
|
||||||
// If we get a close here, we might have a reply, which we still want to write.
|
// If we get a close here, we might have a reply, which we still want to write.
|
||||||
let _ = self.poll(server, password).await.map_err(|e| {
|
let _ = self.poll(server, password).await.map_err(|e| {
|
||||||
log::error!("rcon error: {e}");
|
log::error!("RCON error: {e}");
|
||||||
self.closed = true;
|
self.closed = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -161,16 +169,21 @@ impl RCONClient {
|
|||||||
None => return Ok(()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let config = &ADVANCED_CONFIG.rcon;
|
||||||
match packet.get_type() {
|
match packet.get_type() {
|
||||||
ServerboundPacket::Auth => {
|
ServerboundPacket::Auth => {
|
||||||
let body = packet.get_body();
|
let body = packet.get_body();
|
||||||
if !body.is_empty() && packet.get_body() == password {
|
if !body.is_empty() && packet.get_body() == password {
|
||||||
self.send(ClientboundPacket::AuthResponse, packet.get_id(), "".into())
|
self.send(ClientboundPacket::AuthResponse, packet.get_id(), "".into())
|
||||||
.await?;
|
.await?;
|
||||||
log::info!("RCON Client logged in successfully");
|
if config.logging.log_logged_successfully {
|
||||||
|
log::info!("RCON ({}): Client logged in successfully", self.address);
|
||||||
|
}
|
||||||
self.logged_in = true;
|
self.logged_in = true;
|
||||||
} else {
|
} else {
|
||||||
log::warn!("RCON Client has tried wrong password");
|
if config.logging.log_wrong_password {
|
||||||
|
log::info!("RCON ({}): Client has tried wrong password", self.address);
|
||||||
|
}
|
||||||
self.send(ClientboundPacket::AuthResponse, -1, "".into())
|
self.send(ClientboundPacket::AuthResponse, -1, "".into())
|
||||||
.await?;
|
.await?;
|
||||||
self.closed = true;
|
self.closed = true;
|
||||||
@ -186,6 +199,9 @@ impl RCONClient {
|
|||||||
packet.get_body(),
|
packet.get_body(),
|
||||||
);
|
);
|
||||||
for line in output {
|
for line in output {
|
||||||
|
if config.logging.log_commands {
|
||||||
|
log::info!("RCON ({}): {}", self.address, line);
|
||||||
|
}
|
||||||
self.send(ClientboundPacket::Output, packet.get_id(), line)
|
self.send(ClientboundPacket::Output, packet.get_id(), line)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user