Skip to content

Commit 5b8d7a8

Browse files
committed
feat: add basic loggers
1 parent 8df910f commit 5b8d7a8

File tree

19 files changed

+243
-252
lines changed

19 files changed

+243
-252
lines changed

capybara-bin/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ serde_yaml = "0.9.27"
3131
once_cell = "1.19.0"
3232
async-trait = "0.1.74"
3333
ahash = "0.8.11"
34-
pretty_env_logger = "0.5.0"
3534
dirs = "5.0.1"
3635
hashbrown = { version = "0.15.2", features = ["serde"] }
3736
duration-str = "0.11.2"

capybara-bin/src/bootstrap/config.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::collections::HashMap;
22

3+
use capybara_core::logger::Config as LoggerConfig;
34
use serde::{Deserialize, Serialize};
45

56
#[derive(Debug, Clone, Serialize, Deserialize)]
67
pub struct BootstrapConf {
78
#[serde(default)]
89
pub resolvers: HashMap<String, ResolverConf>,
910
#[serde(default)]
10-
pub loggers: HashMap<String, LoggerConf>,
11+
pub loggers: HashMap<String, LoggerConfig>,
1112
#[serde(default)]
1213
pub providers: Vec<ProviderConf>,
1314
}
@@ -18,11 +19,6 @@ pub struct ResolverConf {
1819
pub props: HashMap<String, serde_yaml::Value>,
1920
}
2021

21-
#[derive(Debug, Clone, Serialize, Deserialize)]
22-
pub struct LoggerConf {
23-
pub path: String,
24-
}
25-
2622
#[derive(Debug, Clone, Serialize, Deserialize)]
2723
pub struct ProviderConf {
2824
pub kind: String,

capybara-bin/src/bootstrap/runtime.rs

+43-52
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
use std::net::{IpAddr, SocketAddr};
1+
use std::net::SocketAddr;
22
use std::path::PathBuf;
33
use std::sync::Arc;
44
use std::time::Duration;
55

66
use hashbrown::HashMap;
77
use tokio::sync::{mpsc, Notify, RwLock};
88

9-
use capybara_core::proto::{Listener, Signal};
9+
use capybara_core::logger;
10+
use capybara_core::proto::{Addr, Listener, Signal};
1011
use capybara_core::protocol::http::HttpListener;
1112
use capybara_core::protocol::stream::StreamListener;
1213
use capybara_core::transport::tcp::TcpStreamPoolBuilder;
1314
use capybara_core::transport::tls::TlsStreamPoolBuilder;
1415
use capybara_core::transport::TlsAcceptorBuilder;
15-
use capybara_core::{CapybaraError, Pool, Pools, RoundRobinPools, WeightedPools};
16+
use capybara_core::{Pool, Pools, RoundRobinPools, WeightedPools};
1617
use capybara_etc::{
1718
BalanceStrategy, Config, ListenerConfig, Properties, TransportKind, UpstreamConfig,
1819
};
@@ -66,15 +67,15 @@ impl Dispatcher {
6667

6768
let p = match endpoint.transport.as_ref().unwrap_or(&v.transport) {
6869
TransportKind::Tcp => {
70+
let addr = endpoint.addr.parse::<Addr>()?;
71+
let closer = Clone::clone(&self.closer);
6972
if endpoint
7073
.tls
7174
.unwrap_or_else(|| endpoint.addr.ends_with(":443"))
7275
{
73-
let b = to_tls_stream_pool_builder(&endpoint.addr)?;
74-
Pool::Tls(b.build(Clone::clone(&self.closer)).await?)
76+
Pool::Tls(TlsStreamPoolBuilder::new(addr).build(closer).await?)
7577
} else {
76-
let b = to_tcp_stream_pool_builder(&endpoint.addr)?;
77-
Pool::Tcp(b.build(Clone::clone(&self.closer)).await?)
78+
Pool::Tcp(TcpStreamPoolBuilder::new(addr).build(closer).await?)
7879
}
7980
}
8081
TransportKind::Udp => {
@@ -92,17 +93,15 @@ impl Dispatcher {
9293
for endpoint in &v.endpoints {
9394
let pool = match endpoint.transport.unwrap_or(v.transport) {
9495
TransportKind::Tcp => {
96+
let addr = endpoint.addr.parse::<Addr>()?;
97+
let closer = Clone::clone(&self.closer);
9598
if endpoint
9699
.tls
97100
.unwrap_or_else(|| endpoint.addr.ends_with(":443"))
98101
{
99-
let b = to_tls_stream_pool_builder(&endpoint.addr)?;
100-
let p = b.build(Clone::clone(&self.closer)).await?;
101-
Pool::Tls(p)
102+
Pool::Tls(TlsStreamPoolBuilder::new(addr).build(closer).await?)
102103
} else {
103-
let b = to_tcp_stream_pool_builder(&endpoint.addr)?;
104-
let p = b.build(Clone::clone(&self.closer)).await?;
105-
Pool::Tcp(p)
104+
Pool::Tcp(TcpStreamPoolBuilder::new(addr).build(closer).await?)
106105
}
107106
}
108107
TransportKind::Udp => {
@@ -254,48 +253,11 @@ impl Dispatcher {
254253
}
255254
}
256255

257-
#[inline]
258-
fn to_tls_stream_pool_builder(addr: &str) -> anyhow::Result<TlsStreamPoolBuilder> {
259-
let mut sp = addr.split(':');
260-
if let Some(left) = sp.next() {
261-
if let Some(right) = sp.next() {
262-
if let Ok(port) = right.parse::<u16>() {
263-
if sp.next().is_none() {
264-
return Ok(match left.parse::<IpAddr>() {
265-
Ok(ip) => TlsStreamPoolBuilder::with_addr(SocketAddr::new(ip, port)),
266-
Err(_) => TlsStreamPoolBuilder::with_domain(left, port),
267-
});
268-
}
269-
}
270-
}
271-
}
272-
273-
bail!(CapybaraError::InvalidUpstream(addr.to_string().into()));
274-
}
275-
276-
#[inline]
277-
fn to_tcp_stream_pool_builder(addr: &str) -> anyhow::Result<TcpStreamPoolBuilder> {
278-
let mut sp = addr.split(':');
279-
if let Some(left) = sp.next() {
280-
if let Some(right) = sp.next() {
281-
if let Ok(port) = right.parse::<u16>() {
282-
if sp.next().is_none() {
283-
return Ok(match left.parse::<IpAddr>() {
284-
Ok(ip) => TcpStreamPoolBuilder::with_addr(SocketAddr::new(ip, port)),
285-
Err(_) => TcpStreamPoolBuilder::with_domain(left, port),
286-
});
287-
}
288-
}
289-
}
290-
}
291-
292-
bail!(CapybaraError::InvalidUpstream(addr.to_string().into()));
293-
}
294-
295256
pub(crate) struct Bootstrap {
296257
bc: BootstrapConf,
297258
c: Arc<RwLock<Config>>,
298259
dispatcher: Arc<RwLock<Dispatcher>>,
260+
loggers: Arc<RwLock<HashMap<String, logger::Key>>>,
299261
}
300262

301263
impl Bootstrap {
@@ -304,9 +266,37 @@ impl Bootstrap {
304266
w.shutdown().await;
305267
}
306268

269+
async fn generate_loggers(&self) -> anyhow::Result<()> {
270+
let mut loggers: HashMap<String, logger::Key> = Default::default();
271+
let mut has_main = false;
272+
for (k, v) in &self.bc.loggers {
273+
if k == "main" {
274+
has_main = true;
275+
logger::init_global(v)?;
276+
} else {
277+
let lk = logger::register(v)?;
278+
loggers.insert(Clone::clone(k), lk);
279+
}
280+
}
281+
282+
// use default logger settings if no main logger found
283+
if !has_main {
284+
logger::init_global(&logger::Config::default())?;
285+
}
286+
287+
// extend loggers
288+
{
289+
let mut w = self.loggers.write().await;
290+
w.extend(loggers);
291+
}
292+
293+
Ok(())
294+
}
295+
307296
pub(crate) async fn start(&self) -> anyhow::Result<()> {
308-
let (c_tx, mut c_rx) = mpsc::unbounded_channel::<Config>();
297+
self.generate_loggers().await?;
309298

299+
let (c_tx, mut c_rx) = mpsc::unbounded_channel::<Config>();
310300
{
311301
let dispatcher = Clone::clone(&self.dispatcher);
312302
let c = Clone::clone(&self.c);
@@ -428,6 +418,7 @@ impl From<BootstrapConf> for Bootstrap {
428418
bc: value,
429419
c: Default::default(),
430420
dispatcher: Default::default(),
421+
loggers: Default::default(),
431422
}
432423
}
433424
}

capybara-bin/src/main.rs

-6
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,8 @@ enum Commands {
5050
},
5151
}
5252

53-
fn init() {
54-
pretty_env_logger::try_init_timed().ok();
55-
}
56-
5753
#[tokio::main]
5854
async fn main() -> anyhow::Result<()> {
59-
init();
60-
6155
let cli = Cli::parse();
6256

6357
let shutdown = Arc::new(Notify::new());

capybara-core/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ liquid = "0.26"
7373
rustls = "0.23"
7474
webpki-roots = "0.26"
7575
tokio-rustls = "0.26"
76+
dirs = "5.0"
7677

7778
[[example]]
7879
name = "httpbin"

capybara-core/src/error.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::borrow::Cow;
22
use std::io;
3-
use tokio::time::error::Elapsed;
43

54
#[derive(thiserror::Error, Debug)]
65
pub enum CapybaraError {
@@ -32,6 +31,9 @@ pub enum CapybaraError {
3231
#[error("invalid route")]
3332
InvalidRoute,
3433

34+
#[error("invalid address '{0}'")]
35+
InvalidAddress(/* address */ Cow<'static, str>),
36+
3537
#[error("invalid upstream pool")]
3638
InvalidUpstreamPool,
3739

capybara-core/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub type Result<T> = std::result::Result<T, CapybaraError>;
2626

2727
mod builtin;
2828
mod error;
29-
mod logger;
29+
pub mod logger;
3030
mod macros;
3131
pub mod pipeline;
3232
pub mod proto;

capybara-core/src/logger.rs

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::io::{self, Write};
2-
use std::path::Path;
2+
use std::path::PathBuf;
33
use std::sync::atomic::{AtomicU32, Ordering};
44

55
use bytesize::ByteSize;
@@ -104,7 +104,7 @@ impl Default for Config {
104104
level: Default::default(),
105105
stdout: true,
106106
file: None,
107-
line_num: false,
107+
line_num: true,
108108
noh: false,
109109
chan_size: None,
110110
overflow: None,
@@ -222,8 +222,16 @@ fn new_logger(c: &Config) -> anyhow::Result<Option<Logger>> {
222222

223223
match &c.file {
224224
Some(fc) => {
225-
let path = Path::new(&fc.path);
226-
225+
// normalize path
226+
let path = match &fc.path.strip_prefix("~/") {
227+
Some(rel) => {
228+
let pb = PathBuf::from(rel);
229+
dirs::home_dir().unwrap_or_default().join(pb)
230+
}
231+
None => PathBuf::from(&fc.path),
232+
};
233+
234+
// ensure logger dir
227235
if let Some(dir) = path.parent() {
228236
std::fs::create_dir_all(dir)?;
229237
}

0 commit comments

Comments
 (0)