fix: refactor logging events to use owned asset instances and simplify log event structures
This commit is contained in:
22
src/api.rs
22
src/api.rs
@@ -6,7 +6,7 @@ use serde_json::json;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data_mgt::AssetTracker,
|
data_mgt::AssetTracker,
|
||||||
logs::{LogEventBody, LogEventLine, LogEventType, log_event},
|
logs::{ LogEvent, LogEventType, log_event},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@@ -45,7 +45,7 @@ async fn api_upload(
|
|||||||
Some(uploader_ip.clone()),
|
Some(uploader_ip.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
log_event(LogEventType::AssetUploaded(&asset));
|
log_event(LogEventType::AssetUploaded(asset.clone()));
|
||||||
let id = asset.id();
|
let id = asset.id();
|
||||||
assets.add_asset(asset).await;
|
assets.add_asset(asset).await;
|
||||||
let response_body = json!({ "link": format!("/bhs/{}", id) });
|
let response_body = json!({ "link": format!("/bhs/{}", id) });
|
||||||
@@ -58,7 +58,7 @@ async fn api_get_asset(
|
|||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
assets: web::Data<AssetTracker>,
|
assets: web::Data<AssetTracker>,
|
||||||
) -> Result<HttpResponse, actix_web::Error> {
|
) -> Result<HttpResponse, actix_web::Error> {
|
||||||
log_event(LogEventType::HttpRequest(&req.into()));
|
log_event(LogEventType::HttpRequest(req.into()));
|
||||||
|
|
||||||
match assets.get_asset(&path.into_inner()).await {
|
match assets.get_asset(&path.into_inner()).await {
|
||||||
None => Ok(HttpResponse::NotFound().body("Asset not found")),
|
None => Ok(HttpResponse::NotFound().body("Asset not found")),
|
||||||
@@ -104,26 +104,26 @@ async fn api_stats(assets: web::Data<AssetTracker>) -> Result<HttpResponse, acti
|
|||||||
let log_path = format!("{}access.log", LOG_DIR);
|
let log_path = format!("{}access.log", LOG_DIR);
|
||||||
if let Ok(content) = fs::read_to_string(&log_path) {
|
if let Ok(content) = fs::read_to_string(&log_path) {
|
||||||
for line in content.lines() {
|
for line in content.lines() {
|
||||||
if let Ok(entry) = serde_json::from_str::<LogEventLine>(line) {
|
if let Ok(entry) = serde_json::from_str::<LogEvent>(line) {
|
||||||
match entry.event {
|
match entry.event {
|
||||||
LogEventBody::HttpRequest(_req) => {
|
LogEventType::HttpRequest(_req) => {
|
||||||
request_count += 1;
|
request_count += 1;
|
||||||
}
|
}
|
||||||
LogEventBody::AssetUploaded(asset) => {
|
LogEventType::AssetUploaded(asset) => {
|
||||||
total_uploads += 1;
|
total_uploads += 1;
|
||||||
recent_activity.push(ActivityItem {
|
recent_activity.push(ActivityItem {
|
||||||
action: "upload".to_string(),
|
action: "upload".to_string(),
|
||||||
mime: asset.mime,
|
mime: asset.mime(),
|
||||||
share_duration: asset.share_duration,
|
share_duration: asset.share_duration(),
|
||||||
timestamp: entry.time,
|
timestamp: entry.time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
LogEventBody::AssetDeleted(asset) => {
|
LogEventType::AssetDeleted(asset) => {
|
||||||
total_deleted += 1;
|
total_deleted += 1;
|
||||||
recent_activity.push(ActivityItem {
|
recent_activity.push(ActivityItem {
|
||||||
action: "delete".to_string(),
|
action: "delete".to_string(),
|
||||||
mime: asset.mime,
|
mime: asset.mime(),
|
||||||
share_duration: asset.share_duration,
|
share_duration: asset.share_duration(),
|
||||||
timestamp: entry.time,
|
timestamp: entry.time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ use anyhow::Result;
|
|||||||
use chrono::{Duration, Utc};
|
use chrono::{Duration, Utc};
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::DATA_STORAGE;
|
use crate::DATA_STORAGE;
|
||||||
use crate::logs::{LogEventType, log_event};
|
use crate::logs::{LogEventType, log_event};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Default, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Asset {
|
pub struct Asset {
|
||||||
id: String,
|
id: String,
|
||||||
share_duration: u32,
|
share_duration: u32,
|
||||||
@@ -45,8 +46,8 @@ impl Asset {
|
|||||||
self.id.clone()
|
self.id.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mime(&self) -> &str {
|
pub fn mime(&self) -> String {
|
||||||
&self.mime
|
self.mime.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn content(&self) -> Vec<u8> {
|
pub fn content(&self) -> Vec<u8> {
|
||||||
@@ -65,6 +66,10 @@ impl Asset {
|
|||||||
self.expires_at
|
self.expires_at
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn mime_type(&self) -> &str {
|
||||||
|
&self.mime
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size_bytes(&self) -> usize {
|
pub fn size_bytes(&self) -> usize {
|
||||||
self.content.len()
|
self.content.len()
|
||||||
}
|
}
|
||||||
@@ -85,8 +90,16 @@ impl Asset {
|
|||||||
std::fs::write(&path, self.to_bytes()?)?;
|
std::fs::write(&path, self.to_bytes()?)?;
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Asset> for Value {
|
||||||
|
fn from(asset: Asset) -> Self {
|
||||||
|
serde_json::to_value(asset).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AssetTracker {
|
pub struct AssetTracker {
|
||||||
assets: Arc<Mutex<Vec<Asset>>>,
|
assets: Arc<Mutex<Vec<Asset>>>,
|
||||||
@@ -110,8 +123,8 @@ impl AssetTracker {
|
|||||||
let mut assets = self.assets.lock().await;
|
let mut assets = self.assets.lock().await;
|
||||||
let removed_assets = assets.extract_if(.., |asset| asset.is_expired());
|
let removed_assets = assets.extract_if(.., |asset| asset.is_expired());
|
||||||
for asset in removed_assets {
|
for asset in removed_assets {
|
||||||
log_event(LogEventType::AssetDeleted(&asset));
|
|
||||||
println!("[{}] Removing asset: {}", chrono::Local::now().to_rfc3339(), asset.id());
|
println!("[{}] Removing asset: {}", chrono::Local::now().to_rfc3339(), asset.id());
|
||||||
|
log_event(LogEventType::AssetDeleted(asset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
45
src/logs.rs
45
src/logs.rs
@@ -6,31 +6,6 @@ use serde::{Deserialize, Serialize};
|
|||||||
use crate::{LOG_DIR, data_mgt::Asset};
|
use crate::{LOG_DIR, data_mgt::Asset};
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct LogEventLine {
|
|
||||||
pub time: String,
|
|
||||||
pub event: LogEventBody,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub enum LogEventBody {
|
|
||||||
AssetUploaded(LogAsset),
|
|
||||||
AssetDeleted(LogAsset),
|
|
||||||
HttpRequest(LogHttpRequest),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct LogAsset {
|
|
||||||
pub id: String,
|
|
||||||
pub share_duration: u32,
|
|
||||||
pub created_at: i64,
|
|
||||||
pub expires_at: i64,
|
|
||||||
pub mime: String,
|
|
||||||
pub uploader_ip: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LogHttpRequest {
|
pub struct LogHttpRequest {
|
||||||
pub method: String,
|
pub method: String,
|
||||||
@@ -72,21 +47,21 @@ impl From<HttpRequest> for LogHttpRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub enum LogEventType<'a> {
|
pub enum LogEventType {
|
||||||
AssetUploaded(&'a Asset),
|
AssetUploaded(Asset),
|
||||||
AssetDeleted(&'a Asset),
|
AssetDeleted(Asset),
|
||||||
HttpRequest(&'a LogHttpRequest),
|
HttpRequest(LogHttpRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct LogEvent<'a> {
|
pub struct LogEvent {
|
||||||
pub time: String,
|
pub time: String,
|
||||||
pub event: LogEventType<'a>,
|
pub event: LogEventType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<LogEventType<'a>> for LogEvent<'a> {
|
impl From<LogEventType> for LogEvent {
|
||||||
fn from(event: LogEventType<'a>) -> Self {
|
fn from(event: LogEventType) -> Self {
|
||||||
let time = chrono::Utc::now().to_rfc3339();
|
let time = chrono::Utc::now().to_rfc3339();
|
||||||
LogEvent { time, event }
|
LogEvent { time, event }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,21 +51,21 @@ use crate::{
|
|||||||
#[get("/")]
|
#[get("/")]
|
||||||
async fn index(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
async fn index(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
||||||
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "index.html");
|
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "index.html");
|
||||||
log_event(LogEventType::HttpRequest(&req.into()));
|
log_event(LogEventType::HttpRequest(req.into()));
|
||||||
Ok(NamedFile::open(path)?)
|
Ok(NamedFile::open(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/stats")]
|
#[get("/stats")]
|
||||||
async fn stats(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
async fn stats(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
||||||
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "stats.html");
|
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "stats.html");
|
||||||
log_event(LogEventType::HttpRequest(&req.into()));
|
log_event(LogEventType::HttpRequest(req.into()));
|
||||||
Ok(NamedFile::open(path)?)
|
Ok(NamedFile::open(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/bhs/{id}")]
|
#[get("/bhs/{id}")]
|
||||||
async fn view_asset(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
async fn view_asset(req: HttpRequest) -> actix_web::Result<NamedFile> {
|
||||||
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "view.html");
|
let path: PathBuf = PathBuf::from(HTML_DIR.to_string() + "view.html");
|
||||||
log_event(LogEventType::HttpRequest(&req.into()));
|
log_event(LogEventType::HttpRequest(req.into()));
|
||||||
Ok(NamedFile::open(path)?)
|
Ok(NamedFile::open(path)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ async fn catch_all(req: HttpRequest, _payload: Option<web::Json<Value>>) -> acti
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
log_event(LogEventType::HttpRequest(&req.into()));
|
log_event(LogEventType::HttpRequest(req.into()));
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user