Metadata-Version: 2.4
Name: snakemake-logger-plugin-rich-loguru
Version: 0.2.1
Summary: A Snakemake logger plugin using Loguru and Rich for beautiful console and file logging.
License-File: LICENSE
Author: ZHANGJIAN
Author-email: zhangjian199567@outlook.com
Requires-Python: >=3.11,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: cryptography (>=42.0.0,<43.0.0)
Requires-Dist: loguru (>=0.7.0,<0.8.0)
Requires-Dist: pyfiglet (>=1.0.2,<2.0.0)
Requires-Dist: pyyaml (>=6.0.3,<7.0.0)
Requires-Dist: rich (>=13.0.0,<14.0.0)
Requires-Dist: snakemake-interface-logger-plugins (>=1.0.0)
Description-Content-Type: text/markdown

# Snakemake Logger 增强插件：Rich-Loguru

这是一个基于 Loguru 和 Rich 开发的 Snakemake 日志插件，旨在为生物信息学流程提供极度舒适的终端输出、结构化的本地记录，以及基于 **Grafana Loki** 和 **OmicHub** 的远程可视化监控。

## 🌟 核心特性

- **华丽的终端输出**：利用 Rich 库优化 Snakemake 运行状态，支持进度条展示和规则高亮。
- **沉浸式启动体验**：内置系统自检风格的启动过场动画与状态面板（默认关闭，设置环境变量 `SNAKEMAKE_RICH_LOGURU_SPLASH=1` 启用），提供专业的 CLI 交互感。
- **结构化本地日志**：Loguru 驱动，支持自动滚动、多级别记录（JSON 或文本）。
- **Grafana Loki 远程监控深度整合**：
    - 将流程日志实时以结构化 JSON 格式推送到 Loki 服务器。
    - **智能日志清洗**：自动去除终端的高亮颜色代码（Rich Markup），确保 Loki 中展示纯净文本。
    - **自动结构化解析**：自动从日志中提取 `Snakemake_Rule` (规则名)、`Snakemake_JobId` (任务ID)、`Event_Type` (事件类型) 和 `Shell_Command` 等字段，便于精确查询。
    - **鲁棒的进度监控**：
        - 支持自动解析 Snakemake 任务统计表（Job stats）以获取总任务数，即使日志存在缩进或分块也能准确识别。
        - 实时追踪任务完成事件（`Finished jobid`），支持多种 Snakemake 输出格式。
        - **透明化进度详情**：每个日志包中包含 `progress_percent`（百分比）和 `progress_details`（如 `5/149`），方便在监控面板中实时查看具体的任务完成情况。
    - **Dry-run 智能保护**：自动识别 Snakemake 的 `-n/--dry-run` 模式。在测试运行期间自动禁用 Loki 推送，防止测试数据污染远程监控面板，并减少无效的网络开销。
    - **项目隔离**：日志消息自动添加 `ProjectName |` 前缀，标签中包含 `project` 字段，轻松区分不同项目。
    - **异步非阻塞推送**：Loki 日志发送采用后台线程 + 5 秒超时机制，即使服务端不可达也不会阻塞 Snakemake 主流程。
    - **多实例状态隔离**：每个 Snakemake 流程拥有独立的进度追踪状态，彻底解决多项目并行运行时的进度串扰问题。
- **OmicHub 原生监控集成**：
    - 推送结构化原生事件 `omichub.workflow_event.v1`，包含 `task_id`、`flow_id`、`user_id`、`progress_percent` 等业务字段。
    - 支持 Bearer Token 鉴权、HMAC-SHA256 签名、AES-256-GCM payload 加密。
    - 支持有界队列、重试/退避、退出 flush，服务端不可达时不阻塞主流程。
- **多平台推送告警**：新增对 **钉钉 (DingTalk)** 和 **飞书 (Feishu)** Webhook 的支持。在流程顺利完成或发生致命错误时，自动向您的即时通讯软件发送图文告警。
- **高性能异步架构**：Loki 推送机制升级为 **生产者-消费者模型 (Queue + Worker Thread)**，有效处理高频日志，防止在高并发任务下产生大量瞬时线程，极大提升系统稳定性。

## 🚀 安装指南

```bash
pip install snakemake-logger-plugin-rich-loguru
```

（请根据实际包名调整安装命令，如果是本地开发，请使用 `pip install -e .`）

## 📢 即时通讯告警配置 (IM Webhooks)

插件支持在工作流结束（成功或失败）时发送即时通讯通知。

### 配置参数

| 参数名 | 环境变量 | 描述 |
| :--- | :--- | :--- |
| `notification_url` | `SNAKEMAKE_NOTIFICATION_URL` | Webhook 地址 |
| `notification_platform` | `SNAKEMAKE_NOTIFICATION_PLATFORM` | 平台类型 (`dingtalk` 或 `feishu`) |

### 使用方式

您可以通过环境变量快速启用：

```bash
export SNAKEMAKE_NOTIFICATION_URL="https://oapi.dingtalk.com/robot/send?access_token=..."
export SNAKEMAKE_NOTIFICATION_PLATFORM="dingtalk"
snakemake --logger rich-loguru ...
```

或在 `monitor_config.yaml` 中配置：

```yaml
loki_url: "http://loki:3100/loki/api/v1/push"
project_name: "RNA-Seq_Analysis"
notification_url: "https://open.feishu.cn/open-apis/bot/v2/hook/..."
notification_platform: "feishu"
```

## 📊 远程监控配置 (Loki)

该插件支持通过多种方式加载配置，优先级如下：

1.  **命令行指定的 Analysis 配置** (`--config analysisyaml=...`)
2.  **Snakemake 配置文件** (`config.yaml` 或 `--config` 参数)
3.  **环境变量** (`SNAKEMAKE_MONITOR_CONF`)
4.  **独立配置文件** (`monitor_config.yaml`，默认查找当前目录)

### 配置参数

| 参数名 | 描述 | 示例 |
| :--- | :--- | :--- |
| `loki_url` | Loki 推送 API 地址 | `http://192.168.1.100:3100/loki/api/v1/push` |
| `project_name` | 项目名称 (作为标签和消息前缀) | `GenomicsPipeline` |

### 方式一：通过 Analysis Config 文件（新增，推荐用于动态场景）

如果您的流程通过 `--config analysisyaml=path/to/analysis.yaml` 指定了额外的分析配置文件，插件会自动读取该文件中的 `loki_url` 和 `project_name`。

**命令示例：**
```bash
snakemake --logger rich-loguru --config analysisyaml=/data/project/config.yaml ...
```

**配置文件内容 (`/data/project/config.yaml`)：**
```yaml
# 其他分析参数...
input_dir: "/data/raw"

# 监控配置
loki_url: "http://loki-server:3100/loki/api/v1/push"
project_name: "Batch_20260130"
```

### 方式二：集成到 Snakemake 主配置

直接在您的 `config.yaml` 中添加监控配置：

```yaml
# config.yaml
samples: "samples.tsv"

# === 监控配置 ===
loki_url: "http://192.168.1.100:3100/loki/api/v1/push"
project_name: "My_Analysis_Project"
```

在运行 Snakemake 时，确保显式加载插件：

```bash
snakemake --logger rich-loguru --configfile config.yaml ...
```

### 方式二：使用独立配置文件 (monitor_config.yaml)

在工作流根目录下创建 `monitor_config.yaml`：

```yaml
loki_url: "http://localhost:3100/loki/api/v1/push"
project_name: "Debug_Run"
```

插件会在启动时自动检测并加载该文件。

## 📡 OmicHub 平台监控

从 **v0.2.0** 开始，插件新增对 **OmicHub** 平台的原生工作流监控推送能力，同时保留原有 Loki/Grafana 兼容能力。OmicHub 模式相比 Loki 兼容模式具有以下优势：

- 原生事件结构（`omichub.workflow_event.v1`），便于平台直接解析任务状态。
- 支持 `task_id` / `flow_id` / `user_id` 等业务字段，实现精准的任务归属与权限校验。
- 支持 Bearer Token 鉴权、HMAC-SHA256 签名、AES-256-GCM payload 加密。

### 配置参数

| 参数名 | 环境变量 | 描述 |
| :--- | :--- | :--- |
| `omichub_monitor_url` | `SNAKEMAKE_OMICHUB_MONITOR_URL` | OmicHub 原生事件接收端点 |
| `omichub_monitor_token` | `SNAKEMAKE_OMICHUB_MONITOR_TOKEN` | Bearer Token 鉴权凭据 |
| `omichub_task_id` | `SNAKEMAKE_OMICHUB_TASK_ID` | 任务 ID（建议等于 `project_name`） |
| `omichub_flow_id` | `SNAKEMAKE_OMICHUB_FLOW_ID` | 流程 ID，如 `rna_seq`、`atac_seq` |
| `omichub_user_id` | `SNAKEMAKE_OMICHUB_USER_ID` | 任务归属用户 ID |
| `omichub_monitor_sign_requests` | `SNAKEMAKE_OMICHUB_MONITOR_SIGN_REQUESTS` | 是否启用 HMAC 签名（默认 `false`） |
| `omichub_monitor_signing_key` | `SNAKEMAKE_OMICHUB_MONITOR_SIGNING_KEY` | HMAC 签名密钥 |
| `omichub_monitor_encrypt_payload` | `SNAKEMAKE_OMICHUB_MONITOR_ENCRYPT_PAYLOAD` | 是否启用 AES-256-GCM 加密（默认 `false`） |
| `omichub_monitor_encryption_key` | `SNAKEMAKE_OMICHUB_MONITOR_ENCRYPTION_KEY` | Base64 编码的 32 字节 AES 密钥 |
| `omichub_monitor_tls_verify` | `SNAKEMAKE_OMICHUB_MONITOR_TLS_VERIFY` | 是否校验 HTTPS 证书（默认 `true`） |
| `omichub_monitor_timeout` | `SNAKEMAKE_OMICHUB_MONITOR_TIMEOUT` | 单次请求超时秒数（默认 `5`） |
| `omichub_monitor_queue_size` | `SNAKEMAKE_OMICHUB_MONITOR_QUEUE_SIZE` | 事件队列大小（默认 `10000`） |
| `omichub_monitor_retry_count` | `SNAKEMAKE_OMICHUB_MONITOR_RETRY_COUNT` | 网络错误/5xx 重试次数（默认 `3`） |
| `omichub_monitor_retry_backoff` | `SNAKEMAKE_OMICHUB_MONITOR_RETRY_BACKOFF` | 重试退避基数秒（默认 `0.5`） |

### 配置文件示例

在工作流根目录下创建 `monitor_config.yaml`：

```yaml
# Loki 兼容端点（第一期兼容方案，可选）
loki_url: "http://web:8000/api/v1/workflow-monitor"
project_name: "<task_id>"

# OmicHub 原生事件端点（推荐）
omichub_monitor_url: "https://omichub.example.edu/api/v1/workflow-monitor/events"
omichub_monitor_token: "${OMICHUB_WORKFLOW_MONITOR_TOKEN}"
omichub_task_id: "<task_id>"
omichub_flow_id: "rna_seq"
omichub_user_id: "<user_id>"

# 生产环境安全加固
omichub_monitor_sign_requests: true
omichub_monitor_signing_key: "${OMICHUB_WORKFLOW_MONITOR_SIGNING_KEY}"
omichub_monitor_encrypt_payload: false
omichub_monitor_encryption_key: "${OMICHUB_WORKFLOW_MONITOR_ENCRYPTION_KEY}"
```

### 运行方式

```bash
snakemake \
  -s Snakefile \
  --cores 8 \
  --logger rich-loguru \
  --config monitor_conf=monitor_config.yaml
```

> 注意：Snakemake 实际接受的 logger 名称是 `rich-loguru`（带连字符），与 `pyproject.toml` 中 entry point 名称 `rich_loguru`（下划线）不同。

### 安全等级建议

- **等级 A（内网开发）**：HTTP + Bearer Token。
- **等级 B（生产推荐）**：HTTPS + Bearer Token + HMAC 签名。
- **等级 C（高敏感）**：HTTPS + Bearer Token + HMAC 签名 + AES-256-GCM payload 加密。

### 事件 Payload 示例

OmicHub 原生事件包含 Snakemake 运行状态与进度信息：

```json
{
  "schema_version": "omichub.workflow_event.v1",
  "task_id": "<task_id>",
  "flow_id": "rna_seq",
  "user_id": "<user_id>",
  "project_name": "<task_id>",
  "timestamp": "2026-07-10T12:00:00Z",
  "level": "info",
  "source": "snakemake",
  "message": "Finished jobid: 12 (Rule: trim_fastq)",
  "snakemake": {
    "rule": "trim_fastq",
    "job_id": 12,
    "event_type": "JobFinished",
    "shell_command": null,
    "progress_percent": 42.5,
    "progress_details": "17/40"
  },
  "runtime": {
    "host": "worker-host",
    "pid": 12345,
    "cwd": "/data/...",
    "command": "snakemake -s ..."
  }
}
```

## 🛠 使用方法

### 基础运行

只需指定 logger 插件即可：

```bash
snakemake --logger rich-loguru --cores 4
```

### 进阶：在 Python 脚本中使用

您的 `scripts/` 目录下的 Python 脚本也可以复用该日志配置，将分析日志也推送到 Loki。

```python
# scripts/analysis.py
from snakemake_logger_plugin_rich_loguru import get_logger, install

# 如果是独立脚本运行（非 Snakemake 规则内），可以手动初始化
# install({"loki_url": "...", "project_name": "..."})

logger = get_logger()

def analyze_data():
    logger.info("开始处理样本...", extra={"sample_id": "S1"})
    try:
        # ... 业务逻辑 ...
        logger.success("样本 S1 处理完成")
    except Exception as e:
        logger.exception("处理失败")

if __name__ == "__main__":
    analyze_data()
```

## 📈 Grafana 中的查询示例

在 Grafana 的 Explore 页面中，您可以选择 Loki 数据源并使用 LogQL 进行查询：

**筛选特定项目的日志：**
```logql
{job="snakemake", project="My_Analysis_Project"}
```

**查找特定规则的日志（利用自动提取的字段）：**
```logql
{job="snakemake"} | json | Snakemake_Rule="short_read_qc_r1"
```

**统计特定任务的耗时或错误：**
```logql
count_over_time({job="snakemake"} | json | level="ERROR" [1h])
```

**实时监控分析进度 (Progress Bar)：**

若要在 Grafana 面板中展示实时的任务完成进度条，推荐使用以下配置。该配置兼顾了查询性能与显示逻辑，能够自动隐藏非活跃项目和已完成项目。

#### 1. 查询语句 (LogQL)
使用 **Bar Gauge** 面板，输入以下精简后的 LogQL：

```logql
max by (project) (
  last_over_time(
    (
      {service_name="snakemake"}
      |= "progress_percent"          # 🚀 性能核心：先过滤文本，防止大数据量下的 500 错误
      | json
      | line_format "{{.msg}}"
      | regexp "^(?P<project>[^\\s|]+)"
      | unwrap progress_percent
      | __error__=""
    )[1m]                            # ⏱️ 时效控制：仅查看最近 1 分钟内活跃的数据
  )
) > 0.5 < 100                        # 🧹 净化逻辑：大于 0.5 (过滤死任务) 且 小于 100 (隐藏已完成)
```
> **注意**：使用 `< 100` 可以让任务在完成后瞬间从面板消失。如果你希望任务完成后在面板停留 1 分钟再消失，请改为 `<= 100`。

#### 2. 查询面板设置 (Query Options)
为了确保标签生效并能自动隐藏旧数据，请务必进行以下设置：
- **Legend (图例)**: `{{project}}`
- **Type (类型)**: `Instant` (瞬时查询) —— **关键设置！**
- **Format**: 如果有此选项，选择 `Time series`。

#### 3. 转换设置 (Transformations) 🛠️
如果面板显示 "Value #A" 而不是项目名，请添加以下转换：
- **功能**: `Prepare time series` (准备时间序列)
- **设置**: `Format` 选择 `Multi-frame time series`
- **作用**: 强制将表格数据转换为带标签的时间序列，使 Legend 设置生效。

#### 4. 面板属性设置 (Panel Options)
- **Standard options > Display name**: [保持为空]（利用 Transformation 自动提取项目名）
- **Standard options > Min**: `0`
- **Standard options > Max**: `100`
- **Value options > Calculation**: `Last` (默认值)

> **提示**：建议将 Unit 设置为 `Misc -> Percent (0-100)`。

## 📋 版本历史

### v0.2.1
- **Bugfix**：将 Loki/OmicHub 后台 worker 线程改为 `daemon=True`，修复 Snakemake 任务完成后进程偶发挂起的问题。
- **测试**：新增 `tests/mock_omichub_server.py` 与 `tests/monitor_config.yaml`，提供本地 OmicHub 集成测试能力。

### v0.2.0
- **新特性**：新增 **OmicHub 原生工作流监控推送**能力，支持 Bearer Token、HMAC-SHA256 签名、AES-256-GCM payload 加密。
- **架构升级**：抽取公共事件解析器 `extract_snakemake_event()` 与公共进度追踪器 `SnakemakeProgressTracker`，Loki 与 OmicHub 共用同一套进度计算逻辑。
- **配置增强**：支持仅含 `omichub_monitor_url` 的配置文件、`${ENV}` 占位符解析、`SNAKEMAKE_OMICHUB_*` 环境变量兜底，以及敏感字段自动脱敏。
- **可靠性增强**：OmicHub handler 采用有界队列、可配置重试/退避、5 秒超时、`atexit` 退出 flush。
- **依赖更新**：新增 `cryptography ^42.0.0`、`pyyaml ^6.0.3`。
- **测试**：新增 `test_omichub_utils.py`、`test_security_utils.py`。

### v0.1.8 (Latest)
- **新特性**：集成 **钉钉/飞书 Webhook 通知** 功功能，支持工作流成功/失败自动告警。
- **架构升级**：Loki 推送采用 **Queue + Worker Thread** 模式，显著降低高频率日志下的系统开销。
- **可靠性增强**：优化 Loki 标签逻辑，确保 ProjectID 标签的唯一性与准确性。
- **质量保证**：新增 `loki_utils` 和 `notification_utils` 的自动化单元测试。

### v0.1.7
- **性能优化**：启动动画默认关闭（去除 `time.sleep` 硬阻塞），Snakemake 启动速度提升 4-5 秒；可通过环境变量 `SNAKEMAKE_RICH_LOGURU_SPLASH=1` 手动开启。
- **稳定性**：`logger.remove()` 改为精确移除默认 handler（`logger.remove(0)`），不再误删用户或其他库预设的 loguru 配置。
- **Loki 推送优化**：改为后台 `threading.Thread` 异步发送，增加 5 秒网络超时；失败时向 `stderr` 输出提示，避免完全静默丢失。
- **状态隔离**：Loki 进度状态从全局函数属性移到 `LokiHandler` 实例属性，多个 Snakemake 流程同时运行互不串扰。
- **进度锁定**：`real_total` 一旦从 Job stats 中检测到即锁定，防止后续日志误匹配导致进度基准被篡改。
- **日志格式优化**：自定义 `CompactRichHandler` 去除级别名默认 8 字符填充，修复终端输出间距过大的问题；过滤空/`None` 消息。

## 📅 后续更新计划

为了满足更广泛的监控需求，本项目计划在后续版本中引入 **多平台推送扩展 (Multi-platform Push Extensions)**，支持将关键任务状态推送到更多协作与告警平台：

- [ ] **企业级即时通讯**：支持 钉钉 (DingTalk)、飞书 (Lark)、企业微信 (WeChat Work) 的 Webhook 机器人通知。
- [ ] **多端推送服务**：集成 Bark (iOS)、PushDeer、Server酱 等移动端推送工具。
- [ ] **标准协议支持**：支持通过 SMTP 发送关键错误邮件告警。
- [ ] **日志存储优化**：提供对 ELK (Elasticsearch, Logstash, Kibana) 的支持。
- [ ] **交互式监控**：开发简单的 Web Dashboard 实时预览多个 Snakemake 实例的状态。

欢迎通过 Issue 提交您的功能需求或贡献代码！
