feat: 添加日志功能

This commit is contained in:
zhushenwudi 2025-01-06 23:13:20 +08:00
parent 5a0f888000
commit ee2e8dd1c6
11 changed files with 125 additions and 52 deletions

View File

@ -31,3 +31,5 @@ serde = { version = "1.0.215", features = ["derive"] }
futures = "0.3.31"
mime_guess = "2.0.5"
actix-files = "0.6.6"
simplelog = "0.12.2"
log = "0.4.22"

67
src/logger.rs Normal file
View File

@ -0,0 +1,67 @@
use log::{debug, error, info, warn, LevelFilter};
use simplelog::*;
use std::fs::{create_dir_all, File, OpenOptions};
use std::path::Path;
const MAX_LOG_SIZE: u64 = 50 * 1024 * 1024;
const LOG_FILE_PATH: &str = "data/rust.log";
pub fn init_logger() {
let mut builder = ConfigBuilder::new();
builder.set_time_offset_to_local().unwrap();
let config = builder.build();
// 获取文件的目录路径
let dir = Path::new(LOG_FILE_PATH).parent().unwrap();
// 检查并创建目录
if !dir.exists() {
create_dir_all(dir).unwrap();
}
let file = OpenOptions::new()
.write(true)
.append(true)
.create(true)
.open(LOG_FILE_PATH).unwrap();
CombinedLogger::init(
vec![
TermLogger::new(LevelFilter::Info, config.clone(), TerminalMode::Mixed, ColorChoice::Auto),
WriteLogger::new(LevelFilter::Info, config.clone(), file),
]
).unwrap();
}
// 检查文件大小并清空文件(如果超出限制)
fn check_and_clear_log_file() {
let metadata = std::fs::metadata(LOG_FILE_PATH).unwrap();
if metadata.len() > MAX_LOG_SIZE {
// 清空文件
File::create(LOG_FILE_PATH).expect(&format!("Can't re-create file {}", LOG_FILE_PATH));
}
}
#[allow(dead_code)]
pub fn debug(message: &str) {
check_and_clear_log_file();
debug!("{}", message);
}
#[allow(dead_code)]
pub fn info(message: &str) {
check_and_clear_log_file();
info!("{}", message);
}
#[allow(dead_code)]
pub fn warn(message: &str) {
check_and_clear_log_file();
warn!("{}", message);
}
#[allow(dead_code)]
pub fn error(message: &str) {
check_and_clear_log_file();
error!("{}", message);
}

View File

@ -1,6 +1,7 @@
mod encryption;
mod router;
mod sql;
mod logger;
use actix_web::{
rt,
@ -42,7 +43,7 @@ pub struct Args {
#[arg(short, long, default_value_t = 8000, help = "Assets port to listen on")]
asset_port: u16,
#[arg(long, default_value = "./", help = "Path to store database files")]
#[arg(long, default_value = "./data/", help = "Path to store database files")]
path: String,
#[arg(long, default_value = "./asset/", help = "Path to store database files")]
@ -110,43 +111,45 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> {
let asset_port = args.asset_port;
if args.purge {
println!("Purging accounts...");
let ct = crate::router::userdata::purge_accounts();
println!("Purged {} accounts", ct);
logger::debug("Purging accounts...");
let ct = router::userdata::purge_accounts();
logger::warn(&format!("Purged {} accounts", ct));
}
let webui_server = HttpServer::new(|| App::new()
let webui_server = HttpServer::new(|| {
App::new()
.wrap_fn(|req, srv| {
println!("WebUI Request: {}", req.path());
logger::info(&format!("WebUI Request: {}", req.path())); // 使用日志记录
srv.call(req)
})
.app_data(web::PayloadConfig::default().limit(1024 * 1024 * 25))
.service(css)
.service(js)
.default_service(web::route().to(router::request))
).bind(("0.0.0.0", port))?.run();
}).bind(("0.0.0.0", port))?.run();
println!("WebUI Server started: http://0.0.0.0:{}", port);
println!("Database path is set to {}", args.path);
println!("Sif1 transfer requests will attempt to contact NPPS4 at {}", args.npps4);
logger::info(&format!("WebUI Server started: http://0.0.0.0:{}", port));
logger::info(&format!("Database path is set to {}", args.path));
logger::debug(&format!("Sif1 transfer requests will attempt to contact NPPS4 at {}", args.npps4));
let mut asset_server: Option<Server> = None;
if enable_asset_server {
asset_server = Some(HttpServer::new(|| App::new()
asset_server = Some(HttpServer::new(|| {
App::new()
.wrap_fn(|req, srv| {
println!("Assets Request: {}", req.path());
logger::info(&format!("Assets Request: {}", req.path()));
srv.call(req)
})
.app_data(web::PayloadConfig::default().limit(1024 * 1024 * 1024))
.default_service(web::route().to(router::asset_request))
).bind(("0.0.0.0", asset_port))?.run());
}).bind(("0.0.0.0", asset_port))?.run());
println!("Assets Server started: http://0.0.0.0:{}", asset_port);
println!("Assets path is set to {}", args.asset_path);
logger::info(&format!("Assets Server started: http://0.0.0.0:{}", asset_port));
logger::info(&format!("Assets path is set to {}", args.asset_path));
}
if args.https {
println!("Note: gree is set to https mode. http requests will fail on jp clients.");
logger::warn("Note: gree is set to https mode. http requests will fail on jp clients.");
}
if in_thread {
@ -161,13 +164,13 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> {
}
while get_running().await {
actix_web::rt::time::sleep(Duration::from_millis(100)).await;
rt::time::sleep(Duration::from_millis(100)).await;
}
handle.stop(false).await;
if handle2.is_some() {
handle2.unwrap().stop(false).await;
}
println!("Stopped");
logger::info("Stopped");
return Ok(());
}
if asset_server.is_some() {
@ -181,10 +184,11 @@ async fn run_server(in_thread: bool) -> std::io::Result<()> {
#[actix_web::main]
async fn stop_server() {
set_running(false).await;
println!("Stopping");
logger::error("Stopping");
}
fn main() -> std::io::Result<()> {
logger::init_logger();
run_server(false)
}

View File

@ -30,13 +30,13 @@ pub mod event_ranking;
use actix_web::{HttpResponse, HttpRequest, http::header::HeaderValue, http::header::HeaderMap, Responder};
use json::{JsonValue, object};
use crate::encryption;
use crate::{encryption, logger};
fn unhandled(req: HttpRequest, body: String) -> Option<JsonValue> {
if body != String::new() {
println!("{}", encryption::decrypt_packet(&body).unwrap_or(body));
logger::error(&format!("{}", encryption::decrypt_packet(&body).unwrap_or(body)));
}
println!("Unhandled request: {}", req.path());
logger::error(&format!("Unhandled request: {}", req.path()));
None
}

View File

@ -2,7 +2,7 @@ use json::{object, array, JsonValue};
use actix_web::{HttpRequest};
use crate::router::{global, items, userdata, databases};
use crate::encryption;
use crate::{encryption, logger};
pub fn add_chat(id: i64, num: i64, chats: &mut JsonValue) -> bool {
for data in chats.members() {
@ -23,7 +23,7 @@ pub fn add_chat(id: i64, num: i64, chats: &mut JsonValue) -> bool {
pub fn add_chat_from_chapter_id(chapter_id: i64, chats: &mut JsonValue) -> bool {
let chapter = &databases::CHAPTERS_MASTER[chapter_id.to_string()];
if chapter.is_empty() {
println!("Attempted to give unknown chapter id {}", chapter_id);
logger::info(&format!("Attempted to give unknown chapter id {}", chapter_id));
return false;
}
add_chat(chapter["masterChatId"].as_i64().unwrap(), chapter["roomId"].as_i64().unwrap(), chats)

View File

@ -1,12 +1,12 @@
use json::{JsonValue, object};
use actix_web::{HttpRequest};
use crate::encryption;
use crate::{encryption, logger};
pub fn error(_req: HttpRequest, body: String) -> Option<JsonValue> {
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
println!("client error: {}", body["code"]);
logger::error(&format!("client error: {}", body["code"]));
Some(object!{})
}

View File

@ -1,7 +1,7 @@
use json::{array, object, JsonValue};
use rand::Rng;
use actix_web::{HttpRequest, http::header::{HeaderMap, HeaderValue}};
use crate::encryption;
use crate::{encryption, logger};
use crate::router::{userdata, global, databases};
@ -113,7 +113,7 @@ pub fn use_item(item: &JsonValue, multiplier: i64, user: &mut JsonValue) {
} else if item["consumeType"] == 4 {
use_itemm(item["value"].as_i64().unwrap(), item["amount"].as_i64().unwrap() * multiplier, user);
} else {
println!("Unknown consume type {}", item["consumeType"]);
logger::error(&format!("Unknown consume type {}", item["consumeType"]));
}
}
@ -142,7 +142,7 @@ pub fn give_gift(data: &JsonValue, user: &mut JsonValue, missions: &mut JsonValu
}
return false;
}
println!("Redeeming reward not implemented for reward type {}", data["reward_type"]);
logger::error(&format!("Redeeming reward not implemented for reward type {}", data["reward_type"]));
false
}
pub fn give_gift_basic(ty_pe: i32, id: i64, amount: i64, user: &mut JsonValue, missions: &mut JsonValue, clear_missions: &mut JsonValue, chats: &mut JsonValue) -> bool {
@ -279,7 +279,7 @@ pub fn get_rarity(id: i64) -> i32 {
pub fn give_character(id: i64, user: &mut JsonValue, missions: &mut JsonValue, clear_missions: &mut JsonValue, chats: &mut JsonValue) -> bool {
let character_rarity = get_rarity(id);
if character_rarity == 0 {
println!("Attempted to give user undefined card!! Card id: {}", id);
logger::error(&format!("Attempted to give user undefined card!! Card id: {}", id));
return false;
}
@ -498,7 +498,7 @@ pub fn use_item_req(req: HttpRequest, body: String) -> Option<JsonValue> {
if item["effectType"].as_i32().unwrap() == 1 {
lp_modification(&mut user, item["effectValue"].as_u64().unwrap() * (amount as u64), false);
} else {
println!("Use item not implemented for effect type {}", item["effectType"]);
logger::error(&format!("Use item not implemented for effect type {}", item["effectType"]));
}
use_item(&object!{
value: body["id"].as_i64().unwrap(),

View File

@ -1,12 +1,12 @@
use json::{JsonValue, object};
use actix_web::{HttpRequest, http::header::HeaderValue};
use crate::encryption;
use crate::{encryption, logger};
use crate::router::{userdata, global};
fn get_asset_hash(req: &HttpRequest, body: &JsonValue) -> String {
if body["asset_version"] != global::ASSET_VERSION && body["asset_version"] != global::ASSET_VERSION_JP {
println!("Warning! Asset version is not what was expected. (Did the app update?)");
logger::warn("Warning! Asset version is not what was expected. (Did the app update?)");
}
let blank_header = HeaderValue::from_static("");
@ -29,7 +29,7 @@ pub fn start(req: HttpRequest, body: String) -> Option<JsonValue> {
let body = json::parse(&encryption::decrypt_packet(&body).unwrap()).unwrap();
let mut user = userdata::get_acc(&key);
println!("Signin from uid: {}", user["user"]["id"].clone());
logger::info(&format!("Signin from uid: {}", user["user"]["id"].clone()));
user["user"]["last_login_time"] = global::timestamp().into();

View File

@ -2,7 +2,7 @@ use json::{array, object, JsonValue};
use actix_web::{HttpRequest};
use sha1::{Sha1, Digest};
use crate::encryption;
use crate::{encryption, logger};
use crate::router::{userdata, global, items};
use crate::include_file;
@ -329,7 +329,7 @@ async fn npps4_req(sha_id: String) -> Option<JsonValue> {
host.pop();
}
let url = format!("{}/ewexport?sha1={}", host, sha_id);
println!("Polling NPPS4 at {}", host);
logger::debug(&format!("Polling NPPS4 at {}", host));
let client = reqwest::Client::new();
let response = client.get(url);

View File

@ -8,7 +8,7 @@ use base64::{Engine as _, engine::general_purpose};
use crate::router::global;
use crate::router::items;
use crate::sql::SQLite;
use crate::include_file;
use crate::{include_file, logger};
lazy_static! {
static ref DATABASE: SQLite = SQLite::new("userdata.db", setup_tables);
@ -625,7 +625,7 @@ pub fn purge_accounts() -> usize {
)).unwrap();
for uid in dead_uids.members() {
let user_id = uid.as_i64().unwrap();
println!("Removing dead UID: {}", user_id);
logger::error(&format!("Removing dead UID: {}", user_id));
crate::router::gree::delete_uuid(user_id);
DATABASE.lock_and_exec("DELETE FROM userdata WHERE user_id=?1", params!(user_id));
DATABASE.lock_and_exec("DELETE FROM userhome WHERE user_id=?1", params!(user_id));

View File

@ -1,4 +1,4 @@
import { useState, useParams, useEffect } from 'react'
import { useState, useEffect } from 'react'
import './Home.css'
import Request from '../Request.jsx'
let bonusItems = [];