Skip to content

日志与调试输出

PDF Oxide 通过 Rust 的 log crate 输出内部 debug、trace、warn 和 error 日志。自 v0.3.24 起,每个语言绑定都暴露了全局的 set_log_level / get_log_level 函数,可以在 Python、Node.js、Go、C# 和 Rust 中统一控制这些消息。

自 v0.3.21 起,Python 的日志集成得到了完整支持——消息不再通过 eprintln! 绕过 logging.basicConfig

日志级别

级别 说明
OFF 0 屏蔽所有日志输出
ERROR 1 导致提取终止的 panic 和解析错误
WARN 2 已恢复的错误、被绕过的格式问题
INFO 3 高级操作(打开、保存、认证)
DEBUG 4 内部决策(列检测、阅读顺序)
TRACE 5 逐对象的算符解析、逐字形的字体度量

默认值: WARN

Python

PDF Oxide 的日志宏会转发至 logging.getLogger("pdf_oxide"):

Python

import logging
import pdf_oxide

logging.basicConfig(level=logging.DEBUG)
# Equivalent to:
pdf_oxide.set_log_level("debug")

doc = pdf_oxide.PdfDocument("tricky.pdf")
doc.extract_text(0)  # emits debug logs to root handler

C++

#include <pdf_oxide/pdf_oxide.hpp>

pdf_oxide::set_log_level(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Swift

import PdfOxide

setLogLevel(4)   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

R

library(pdfoxide)

pdf_set_log_level(4L)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Julia

using PdfOxide

set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Zig

const pdf_oxide = @import("pdf_oxide");

pdf_oxide.setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Objective-C

#import <POXPdfOxide.h>

[POXSigning setLogLevel:4];   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Elixir

PdfOxide.set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

将 PDF Oxide 的输出单独路由到专属日志记录器:

Python

import logging

handler = logging.FileHandler("pdf_oxide.log")
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(message)s"))

log = logging.getLogger("pdf_oxide")
log.addHandler(handler)
log.setLevel(logging.DEBUG)

Node.js

Node.js

const { setLogLevel } = require("pdf-oxide");

setLogLevel("debug");          // one of "off"|"error"|"warn"|"info"|"debug"|"trace"

C++

#include <pdf_oxide/pdf_oxide.hpp>

pdf_oxide::set_log_level(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Swift

import PdfOxide

setLogLevel(4)   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

R

library(pdfoxide)

pdf_set_log_level(4L)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Julia

using PdfOxide

set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Zig

const pdf_oxide = @import("pdf_oxide");

pdf_oxide.setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Objective-C

#import <POXPdfOxide.h>

[POXSigning setLogLevel:4];   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Elixir

PdfOxide.set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

日志以 [LEVEL] message 格式输出到 stderr。可以通过管道接入任意日志处理器:

Node.js

const { pipeline } = require("stream");

pipeline(
  process.stderr,
  myBunyanSink,
  (err) => err && console.error("log pipe failed", err)
);

Go

Go

import pdfoxide "github.com/yfedoseev/pdf_oxide/go"

pdfoxide.SetLogLevel(pdfoxide.LogDebug)

C++

#include <pdf_oxide/pdf_oxide.hpp>

pdf_oxide::set_log_level(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Swift

import PdfOxide

setLogLevel(4)   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

R

library(pdfoxide)

pdf_set_log_level(4L)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Julia

using PdfOxide

set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Zig

const pdf_oxide = @import("pdf_oxide");

pdf_oxide.setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Objective-C

#import <POXPdfOxide.h>

[POXSigning setLogLevel:4];   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Elixir

PdfOxide.set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

若要捕获输出,请在二进制启动前设置 RUST_LOG 环境变量:

RUST_LOG=pdf_oxide=debug ./my-app

C#

C#

using PdfOxide.Core;

PdfOxide.Logging.SetLogLevel(LogLevel.Debug);

C++

#include <pdf_oxide/pdf_oxide.hpp>

pdf_oxide::set_log_level(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Swift

import PdfOxide

setLogLevel(4)   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Dart

import 'package:pdf_oxide/pdf_oxide.dart';

setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

R

library(pdfoxide)

pdf_set_log_level(4L)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Julia

using PdfOxide

set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Zig

const pdf_oxide = @import("pdf_oxide");

pdf_oxide.setLogLevel(4);   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Objective-C

#import <POXPdfOxide.h>

[POXSigning setLogLevel:4];   // 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

Elixir

PdfOxide.set_log_level(4)   # 0=Off 1=Error 2=Warn 3=Info 4=Debug 5=Trace

接入 ILogger:

C#

var logger = loggerFactory.CreateLogger("PdfOxide");
PdfOxide.Logging.OnLog += (level, message) =>
{
    logger.Log(Map(level), message);
};

Rust

可使用任何兼容 log 的后端(env_loggertracing-logslog-stdlog 等)。PDF Oxide 通过 pdf_oxide 目标输出日志:

Rust

fn main() {
    env_logger::builder()
        .filter_module("pdf_oxide", log::LevelFilter::Debug)
        .init();

    let doc = pdf_oxide::PdfDocument::open("tricky.pdf").unwrap();
    let _ = doc.extract_text(0);
}

DEBUG 能揭示什么?

值得了解的常见调试消息:

  • Detected document script: Latin / Arabic / CJK — 阅读顺序启发式算法的选择结果。
  • is_single_column_region = true — 列检测器回退到单列布局。
  • Falling back to system font DejaVu Sans for ArialMT — 字体解析失败。
  • Authenticating with user passwordauthenticate() 成功后输出。
  • Table detector: rejected 3 edges via coverage filter — 应用了边缘过滤。

TRACE 能揭示什么?

TRACE 包含逐对象的内容流解析和逐字形的字体度量解析——当某一页提取结果有误,且需要查看哪个算符产生了什么内容时非常有用。每页可能输出数千行。

相关文档