news 2026/9/24 8:56:28

EOSIO nodeos Deep-mind Logger 集成指南:启用 `--deep-mind` 与解析 DMLOG 链上操作日志

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
EOSIO nodeos Deep-mind Logger 集成指南:启用 `--deep-mind` 与解析 DMLOG 链上操作日志
  • 区块链

【免费下载链接】eos

An open source smart contract platform

项目地址:https://gitcode.com/gh_mirrors/eo/eos
点击查看免费下载

本指南以 EOSIO 仓库中 Deep-mind Logger 集成文档 为核心,系统讲解如何在nodeos上启用 Deep-mind logger、识别以DMLOG为前缀的结构化日志行,并深入nodeoschain_pluginchain库源码,说明这些日志事件从何处产生、如何输出,帮助你为区块链数据索引、审计与分析类系统(如 dfuse 平台)提供完整的链上数据源。

Overview:Deep-mind Logger 是什么

Deep-mind logger是 dfuse 平台(一个高可扩展、高性能的开源区块链数据搜索与处理平台)的核心组件之一。它通过与 EOSIO 的nodeos核心服务守护进程深度集成,将节点在出块、验证、资源限制、授权、数据库读写等链上操作过程中的内部细节,以结构化、可机器解析的日志行完整输出出来。

与面向人眼排障的普通nodeos日志不同,Deep-mind 日志的目标读者是外部数据索引与处理程序:下游系统(例如 dfuse 的索引器)可以消费这些日志,重建出完整的链状态变化历史(谁创建了表、哪一行数据被插入/更新/删除、每笔交易的完整 trace、协议特性何时激活等),而无需解析区块二进制或依赖节点内存状态。

在 EOSIO 中,Deep-mind 日志功能由chain_plugin提供(--deep-mind命令行开关),其日志输出经由fc日志框架的专用dmlogappender 完成。

与 Zipkin tracer 的关系

在 第三方日志与追踪集成总览 中,EOSIO 官方将 Deep-mind logger 与 Zipkin tracer 并列为两种官方支持的遥测集成方式:

遥测工具关注点输出形式
Deep-mind logger链上操作细节(区块、交易、资源、DB 变更、协议特性)文本日志行(DMLOG前缀)
Zipkin tracer节点内部请求/处理的分布式追踪时序Zipkin span(HTTP 上报)

二者用途互补:Deep-mind 回答"链上发生了什么",Zipkin 回答"节点内部处理耗时如何"。

如何启用 Deep-mind Logger

要获得完整的 Deep-mind 日志功能,只需在启动nodeos实例时追加--deep-mind标志:

nodeos --deep-mind

该标志在源码中定义于 chain_plugin.cpp:

("contracts-console", bpo::bool_switch()->default_value(false), "print contract's output to console") ("deep-mind", bpo::bool_switch()->default_value(false), "print deeper information about chain operations")
  • 类型为布尔开关,默认关闭false);
  • 开启后,nodeos会输出"关于链操作的更深层信息"(print deeper information about chain operations)。

启动后即可在nodeos控制台输出中观察到 Deep-mind logger 生成的详细信息。这些日志行与默认nodeos输出行的区别在于:它们以DMLOG关键字开头。此外,chain_plugin还会同时输出一条独立的启动日志行(以dm-log相关文本标识),便于确认 Deep-mind 已激活。

启用时的底层处理

--deep-mind开启后,chain_plugin.cpp 会执行两件关键操作:

// initialize deep mind logging if ( options.at( "deep-mind" ).as<bool>() ) { // ...(注释说明见下) setbuf(stdout, NULL); // 1. 将 stdout 切换为无缓冲 I/O my->chain->enable_deep_mind( &_deep_mind_log ); // 2. 在 controller 上启用 Deep-mind 并挂接日志器 }
  1. setbuf(stdout, NULL):将标准输出从行缓冲切换为无缓冲模式。源码注释(chain_plugin.cpp)解释了原因:Deep-mind 会向进程外输出海量数据,在高压力下fwrite等系统调用可能在中途失败;如果使用 libc 持有的缓冲,恢复与重试几乎不可能正确完成。改为无缓冲后,fc::dmlog_appender可以在写入失败时自行重试,从而获得更健壮的输出。注释同时提到未来版本计划改用 FIFO 文件方式输出,以彻底摆脱对stdout的依赖。
  2. enable_deep_mind(&_deep_mind_log):将 Deep-mind 日志器注入链控制器(controller),此后区块、交易、数据库、资源等环节都会向该日志器发送结构化事件。

日志器与 appender 的注册

nodeos在 main.cpp 中通过add_deep_mind_loggerdeep-mind日志器注册进fc日志框架:

fc::logging_config& add_deep_mind_logger(fc::logging_config& config) { config.appenders.push_back( fc::appender_config( "deep-mind", "dmlog" ) ); fc::logger_config dmlc; dmlc.name = "deep-mind"; dmlc.level = fc::log_level::debug; dmlc.enabled = true; dmlc.appenders.push_back("deep-mind"); config.loggers.push_back( dmlc ); return config; }

要点:

  • appender 类型为dmlog(Deep-mind 专用输出器),日志器名为deep-mind
  • 日志级别固定为debugenabled = true
  • 当用户没有提供logging.json时(main.cpp),initialize_logging会使用默认配置并注入该 Deep-mind 日志器;若提供了logging.json,Deep-mind 的日志配置则交由配置文件中对应的 logger/appender 控制(日志配置热重载由logging_conf_handler支持,见 main.cpp)。

DMLOG 日志行详解:你在控制台会看到什么

下面是启用--deep-mind后,在nodeos输出控制台中实际可见的DMLOG日志行示例(来自 Deep-mind Logger 集成文档):

DMLOG START_BLOCK 30515 DMLOG TRX_OP CREATE onblock 308f77bf49ab4ddde74d37c7310c0742e253319d9da57ebe51eb7b35f1ffe174 {"expiration":"2020-11-12T10:13:06","ref_block_num":30514,...} DMLOG CREATION_OP ROOT 0 DMLOG RLIMIT_OP ACCOUNT_USAGE UPD {"owner":"eosio","net_usage":{"last_ordinal":1316982371,"value_ex":0,"consumed":0},"cpu_usage":{"last_ordinal":1316982371,"value_ex":24855,"consumed":101},"ram_usage":27083} DMLOG APPLIED_TRANSACTION 30515 {"id":"308f77bf49ab4ddde74d37c7310c0742e253319d9da57ebe51eb7b35f1ffe174","block_num":30515,"block_time":"2020-11-12T10:13:05.500",...} DMLOG RLIMIT_OP STATE UPD {"average_block_net_usage":{"last_ordinal":30514,"value_ex":0,"consumed":0},"average_block_cpu_usage":{"last_ordinal":30514,...} DMLOG ACCEPTED_BLOCK 30516 {"block_num":30516,"dpos_proposed_irreversible_blocknum":30516,"dpos_irreversible_blocknum":30515,... ... DMLOG FEATURE_OP ACTIVATE 0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd {"feature_digest":"0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd","subjective_restrictions":{"enabled":true,"preactivation_required":false,"earliest_allowed_activation_time":"1970-01-01T00:00:00.000"},"description_digest":"64fe7df32e9b86be2b296b3f81dfd527f84e82b98e363bc97e40bc7a83733310","dependencies":[],"protocol_feature_type":"builtin","specification": [{"name":"builtin_feature_codename","value":"PREACTIVATE_FEATURE"}]} ... DMLOG FEATURE_OP ACTIVATE 825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16 {"feature_digest":"825ee6288fb1373eab1b5187ec2f04f6eacb39cb3a97f356a07c91622dd61d16","subjective_restrictions":{"enabled":true,"preactivation_required":true,"earliest_allowed_activation_time":"1970-01-01T00:00:00.000"},"description_digest":"14cfb3252a5fa3ae4c764929e0bbc467528990c9cc46aefcc7f16367f28b6278","dependencies":[],"protocol_feature_type":"builtin","specification": [{"name":"builtin_feature_codename","value":"KV_DATABASE"}]} ... DMLOG FEATURE_OP ACTIVATE c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071 {"feature_digest":"c3a6138c5061cf291310887c0b5c71fcaffeab90d5deb50d3b9e687cead45071","subjective_restrictions":{"enabled":true,"preactivation_required":true,"earliest_allowed_activation_time":"1970-01-01T00:00:00.000"},"description_digest":"69b064c5178e2738e144ed6caa9349a3995370d78db29e494b3126ebd9111966","dependencies":[],"protocol_feature_type":"builtin","specification": [{"name":"builtin_feature_codename","value":"ACTION_RETURN_VALUE"}]}

各事件类型语义

结合文档示例与仓库源码,可以归纳出以下核心事件类型(DMLOG后第一个字段为事件类型):

事件类型语义示例/来源
START_BLOCK开始处理/生产一个区块(后跟区块号,如30515出块循环入口
TRX_OP交易生命周期操作(如CREATE onblock,后跟交易 id 与交易 JSON)交易创建/恢复阶段
CREATION_OP作用域/对象创建操作(如ROOT 0,标识根对象及其 id)数据库会话初始化
RLIMIT_OP资源限制状态变化:ACCOUNT_USAGE UPD(账户资源用量更新,含 net/cpu 用量 ordinal、value_exconsumedram_usage字节数)、STATE UPD(全局资源状态更新,如平均区块 net/cpu 用量)见下文源码位置
APPLIED_TRANSACTION一笔交易已被完整执行应用(后跟区块号与交易 trace JSON,含idblock_numblock_time等)chain_plugin.cpp
ACCEPTED_BLOCK一个区块被接受(后跟区块号与区块状态 JSON,含dpos_proposed_irreversible_blocknumdpos_irreversible_blocknum等)chain_plugin.cpp
FEATURE_OP协议特性(protocol feature)操作,如ACTIVATE(激活,后跟特性摘要feature_digest、主观限制subjective_restrictions、依赖dependencies、特性类型protocol_feature_type与规格说明)protocol_feature_manager相关

值得注意的细节:

  • FEATURE_OP ACTIVATE是理解协议演进的入口。示例中三条ACTIVATE分别对应PREACTIVATE_FEATUREpreactivation_required: false)、KV_DATABASEpreactivation_required: true)与ACTION_RETURN_VALUEpreactivation_required: true)三个内建协议特性,完整记录了每个特性激活时的摘要与约束条件。这为外部系统还原"网络在何时启用了哪些协议特性"提供了精确依据。
  • RLIMIT_OP是资源计量审计的数据源ACCOUNT_USAGE UPD给出了eosio账户在某个时间点的net_usage(last_ordinal、value_ex、consumed)、cpu_usageram_usage(字节数),下游可据此重建资源使用历史。
  • 事件主体部分是 JSON 对象(可能跨行输出),其后紧跟的十六进制字符串(如交易 id)或 JSON 字段可作为关联键。

源码视角:DMLOG 事件从哪些环节产生

Deep-mind 日志并非由单一模块集中生成,而是分散在链执行管线的多个关键节点。除上面已展示的 chain_plugin.cpp(ACCEPTED_BLOCKAPPLIED_TRANSACTION,分别挂在accepted_blockapplied_transaction信号上,将整个区块/交易 trace 序列化并输出)之外,链库内部同样大量埋点:

  • 数据库操作事件(TBL_OP/DB_OP:在 db_context.cpp 中,表创建/删除输出TBL_OP INS/REM,行记录插入/更新/删除输出DB_OP INS/UPD/REM,字段依次为动作 id(action_id)、付费账户(payer)、表所属合约(code)、作用域(scope)、表名、主键(primkey)以及以十六进制表示的记录数据(ndata/odata)。例如插入一行:

    DMLOG DB_OP INS ${action_id} ${payer} ${table_code} ${scope} ${table_name} ${primkey} ${ndata}
  • 授权操作事件(AUTH_OP:authorization_manager.cpp 在授权检查与权限更新路径上(如check_authorizationupdate_permission等)会写入 Deep-mind 日志,记录权限变更与授权判定细节。

  • 资源限制事件(RLIMIT_OPlibraries/chain/resource_limits.cpp是文档示例中RLIMIT_OP ACCOUNT_USAGE/STATE UPD的实现载体,负责在资源账户用量与全局资源状态更新时输出对应 JSON。

  • 合约调用上下文:apply_context.cpp 内含大量if (auto dm_logger = control.get_deep_mind_logger())守卫式埋点(如动作执行、inline action、上下文变更等环节),仅在 Deep-mind 启用时才会进入日志分支,从而在默认情况下保持零开销。

  • KV 数据库(rocksdb)路径libraries/chain/backing_store/kv_context.cppdb_context_rocksdb.cppdb_key_value_any_lookup.cpp等文件同样包含 Deep-mind 埋点,覆盖 KV 表操作事件(KV_OP类),配合KV_DATABASE协议特性使用。

这种"守卫式埋点 + 集中式 appender"的设计带来两个工程优势:

  1. 默认零成本get_deep_mind_logger()未启用时返回空指针,日志分支被短路,不影响正常节点性能;
  2. 输出可审计:所有 Deep-mind 事件最终统一经deep-mindlogger(dmlogappender)输出,格式一致、可被下游工具流式消费。

性能考虑与使用建议

第三方日志与追踪集成总览 明确提示:一切皆有代价。遥测工具一旦激活,必然会对nodeos性能造成一定影响,影响程度取决于多种因素(区块吞吐、交易密度、数据库变更量、输出落盘/管道消费速度等),但无论何种情况性能都会被拖累。

因此官方建议:

  • 按需开启:仅在你确实需要 Deep-mind 提供的额外详细信息(例如搭建区块链数据索引服务、调试协议特性激活、进行链状态审计)时启用--deep-mind
  • 用后即关:完成数据采集后立刻移除该标志并重启nodeos,让节点回归无埋点的正常运行模式;
  • 配套治理输出:由于 Deep-mind 输出量巨大,建议将nodeos的 stdout 重定向到专门的文件或管道供下游消费,避免与控制台人工排障日志混流。

总结

Deep-mind logger 为 EOSIO 链数据生态提供了一个"链上操作全记录"的标准输出通道:一个--deep-mind标志即可让nodeos输出覆盖区块生产(START_BLOCK)、交易生命周期(TRX_OPAPPLIED_TRANSACTION)、资源计量(RLIMIT_OP)、区块接受(ACCEPTED_BLOCK)、协议特性激活(FEATURE_OP)以及表/行级数据库变更(TBL_OPDB_OP)等全链路事件。理解其事件格式与源码埋点位置,是构建基于 EOSIO 的区块链索引、分析与审计系统的第一步。

进一步阅读

  • Deep-mind Logger 官方集成文档(本指南的原始出处)
  • 第三方日志与追踪集成总览
  • Zipkin tracer 集成
  • chain_plugin 插件文档
  • nodeos 原生日志配置
  • 区块链

【免费下载链接】eos

An open source smart contract platform

项目地址:https://gitcode.com/gh_mirrors/eo/eos
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 8:37:51

RUST图解 第 1 章:入门(Getting Started)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/24 8:37:41

SPI四种模式详解:从CPOL/CPHA原理到实战配置与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华