API 参考

March 27, 2026 · View on GitHub

← 返回首页 | English

所有语言 Wrapper 共享一致的 API 命名与语义。以下每个 API 均展示所有支持的语言。


1. 创建 Log 对象

通过 create_log 静态函数创建 Log。如果名称已存在,会返回已有对象并更新其配置(部分字段如 buffer_size 不可修改,详见 配置说明)。

C++
#include <bq_log/bq_log.h>
// bq::string 可隐式接受 char*、std::string、std::string_view
static bq::log bq::log::create_log(const bq::string& log_name, const bq::string& config_content);
Java / Kotlin
import bq.log;
bq.log logObj = bq.log.create_log("my_log", config);
C#
using bq;
bq.log logObj = bq.log.create_log("my_log", config);
TypeScript (Node.js / HarmonyOS ArkTS)
import { bq } from "@pippocao/bqlog";  // Node.js ESM
// import { bq } from "bqlog";          // HarmonyOS ArkTS
const logObj = bq.log.create_log("my_log", config);
Python
from bq.log import log
log_obj = log.create_log("my_log", config)

要点:

  1. 任何语言中,返回值都不会为 null。如创建失败,可通过 is_valid() 判断。
  2. log_name 为空字符串,BqLog 会自动分配唯一名称,如 "AutoBqLog_1"
  3. 对已存在的同名 Log 调用 create_log,会复用原对象并覆盖配置。
  4. 可在全局/静态变量中安全调用——无需担心初始化顺序问题。

2. 获取 Log 对象

通过名称获取已创建的 Log 对象:

C++
static bq::log bq::log::get_log_by_name(const bq::string& log_name);
Java / Kotlin
bq.log logObj = bq.log.get_log_by_name("my_log");
C#
bq.log logObj = bq.log.get_log_by_name("my_log");
TypeScript
const logObj = bq.log.get_log_by_name("my_log");
Python
log_obj = log.get_log_by_name("my_log")

注意:请确保该 Log 已通过 create_log 创建过,否则 is_valid() 返回 false。


3. 写日志

BqLog 提供 6 个日志等级:verbosedebuginfowarningerrorfatal(重要性递增)。

格式参数使用 {} 占位符,遵循 C++20 std::format 规则(不支持排序序号与时间格式化)。强烈建议使用格式参数而非字符串拼接,以获得最佳性能和压缩效果。

C++
log_obj.info("Hello {}, count={}", "world", 42);
log_obj.error("Error code: {}", err_code);
// 所有等级: verbose, debug, info, warning, error, fatal

支持的 STR 类型:char*char16_t*char32_t*wchar_t*std::stringstd::u16stringstd::wstring、Unreal FString / FName / FText 等。

Java / Kotlin
import static bq.utils.param.no_boxing;

logObj.info("Hello {}, count={}", "world", no_boxing(42));
logObj.error("Error code: {}", no_boxing(errCode));
// 所有等级: verbose, debug, info, warning, error, fatal

重要: 使用 bq.utils.param.no_boxing() 包裹基本类型(intfloatboolean 等)以避免装箱和 GC 压力。不使用 no_boxing 时,基本类型会被自动装箱。

C#
logObj.info("Hello {}, count={}", "world", 42);
logObj.error("Error code: {}", errCode);
// 所有等级: verbose, debug, info, warning, error, fatal

参数个数 ≤ 12 时零装箱/拆箱;超过 12 个参数才退化为装箱。

TypeScript
logObj.info("Hello {}, count={}", "world", 42);
logObj.error("Error code: {}", errCode);
// 所有等级: verbose, debug, info, warning, error, fatal

参数通过 NAPI 直接传递——无额外装箱。

Python
log_obj.info("Hello {}, count={}", "world", 42)
log_obj.error("Error code: {}", err_code)
# 所有等级: verbose, debug, info, warning, error, fatal

支持的参数类型

  • 空指针 → null
  • 指针 → 0x 十六进制地址
  • bool、单/双/四字节字符
  • 8/16/32/64 位整数与无符号整数
  • 32 位与 64 位浮点数
  • 各语言的所有字符串类型
  • C# / Java:任意对象(通过 ToString() 输出)
  • C++:POD 类型(1/2/4/8 字节)、自定义类型(见 高级用法 — 自定义参数类型

日志等级


4. 强制刷新

确保所有缓冲日志落盘。在程序退出前或关键检查点调用。

C++
bq::log::force_flush_all_logs();  // 刷新所有 log 对象
log_obj.force_flush();             // 刷新单个 log 对象
Java / Kotlin
bq.log.force_flush_all_logs();
logObj.force_flush();
C#
bq.log.force_flush_all_logs();
logObj.force_flush();
TypeScript
bq.log.force_flush_all_logs();
logObj.force_flush();
Python
log.force_flush_all_logs()
log_obj.force_flush()

5. 崩溃保护

启用异常退出时自动刷新缓冲区(仅 POSIX):

C++
bq::log::enable_auto_crash_handle();
Java / Kotlin
bq.log.enable_auto_crash_handle();
C#
bq.log.enable_auto_crash_handle();
TypeScript
bq.log.enable_auto_crash_handle();
Python
log.enable_auto_crash_handle()

另见:高级用法 — 程序异常退出的数据保护log.recovery 配置


6. 拦截 / 获取 Console 输出

注册回调

C++
static void bq::log::register_console_callback(bq::type_func_ptr_console_callback callback);
static void bq::log::unregister_console_callback(bq::type_func_ptr_console_callback callback);
Java / Kotlin
bq.log.register_console_callback(callback);
bq.log.unregister_console_callback(callback);
C#
bq.log.register_console_callback(callback);
bq.log.unregister_console_callback(callback);
TypeScript
bq.log.register_console_callback(callback);
bq.log.unregister_console_callback(callback);
Python
log.register_console_callback(callback)
log.unregister_console_callback(callback)

注意:

  1. 不要在回调中调用任何同步刷新的 BqLog 函数——会造成死锁。
  2. Unity / 团结引擎 / Unreal 插件已自动将 ConsoleAppender 重定向到编辑器日志窗口。

主动拉取(适用于虚拟机环境)

当不适合从原生线程直接回调到虚拟机时(C#、Java、IL2CPP、Node.js),使用缓冲拉取模式:

// 启用缓冲(register_console_callback 和默认 console 输出将被禁用)
bq::log::set_console_buffer_enable(true);

// 在业务线程中轮询——必须持续调用,否则内存会无限增长
bq::log::fetch_and_remove_console_buffer(on_console_callback);

IL2CPP 环境: 确保回调为 static unsafe 方法,并添加 [MonoPInvokeCallback(typeof(type_console_callback))]


7. 运行时修改配置

C++
bool success = log_obj.reset_config(new_config);
Java / Kotlin
boolean success = logObj.reset_config(newConfig);
C#
bool success = logObj.reset_config(newConfig);
TypeScript
const success = logObj.reset_config(newConfig);
Python
success = log_obj.reset_config(new_config)

部分字段(buffer_sizethread_mode)不可在运行时修改。详见 配置说明


8. 启用 / 禁用 Appender

C++
log_obj.set_appender_enable("appender_name", false);  // 禁用
log_obj.set_appender_enable("appender_name", true);   // 重新启用
Java / Kotlin
logObj.set_appender_enable("appender_name", false);  // 禁用
logObj.set_appender_enable("appender_name", true);   // 重新启用
C#
logObj.set_appender_enable("appender_name", false);
logObj.set_appender_enable("appender_name", true);
TypeScript
logObj.set_appender_enable("appender_name", false);
logObj.set_appender_enable("appender_name", true);
Python
log_obj.set_appender_enable("appender_name", False)
log_obj.set_appender_enable("appender_name", True)

9. 快照(Snapshot)

捕获最近日志用于异常上报。需在 配置说明 中启用 snapshot

C++
bq::string snapshot = log_obj.take_snapshot("UTC+8");
// bq::string 可隐式转换为 std::string
Java / Kotlin
String snapshot = logObj.take_snapshot("UTC+8");
C#
string snapshot = logObj.take_snapshot("UTC+8");
TypeScript
const snapshot: string = logObj.take_snapshot("UTC+8");
Python
snapshot = log_obj.take_snapshot("UTC+8")

10. 解码二进制日志文件

运行时解码 CompressedFileAppender 日志:

// 仅 C++ —— 其他语言使用离线命令行工具
bq::tools::log_decoder decoder("path/to/file.logcompr", "optional_private_key");
while (decoder.decode() == bq::appender_decode_result::success) {
    auto& text = decoder.get_last_decoded_log_entry();
    // 处理 text...
}
// 或一次性解码整个文件:
bq::tools::log_decoder::decode_file("input.logcompr", "output.txt", "optional_key");

离线命令行解码器

从 Releases 下载 {os}_{arch}_tools_{version}

./BqLog_LogDecoder 要解码的文件 [-o 输出文件] [-k 私钥文件]

注意: 不同版本的 BqLog 之间二进制格式可能不兼容,请使用匹配版本的解码器。 另见:高级用法 — 日志加密和解密


同步日志和异步日志

通过 配置说明 中的 log.thread_mode 控制。

同步 (sync)异步 (async / independent)
行为日志在函数返回前立刻处理完毕日志写入缓冲区,由工作线程稍后处理
性能较低——调用线程阻塞等待输出完成较高——调用线程立刻返回
线程安全调用期间参数不被修改即安全同样保证;内部使用高并发环形缓冲区

线程安全说明

BqLog 在调用期间将所有参数完整拷贝到内部环形缓冲区。函数返回后,数据已安全存储。工作线程不会访问调用方栈。

唯一不安全的场景是调用过程中其他线程修改了参数

static std::string global_str = "hello";  // 其他线程正在并发修改

void thread_a() {
    log_obj.info("param: {}", global_str);  // 如果 global_str 在此调用期间被修改,结果未定义
}

原则:确保单次日志调用中传入的参数在调用期间不被修改,无论同步/异步。


Appender 介绍

名称输出目标可读性能尺寸加密
ConsoleAppender控制台 / ADB LogcatYes-No
TextFileAppenderUTF-8 文本文件YesNo
CompressedFileAppender二进制压缩文件NoYes(RSA2048 + AES256)

CompressedFileAppender 是推荐的默认文件输出格式。


构建说明

所有构建脚本位于 /build

/build
├── demo       # Demo 构建
├── lib        # Native 静态/动态库构建
├── test       # 测试工程构建
├── tools      # 工具(LogDecoder、CategoryLogGenerator 等)
├── wrapper    # 各语言 Wrapper 工程(Java / C# 等)
├── benchmark  # Benchmark 工程构建
└── plugin     # 游戏引擎插件(Unity / 团结引擎 / Unreal)

所需环境变量:

  • ANDROID_NDK_ROOT — Android 构建
  • JAVA_HOME — Java wrapper(大多数脚本默认开启)