Metadata-Version: 2.4
Name: pyclog
Version: 0.1.2
Summary: A Python package for reading and writing .clog files with logging integration.
Author-email: Akanyi <sakayezq@gmail.com>
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Logging
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# pyclog

`pyclog` 是一个 Python 包，提供简单易用的 API 来读写 `.clog` 文件，并与 Python 标准 `logging` 模块无缝集成。

[Github](https://github.com/Akanyi/pyclog)

## `.clog` 文件格式

`.clog` 文件旨在提供一种高效、可流式处理的日志存储格式，支持压缩以节省空间。

### 核心设计思想

* **文件头 (Header)**: 用于快速识别文件类型、版本和压缩算法。
* **数据块 (Chunk)**: 将多条日志记录组合在一起进行压缩，以获得高压缩率。
* **流式处理**: 可以一条一条地写入，也可以一个块一个块地读取，无需将整个文件加载到内存。

### 文件结构

```code
[ File Header (16 bytes) ]
[ Chunk 1 ]
[ Chunk 2 ]
...
[ Chunk N ]
```

#### 1. 文件头 (File Header) - 固定16字节

| 偏移量 (Bytes) | 长度 (Bytes) | 字段名          | 描述                                                                                             |
| :------------- | :----------- | :-------------- | :----------------------------------------------------------------------------------------------- |
| 0-3            | 4            | Magic Bytes     | 固定的 `b'CLOG'` (0x43, 0x4C, 0x4F, 0x47)，用于快速识别文件类型。                               |
| 4              | 1            | Format Version  | 格式版本号，例如 `\x01` 代表版本1。允许未来升级格式而不破坏向后兼容性。                         |
| 5              | 1            | Compression Code | 压缩算法代码。`\x00`: 无压缩 (用于调试), `\x01`: Gzip, `\x02`: Zstandard。允许扩展。 |
| 6-15           | 10           | Reserved        | 保留字节，用 `\x00` 填充。为未来扩展（如加密标志、元数据等）预留空间。                           |

#### 2. 数据块 (Chunk) - 变长

每个数据块由 **块头 (Chunk Header)** 和 **块数据 (Chunk Data)** 组成。

| 组成分     | 长度 (Bytes)    | 字段名            | 描述                                                               |
| :----------- | :-------------- | :---------------- | :----------------------------------------------------------------- |
| 块头         | 4               | Compressed Size   | 后面紧跟的 **块数据** 的压缩后字节数。读取时，根据这个值就能知道要读多少字节。 |
|              | 4               | Uncompressed Size | 块数据解压后的原始字节数。用于在解压前分配内存缓冲区。             |
|              | 4               | Record Count      | 这个块中包含的日志记录条数。                                       |
| 块数据 (压缩) | Compressed Size | Compressed Log Data | 将多条日志记录序列化后，使用文件头中指定的压缩算法进行压缩得到的数据。 |

#### 3. 块内日志记录的序列化

在压缩之前，块内的多条日志记录如何组织？我们使用简单的文本格式，每条记录占一行。

**记录格式**: `ISO8601时间戳\t日志级别\t日志消息\n`

* **分隔符**: 使用制表符 `\t` (Tab) 作为字段分隔符，因为它在普通日志消息中出现的概率远低于逗号或空格。
* **换行符**: 使用 `\n` 分隔不同的日志记录。

## 安装

```bash
pip install pyclog
# 如果需要 Zstandard 压缩支持
pip install pyclog[zstandard]
```

## 使用示例

### 写入 `.clog` 文件

```python
from pyclog import ClogWriter, constants

# 使用 gzip 压缩写入
with ClogWriter("my_log.clog", compression_code=constants.COMPRESSION_GZIP) as writer:
    writer.write_record("INFO", "这是一个信息日志。")
    writer.write_record("WARNING", "这是一个警告日志，带有特殊字符：!@#$%^&*()")
    writer.write_record("ERROR", "发生了一个错误。")

# 使用无压缩写入 (用于调试)
with ClogWriter("my_debug_log.clog", compression_code=constants.COMPRESSION_NONE) as writer:
    writer.write_record("DEBUG", "这是调试日志。")

# 如果安装了 python-zstandard，可以使用 Zstandard 压缩
from pyclog import ClogWriter, constants
 try:
     with ClogWriter("my_zstd_log.clog", compression_code=constants.COMPRESSION_ZSTANDARD) as writer:
         writer.write_record("INFO", "这是 Zstandard 压缩的日志。")
 except UnsupportedCompressionError as e:
     print(f"错误: {e}")
```

### 读取 `.clog` 文件

```python
from pyclog import ClogReader

# 读取日志
with ClogReader("my_log.clog") as reader:
    for timestamp, level, message in reader.read_records():
        print(f"[{timestamp}] [{level}] {message}")

# 读取调试日志
with ClogReader("my_debug_log.clog") as reader:
    for timestamp, level, message in reader.read_records():
        print(f"[{timestamp}] [{level}] {message}")
```

### 与 Python `logging` 模块集成

```python
import logging
from pyclog import ClogFileHandler, constants

# 配置日志器
logger = logging.getLogger("my_app")
logger.setLevel(logging.INFO)

# 创建 ClogFileHandler 实例
clog_handler = ClogFileHandler("app.clog", compression_code=constants.COMPRESSION_GZIP)

# 设置日志格式
formatter = logging.Formatter('%(asctime)s\t%(levelname)s\t%(message)s')
clog_handler.setFormatter(formatter)

# 将 handler 添加到日志器
logger.addHandler(clog_handler)

# 记录日志
logger.info("应用程序启动。")
logger.warning("发现潜在问题。")
logger.error("处理请求时发生异常。")

# 确保日志被写入文件
clog_handler.close() # 或者在程序退出时自动关闭

print("日志已写入 app.clog 文件。")

# 验证写入的日志
from pyclog import ClogReader
with ClogReader("app.clog") as reader:
    print("\n--- 从 app.clog 读取日志 ---")
    for timestamp, level, message in reader.read_records():
        print(f"[{timestamp}] [{level}] {message}")
```

## 命令行工具 (CLI)

`pyclog` 提供了一个命令行工具，用于将 `.clog` 文件导出为其他格式（JSON 或纯文本），并支持压缩。

### 安装 CLI

CLI 工具随 `pyclog` 包一起安装。如果需要 Zstandard 压缩支持，请确保安装了 `pyclog[zstandard]`：

```bash
pip install pyclog
# 如果需要 Zstandard 压缩支持
pip install pyclog[zstandard]
```

### 使用 CLI

CLI 工具的入口点是 `pyclog` 命令（如果已正确安装为脚本）。

**基本用法：**

```bash
pyclog --input <input_file.clog> --output <output_file> [--format <json|text>] [--compress <none|gzip|zstd>]
```

**参数说明：**

* `--input`, `-i`：**必需**。要读取的 `.clog` 文件路径。
* `--output`, `-o`：**必需**。导出文件的输出路径。
* `--format`, `-f`：导出格式。可选值：`json` (JSON 格式) 或 `text` (纯文本格式)。默认为 `text`。
  * `json` 格式将每条日志记录导出为 JSON 对象数组。
  * `text` 格式将每条日志记录导出为一行，格式为 `时间戳|日志级别|日志消息`。
* `--compress`, `-c`：导出文件的压缩格式。可选值：`none` (不压缩), `gzip`, `zstd`。默认为 `none`。
  * 选择 `zstd` 需要额外安装 `python-zstandard` 库。

**示例：**

1. **将 `.clog` 文件导出为纯文本文件 (无压缩)：**

    ```bash
    pyclog -i my_log.clog -o my_log.txt -f text -c none
    ```

    这将生成一个 `my_log.txt` 文件，其中包含 `my_log.clog` 中的日志记录，每条记录一行，格式为 `时间戳|日志级别|日志消息`。

2. **将 `.clog` 文件导出为 JSON 文件 (使用 Gzip 压缩)：**

    ```bash
    pyclog -i my_log.clog -o my_log.json.gz -f json -c gzip
    ```

    这将生成一个 `my_log.json.gz` 文件，其中包含 `my_log.clog` 中的日志记录的 JSON 表示，并使用 Gzip 压缩。

3. **将 `.clog` 文件导出为 JSON 文件 (使用 Zstandard 压缩)：**

    ```bash
    pyclog -i my_log.clog -o my_log.json.zst -f json -c zstd
    ```

    这将生成一个 `my_log.json.zst` 文件，其中包含 `my_log.clog` 中的日志记录的 JSON 表示，并使用 Zstandard 压缩。请确保已安装 `pyclog[zstandard]`。

## 开发

### 运行测试

```bash
pytest tests/
```

## 贡献

欢迎贡献！请参阅 `DEVELOPMENT.md` 获取更多信息。

## 许可证

本项目根据 [MIT 许可证](LICENSE) 发布。
