Better structure and logger

This commit is contained in:
2025-08-30 02:41:39 +02:00
parent 6797007526
commit 19c102a7e8
7 changed files with 124 additions and 14 deletions
Generated
+1
View File
@@ -1683,6 +1683,7 @@ name = "voxa-server"
version = "0.1.0"
dependencies = [
"anyhow",
"once_cell",
"serde",
"serde_json",
"wasmtime",
+1
View File
@@ -5,6 +5,7 @@ edition = "2024"
[dependencies]
anyhow = "1.0.99"
once_cell = "1.21.3"
serde = { version = "1.0.219", features = ["serde_derive"] }
serde_json = "1.0.143"
wasmtime = { version = "36.0.2", optional = true }
+66 -9
View File
@@ -1,7 +1,11 @@
use std::path::Path;
use std::{
net::TcpListener,
path::{Path, PathBuf},
};
#[cfg(feature = "loader")]
pub mod loader;
pub mod logger;
pub mod macros;
pub mod plugin;
pub mod vfs;
@@ -15,6 +19,13 @@ pub struct ServerConfig {
port: u16,
}
pub struct Server {
plugins: Vec<PluginInstance>,
root: PathBuf,
config: ServerConfig,
logger: logger::Logger,
}
impl Default for ServerConfig {
fn default() -> Self {
Self { port: 7080 }
@@ -22,19 +33,65 @@ impl Default for ServerConfig {
}
impl ServerConfig {
pub fn start(&self, root: &Path) -> Result<()> {
let mut plugins: Vec<PluginInstance> = Vec::new();
#[cfg(feature = "loader")]
loader::load_plugins(&mut plugins, &root.join("./plugins"))?;
self.start_with(plugins, root)
pub fn build(self, root: &Path) -> Server {
Server::new_config(root, self)
}
}
pub fn start_with(&self, mut plugins: Vec<PluginInstance>, root: &Path) -> Result<()> {
for plugin in &mut plugins {
impl Server {
pub fn new(root: &Path) -> Self {
Self {
plugins: Vec::new(),
root: root.to_path_buf(),
config: ServerConfig::default(),
logger: logger::Logger::new("Server"),
}
}
pub fn new_config(root: &Path, config: ServerConfig) -> Self {
Self {
plugins: Vec::new(),
root: root.to_path_buf(),
config,
logger: logger::Logger::new("Server"),
}
}
pub fn run(&mut self) -> Result<()> {
// Load plugins
#[cfg(feature = "loader")]
loader::load_plugins(&mut self.plugins, &self.root.join("./plugins"))?;
// Initialize plugins
for plugin in &mut self.plugins {
plugin.init();
}
// Start server
let listener = TcpListener::bind(format!("0.0.0.0:{}", self.config.port));
self.logger
.info(format!("Server listening 0.0.0.0:{}", self.config.port));
self.logger
.warn(format!("Server listening 0.0.0.0:{}", self.config.port));
self.logger
.error(format!("Server listening 0.0.0.0:{}", self.config.port));
for stream in listener?.incoming() {
match stream {
Ok(stream) => {
self.logger
.info(format!("New connection: {}", stream.peer_addr()?));
}
Err(e) => {
self.logger.error(format!("Connection failed: {}", e));
}
}
}
Ok(())
}
pub fn add_plugin(&mut self, plugin: PluginInstance) {
self.plugins.push(plugin);
}
}
+8 -4
View File
@@ -3,7 +3,11 @@ use std::path::Path;
use wasmtime::{Engine, Linker, Module, Store};
use wasmtime_wasi::WasiCtxBuilder;
use crate::{PluginInstance, vfs};
use crate::{PluginInstance, logger, vfs};
logger! {
const LOGGER "Loader"
}
pub fn load_plugin(wasm_path: &Path) -> anyhow::Result<PluginInstance> {
let engine = Engine::default();
@@ -30,17 +34,17 @@ pub fn load_plugins(arr: &mut Vec<PluginInstance>, path: &Path) -> crate::Result
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("wasm") {
println!("Loading plugin: {:?}", path);
LOGGER.info(format!("Loading plugin: {:?}", path));
match load_plugin(&path) {
Ok(plugin) => {
arr.push(plugin);
}
Err(e) => eprintln!("Failed to load plugin {:?}: {}", path, e),
Err(e) => LOGGER.error(format!("Failed to load plugin {:?}: {}", path, e)),
}
}
}
} else {
eprintln!("{:?} is not a directory", path);
LOGGER.error(format!("{:?} is not a directory", path));
}
Ok(())
+25
View File
@@ -0,0 +1,25 @@
use std::fmt::Display;
pub struct Logger {
name: String,
}
impl Logger {
pub fn new<T: Display>(name: T) -> Self {
Logger {
name: name.to_string(),
}
}
pub fn info<T: Display>(&self, message: T) {
println!("\x1b[32mINFO\x1b[0m ({}) › {}", self.name, message);
}
pub fn warn<T: Display>(&self, message: T) {
println!("\x1b[33mWARN\x1b[0m ({}) › {}", self.name, message);
}
pub fn error<T: Display>(&self, message: T) {
println!("\x1b[31mERROR\x1b[0m ({}) › {}", self.name, message);
}
}
+21
View File
@@ -13,3 +13,24 @@ macro_rules! export_plugin {
}
};
}
#[macro_export]
macro_rules! logger {
(const $i:ident $name:expr) => {
const $i: once_cell::sync::Lazy<$crate::logger::Logger> =
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name));
};
($i:ident $name:expr) => {
const $i: once_cell::sync::Lazy<$crate::logger::Logger> =
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name));
};
(const $name:expr) => {
once_cell::sync::Lazy::new(|| $crate::logger::Logger::new($name))
};
($name:expr) => {
$crate::logger::Logger::new($name)
};
}
+3 -2
View File
@@ -5,6 +5,7 @@ use voxa_server::{ServerConfig, vfs};
fn main() -> anyhow::Result<()> {
let root = PathBuf::new();
let config: ServerConfig = vfs::read_config(&root.join("config.json"))?;
config.start(&root)
let mut server = config.build(&root);
server.run()?;
Ok(())
}