use pi_logger::ali_sls::{SLBatchConfig, SLSAppender};
use pi_logger::encode_sls::SLSEncoder;
use pi_logger::encode_json::JsonEncoder;
use pi_async_rt::rt::multi_thread::{MultiTaskRuntimeBuilder, StealableTaskPool};
use async_httpc::AsyncHttpcBuilder;
use log4rs::append::Append;
fn create_test_runtime() -> pi_async_rt::rt::multi_thread::MultiTaskRuntime<()> {
let len = 4;
let pool = StealableTaskPool::with(len, 1000000, [1, 1], 3000);
let builder = MultiTaskRuntimeBuilder::new(pool)
.thread_prefix("TEST")
.thread_stack_size(2 * 1024 * 1024)
.init_worker_size(len)
.set_worker_limit(len, len)
.set_timeout(10)
.set_timer_interval(1);
builder.build()
}
#[test]
fn test_batch_trigger_by_timeout() {
let rt = create_test_runtime();
let httpc = AsyncHttpcBuilder::new().build().unwrap();
let config = SLBatchConfig {
batch_bytes: 1024 * 100, timeout_secs: 5, max_retries: 3,
retry_delay_ms: 1000,
};
let url = "https://gcwl-logs.cn-chengdu.log.aliyuncs.com/logstores/logs_test/track".to_string();
let appender = SLSAppender::builder()
.encoder(Box::new(SLSEncoder::new()))
.source("test-project".to_string())
.batch_config(config)
.build(url, rt, httpc)
.expect("Failed to create SLS appender");
println!("Testing appender directly with 5 log messages...");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("test timeout message 1"))
.build()
).expect("Direct appender call failed");
println!("Sent message 1 via direct appender call");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("test timeout message 2"))
.build()
).expect("Direct appender call failed");
println!("Sent message 2 via direct appender call");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("test timeout message 3"))
.build()
).expect("Direct appender call failed");
println!("Sent message 3 via direct appender call");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("test timeout message 4"))
.build()
).expect("Direct appender call failed");
println!("Sent message 4 via direct appender call");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("test timeout message 5"))
.build()
).expect("Direct appender call failed");
println!("Sent message 5 via direct appender call");
println!("All messages sent, waiting for batch processing and timeout...");
std::thread::sleep(std::time::Duration::from_secs(7));
println!("Timeout trigger test passed! Check SLS console for logs.");
}
#[test]
fn test_json_encoder_with_sls_appender() {
let rt = create_test_runtime();
let httpc = AsyncHttpcBuilder::new().build().unwrap();
let config = SLBatchConfig {
batch_bytes: 1024 * 100, timeout_secs: 5, max_retries: 3,
retry_delay_ms: 1000,
};
let url = "https://gcwl-logs.cn-chengdu.log.aliyuncs.com/logstores/logs_test/track".to_string();
let appender = SLSAppender::builder()
.encoder(Box::new(JsonEncoder::new(None)))
.source("json-test".to_string())
.batch_config(config)
.build(url, rt, httpc)
.expect("Failed to create SLS appender with JsonEncoder");
println!("Testing JsonEncoder with SLSAppender...");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("JsonEncoder test message 1"))
.target("test::module")
.module_path(Some("test::module"))
.file(Some("test.rs"))
.line(Some(10))
.build()
).expect("Failed to append log 1");
println!("Sent message 1 via JsonEncoder");
appender.append(
&log::Record::builder()
.level(log::Level::Debug)
.args(format_args!("JsonEncoder test message 2"))
.target("test::module")
.module_path(Some("test::module"))
.file(Some("test.rs"))
.line(Some(11))
.build()
).expect("Failed to append log 2");
println!("Sent message 2 via JsonEncoder");
appender.append(
&log::Record::builder()
.level(log::Level::Warn)
.args(format_args!("JsonEncoder test message 3"))
.target("test::module")
.module_path(Some("test::module"))
.file(Some("test.rs"))
.line(Some(12))
.build()
).expect("Failed to append log 3");
println!("Sent message 3 via JsonEncoder");
appender.append(
&log::Record::builder()
.level(log::Level::Error)
.args(format_args!("JsonEncoder test message 4"))
.target("test::module")
.module_path(Some("test::module"))
.file(Some("test.rs"))
.line(Some(13))
.build()
).expect("Failed to append log 4");
println!("Sent message 4 via JsonEncoder");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("JsonEncoder test message 5"))
.target("test::module")
.module_path(Some("test::module"))
.file(Some("test.rs"))
.line(Some(14))
.build()
).expect("Failed to append log 5");
println!("Sent message 5 via JsonEncoder");
println!("All JsonEncoder messages sent, waiting for batch processing...");
std::thread::sleep(std::time::Duration::from_secs(7));
println!("JsonEncoder with SLSAppender test passed! Check SLS console for JSON formatted logs.");
}
#[test]
fn test_sls_encoder_with_logs_array() {
let rt = create_test_runtime();
let httpc = AsyncHttpcBuilder::new().build().unwrap();
let config = SLBatchConfig {
batch_bytes: 1024 * 100,
timeout_secs: 5,
max_retries: 3,
retry_delay_ms: 1000,
};
let url = "https://gcwl-logs.cn-chengdu.log.aliyuncs.com/logstores/logs_test/track".to_string();
let appender = SLSAppender::builder()
.encoder(Box::new(SLSEncoder::new()))
.source("sls-logs-array-test".to_string())
.batch_config(config)
.build(url, rt, httpc)
.expect("Failed to create SLS appender with SLSEncoder");
println!("Testing SLSEncoder with __logs__ array...");
let logs_with_array = r#"{"__logs__":[{"bievent":"gisum","project":"yszz_local_test","time":"1768961943","uid":"100009186","g_k":"grow/创造次数","g_v":"627"},{"bievent":"levelup","project":"yszz_local_test","time":"1768961944","uid":"100009186","level":"5"}]}"#;
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("{}", logs_with_array))
.build()
).expect("Failed to append logs with __logs__ array");
println!("Sent __logs__ array with 2 entries");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("Normal message without __logs__"))
.build()
).expect("Failed to append normal message");
println!("Sent normal message");
std::thread::sleep(std::time::Duration::from_secs(7));
println!("SLSEncoder with __logs__ array test passed! Check SLS console for logs.");
}
#[test]
fn test_sls_encoder_json_formats() {
let rt = create_test_runtime();
let httpc = AsyncHttpcBuilder::new().build().unwrap();
let config = SLBatchConfig {
batch_bytes: 1024 * 100,
timeout_secs: 5,
max_retries: 3,
retry_delay_ms: 1000,
};
let url = "https://gcwl-logs.cn-chengdu.log.aliyuncs.com/logstores/logs_test/track".to_string();
let appender = SLSAppender::builder()
.encoder(Box::new(SLSEncoder::new()))
.source("sls-json-formats-test".to_string())
.batch_config(config)
.build(url, rt, httpc)
.expect("Failed to create SLS appender");
println!("Testing SLSEncoder with various JSON formats...");
let logs_with_array = r#"{"__logs__":[{"event":"test1"},{"event":"test2"}]}"#;
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("{}", logs_with_array))
.build()
).expect("Failed to append __logs__ array");
println!("Test 1: __logs__ array - sent 2 entries");
let json_without_logs = r#"{"action":"click","page":"home","userId":"12345"}"#;
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("{}", json_without_logs))
.build()
).expect("Failed to append JSON without __logs__");
println!("Test 2: JSON without __logs__ - sent directly");
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("This is a plain text message"))
.build()
).expect("Failed to append plain text");
println!("Test 3: Plain text - wrapped in message field");
let complex_json = r#"{"timestamp":"1768961943","level":"INFO","service":"api","data":{"count":42,"status":"active"}}"#;
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("{}", complex_json))
.build()
).expect("Failed to append complex JSON");
println!("Test 4: Complex JSON - sent directly");
let empty_logs_array = r#"{"__logs__":[]}"#;
appender.append(
&log::Record::builder()
.level(log::Level::Info)
.args(format_args!("{}", empty_logs_array))
.build()
).expect("Failed to append empty __logs__ array");
println!("Test 5: Empty __logs__ array - sent");
std::thread::sleep(std::time::Duration::from_secs(7));
println!("SLSEncoder JSON formats test passed! Check SLS console for all formats.");
}