dm_database_sqllog2db/cli/
init.rs1use crate::error::{Error, FileError, Result};
2use log::{debug, error, info, warn};
3use std::fs;
4use std::path::Path;
5
6pub fn handle_init(output_path: &str, force: bool) -> Result<()> {
8 let path = Path::new(output_path);
9
10 info!("Preparing to generate configuration file: {output_path}");
11
12 if path.exists() && !force {
14 error!("Configuration file already exists: {output_path}");
15 info!("Tip: use --force to overwrite");
16 return Err(Error::File(FileError::AlreadyExists {
17 path: path.to_path_buf(),
18 }));
19 }
20
21 if path.exists() && force {
22 warn!("Will overwrite existing configuration file");
23 }
24
25 debug!("Generating default configuration content...");
27 let default_config = r#"# SQL 日志导出工具默认配置文件 (请根据需要修改)
28
29[sqllog]
30# SQL 日志目录或文件路径
31directory = "sqllogs"
32
33[error]
34# 解析错误日志输出路径(纯文本行: file | error | raw | line)
35file = "export/errors.log"
36
37[logging]
38# 应用日志输出目录或文件路径 (当前版本要求为"文件路径",例如 logs/sqllog2db.log)
39# 如果仅设置为目录(如 "logs"),请确保后续代码逻辑能够自动生成文件;否则请填写完整文件路径
40file = "logs/sqllog2db.log"
41# 日志级别: trace | debug | info | warn | error
42level = "info"
43# 日志保留天数 (1-365) - 用于滚动文件最大保留数量
44retention_days = 7
45
46[features.filters]
47# 是否启用过滤器
48enable = false
49
50# --- 元数据过滤器 (Record-level: 满足任一条件即保留该条记录) ---
51# 过滤指定的事务 ID
52# trxids = ["257809109", "257809110"]
53# 过滤指定的客户端 IP (支持模糊匹配)
54# client_ips = ["127.0.0.1", "192.168"]
55# 过滤指定的用户名 (支持模糊匹配)
56# usernames = ["SYSDBA"]
57# 过滤时间范围 (格式:2023-01-01 00:00:00)
58# start_ts = "2023-01-01 00:00:00"
59# end_ts = "2023-01-01 23:59:59"
60# 过滤指定的会话 ID (支持模糊匹配)
61# sess_ids = ["0x7f41435437a8"]
62# 过滤指定的线程 ID (支持模糊匹配)
63# thrd_ids = ["2188515"]
64# 过滤指定的语句类型 (支持模糊匹配)
65# statements = ["INS", "UPD", "DEL"]
66# 过滤指定的应用名称 (支持模糊匹配)
67# appnames = ["DMSQL"]
68
69# --- 指标过滤器 (Transaction-level: 满足条件则保留包含该语句的整个事务 - 需要预扫描) ---
70[features.filters.indicators]
71# 过滤指定的执行 ID (保留整个事务)
72# exec_ids = [257809109, 257809110]
73# 过滤最小执行时长 (毫秒)
74# min_runtime_ms = 1000
75# 过滤最小影响行数
76# min_row_count = 100
77
78# --- SQL 过滤器 (Transaction-level: 满足模式则保留整个事务 - 需要预扫描) ---
79[features.filters.sql]
80# 包含模式列表 (SQL 包含任一模式则匹配)
81# include_patterns = ["FROM USER_TABLES", "DELETE FROM"]
82# 排除模式列表 (SQL 包含任一模式则剔除)
83# exclude_patterns = ["SELECT 1", "DUAL"]
84
85# ===================== 导出器配置 =====================
86# 只能配置一个导出器
87# 同时配置多个时,按优先级使用:csv > jsonl > sqlite
88
89# 方案 1: csv 导出(默认)
90[exporter.csv]
91file = "outputs/sqllog.csv"
92overwrite = true
93append = false
94
95# 方案 2: JSONL 导出(JSON Lines 格式,每行一个 JSON 对象)
96# [exporter.jsonl]
97# file = "export/sqllog2db.jsonl"
98# overwrite = true
99# append = false
100
101# 方案 3: SQLite 数据库导出
102# [exporter.sqlite]
103# database_url = "export/sqllog2db.db"
104# table_name = "sqllog_records"
105# overwrite = true
106# append = false
107
108"#;
109
110 if let Some(parent) = path.parent().filter(|p| !p.exists()) {
112 info!("Creating directory: {}", parent.display());
113 fs::create_dir_all(parent).map_err(|e| {
114 crate::error::Error::File(crate::error::FileError::CreateDirectoryFailed {
115 path: parent.to_path_buf(),
116 reason: e.to_string(),
117 })
118 })?;
119 }
120
121 debug!("Writing configuration file...");
123 fs::write(path, default_config).map_err(|e| {
124 Error::File(FileError::WriteFailed {
125 path: path.to_path_buf(),
126 reason: e.to_string(),
127 })
128 })?;
129
130 if force && path.exists() {
131 info!("Configuration file overwritten: {output_path}");
132 } else {
133 info!("Configuration file generated: {output_path}");
134 }
135
136 info!("Next steps:");
137 info!(" 1. Edit configuration file: {output_path}");
138 info!(" 2. Validate configuration: sqllog2db validate -c {output_path}");
139 info!(" 3. Run export: sqllog2db run -c {output_path}");
140
141 Ok(())
142}