feat(admin): observability — job history, live now-analyzing, durations & metrics (0.84.0) (#6)
This commit was merged in pull request #6.
This commit is contained in:
43
backend/src/domain/crawl_metrics.rs
Normal file
43
backend/src/domain/crawl_metrics.rs
Normal file
@@ -0,0 +1,43 @@
|
||||
//! Timing metrics for crawler operations (see `crawl_metrics` table, 0028).
|
||||
//!
|
||||
//! One [`OpRow`] per completed operation (manga list walk, manga detail,
|
||||
//! cover, whole chapter); [`OpSummary`] is the per-type average roll-up that
|
||||
//! drives the admin Metrics tab. Per-page crawl timing is derived on the
|
||||
//! client from the `chapter` summary's `avg_items` (pages/chapter), not
|
||||
//! stored per image. Analysis duration lives on `page_analysis`, not here.
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::Serialize;
|
||||
use sqlx::FromRow;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Per-operation-type average roll-up over a time window.
|
||||
#[derive(Debug, Clone, Serialize, FromRow)]
|
||||
pub struct OpSummary {
|
||||
/// `manga_list` | `manga_detail` | `manga_cover` | `chapter`.
|
||||
pub op: String,
|
||||
/// Mean duration in milliseconds (`NULL`→absent only when `n = 0`).
|
||||
pub avg_ms: Option<f64>,
|
||||
/// Total operations in the window.
|
||||
pub n: i64,
|
||||
pub ok: i64,
|
||||
pub failed: i64,
|
||||
/// Mean `items` (pages/chapter, mangas/list-walk); `None` when unused.
|
||||
pub avg_items: Option<f64>,
|
||||
}
|
||||
|
||||
/// One timed operation, resolved to manga/chapter labels for the recent-ops log.
|
||||
#[derive(Debug, Clone, Serialize, FromRow)]
|
||||
pub struct OpRow {
|
||||
pub id: Uuid,
|
||||
pub op: String,
|
||||
pub manga_id: Option<Uuid>,
|
||||
pub manga_title: Option<String>,
|
||||
pub chapter_id: Option<Uuid>,
|
||||
pub chapter_number: Option<i32>,
|
||||
pub outcome: String,
|
||||
pub duration_ms: i64,
|
||||
pub items: Option<i32>,
|
||||
pub error: Option<String>,
|
||||
pub finished_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -4,6 +4,7 @@ pub mod author;
|
||||
pub mod bookmark;
|
||||
pub mod chapter;
|
||||
pub mod collection;
|
||||
pub mod crawl_metrics;
|
||||
pub mod genre;
|
||||
pub mod manga;
|
||||
pub mod page;
|
||||
@@ -25,6 +26,7 @@ pub use author::{Author, AuthorRef, AuthorWithCount};
|
||||
pub use bookmark::{Bookmark, BookmarkSummary};
|
||||
pub use chapter::Chapter;
|
||||
pub use collection::{Collection, CollectionPageItem, CollectionSummary};
|
||||
pub use crawl_metrics::{OpRow, OpSummary};
|
||||
pub use genre::{Genre, GenreRef};
|
||||
pub use manga::{Manga, MangaCard, MangaDetail};
|
||||
pub use page::Page;
|
||||
|
||||
@@ -157,6 +157,46 @@ pub struct PageStatusItem {
|
||||
pub status: String,
|
||||
}
|
||||
|
||||
/// One row in the admin analysis-history table: a completed or failed
|
||||
/// analysis pass resolved to its page/chapter/manga context. Sourced from
|
||||
/// the persistent `page_analysis` table (not the reaped job queue), so it
|
||||
/// survives indefinitely. `status` is `done` | `failed`.
|
||||
#[derive(Debug, Clone, Serialize, FromRow)]
|
||||
pub struct AnalysisHistoryRow {
|
||||
pub page_id: Uuid,
|
||||
pub page_number: i32,
|
||||
pub chapter_id: Uuid,
|
||||
pub chapter_number: i32,
|
||||
pub manga_id: Uuid,
|
||||
pub manga_title: String,
|
||||
pub status: String,
|
||||
pub is_nsfw: bool,
|
||||
pub model: Option<String>,
|
||||
pub error: Option<String>,
|
||||
pub analyzed_at: Option<DateTime<Utc>>,
|
||||
/// Wall-clock the worker spent on this page; `None` for rows analyzed
|
||||
/// before duration tracking landed.
|
||||
pub duration_ms: Option<i64>,
|
||||
}
|
||||
|
||||
/// Per-model average analysis duration (admin Metrics tab).
|
||||
#[derive(Debug, Clone, Serialize, FromRow)]
|
||||
pub struct ModelDuration {
|
||||
pub model: Option<String>,
|
||||
pub avg_ms: Option<f64>,
|
||||
pub n: i64,
|
||||
}
|
||||
|
||||
/// Aggregate analysis timing/outcome roll-up over a time window.
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
pub struct AnalysisMetrics {
|
||||
pub n: i64,
|
||||
pub ok: i64,
|
||||
pub failed: i64,
|
||||
pub avg_ms: Option<f64>,
|
||||
pub by_model: Vec<ModelDuration>,
|
||||
}
|
||||
|
||||
/// One OCR line in the page-detail view.
|
||||
#[derive(Debug, Clone, Serialize, FromRow)]
|
||||
pub struct OcrLine {
|
||||
|
||||
Reference in New Issue
Block a user