news 2026/9/13 15:27:25

ToolJet 审计日志落盘指南:基于 `LOG_FILE_PATH` 配置日志文件生成(Rsyslog)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ToolJet 审计日志落盘指南:基于 `LOG_FILE_PATH` 配置日志文件生成(Rsyslog)

ToolJet 审计日志落盘指南:基于LOG_FILE_PATH配置日志文件生成(Rsyslog)

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

ToolJet 的**日志文件(log file)**功能为审计日志提供了一份完整的落盘记录,能够捕获平台内各类活动(应用创建、删除、更新、查询执行等)的关键信息。本文将以官方指南《Setup Log File Generation (Rsyslog)》为主线,结合仓库源码,讲解如何通过LOG_FILE_PATH环境变量激活该功能、日志文件如何按进程与日期组织、轮转规则是什么,以及每条审计日志记录包含哪些字段。读完本文,你将能够独立完成日志文件功能的启用、验证与运维排查。

激活与配置(Activation and Configuration)

环境变量设置

日志文件功能默认处于关闭状态,只有显式设置环境变量LOG_FILE_PATH才会被激活。该变量的值用于指定日志文件的存放路径,例如:

LOG_FILE_PATH='rsyslog'

在源码层面,这一激活逻辑位于服务端模块加载器中。当检测到process.env.LOG_FILE_PATH存在时,LogToFileModule才会被动态注册进 NestJS 应用(见 server/src/modules/app/loader.ts):

if (process.env.LOG_FILE_PATH) { // Add log-to-file module if LOG_FILE_PATH is set const { LogToFileModule } = await import(`${await getImportPath(configs.IS_GET_CONTEXT)}/log-to-file/module`); dynamicModules.push(await LogToFileModule.register(configs)); }

因此,不设置该变量就不会产生任何日志文件;只有配置后服务端才会创建对应的日志目录与轮转 transport。

路径相对家目录

需要注意的是,LOG_FILE_PATH指定的路径是相对于机器家目录(home directory)的相对路径,而不是绝对路径。例如,若服务器家目录为/home/tooljet,则设置LOG_FILE_PATH='rsyslog'后,日志的根目录将位于/home/tooljet/rsyslog

这一点在源码中有直接印证:日志 transport 构造时会用os.homedir()拼接绝对路径(见 server/src/modules/log-to-file/constants/index.ts):

const absoluteLogDir = path.join(os.homedir(), filePath, 'tooljet_log');

也就是说,实际路径的完整结构为家目录/{LOG_FILE_PATH}/tooljet_log

服务器重启

配置完LOG_FILE_PATH环境变量后,必须重启 ToolJet 服务端,日志文件生成才会开始。这是因为:

  • 模块加载器在应用启动阶段读取环境变量并决定是否注册LogToFileModule
  • 日志轮转 transport(winston-daily-rotate-file)在服务启动时初始化并绑定到审计日志流上。

重启后,服务端才会识别新配置并开始记录审计日志。从源码结构看,LogToFileModule通过 server/src/modules/log-to-file/module.ts 注册,并使用createLogger('Log-to-file-transport')引导日志目录的创建过程。

日志轮转与组织(Log Rotation and Organization)

每日轮转

日志文件采用**每日轮转(daily rotation)**机制,即每天生成一个新的日志文件,便于审计数据的高效管理与组织。这一行为由winston-daily-rotate-filetransport 实现,关键配置如下(见 server/src/modules/log-to-file/constants/index.ts):

const transport = new DailyRotateFile({ filename: `audit.log`, level: 'info', zippedArchive: false, dirname: `${absoluteLogDir}/${processId}-%DATE%`, datePattern: 'YYYY-MM-DD', format: winston.format.combine(winston.format.prettyPrint()), json: true, });
  • datePattern: 'YYYY-MM-DD'控制按天轮转,目录名中的%DATE%会被替换为当前日期;
  • filename: 'audit.log'固定日志文件名;
  • level: 'info'表示只记录 info 及以上级别的日志;
  • zippedArchive: false表示轮转出的旧日志不做压缩归档。

每次轮转触发时,transport 会打印换文件提示,并将旧文件转换为 JSON 格式(见 server/src/modules/log-to-file/constants/index.ts):

transport.on('rotate', function (oldFilename, newFilename) { console.log(`Rotating old log file - ${oldFilename} and creating new log file ${newFilename}`); readObjectFromLines(oldFilename); });

日志文件路径结构

日志文件的最终路径由LOG_FILE_PATH变量决定,结合源码可推导出完整结构:

homepath/{LOG_FILE_PATH}/tooljet_log/{process_id}-{date}/audit.log

其中:

  • homepath:机器家目录(如/home/tooljet);
  • {process_id}:服务端进程的进程标识符,源码中使用process.pid获取;
  • {date}:当前日期,格式为YYYY-MM-DD

在服务端优雅关闭(OnApplicationShutdown)时,系统会按同样的结构定位并导出当日日志(见 server/src/modules/app/schedulers/shut-down.hook.ts):

const absoluteLogDir = join(homedir(), envFilePath, 'tooljet_log'); const currentDate = new Date(); const formattedDate = currentDate.toISOString().slice(0, 10); const filePath = `${absoluteLogDir}/${process.pid}-${formattedDate}/audit.log`; readObjectFromLines(filePath);

这种"进程 + 日期"的目录结构,使得同一进程当天的审计日志聚集在一个目录内,跨天自动分目录,便于追溯与分析。

日志目录自动创建

日志功能会在家目录下自动创建LOG_FILE_PATH值命名的文件夹(如rsyslog),该文件夹作为审计日志存储的根目录。同时,服务端启动时还会在内部再创建tooljet_log子目录(若不存在),源码通过fs.mkdirSync(absoluteLogDir, { recursive: true })实现递归创建(见 server/src/modules/log-to-file/constants/index.ts),因此无需手工预建任何目录

审计日志数据示例与字段说明

日志记录捕获了审计事件的核心要素,包括用户 ID、组织 ID、资源 ID、资源类型、操作类型、资源名称、IP 地址以及附加元数据。以下为官方文档给出的示例日志数据:

{ level: 'info', message: 'PERFORM APP_CREATE OF awdasdawdwd APP', timestamp: '2023-11-02 17:12:40', auditLog: { userId: '0ad48e21-e7a2-4597-9568-c4535aedf687', organizationId: 'cf8e132f-a68a-4c81-a0d4-3617b79e7b17', resourceId: 'eac02f79-b8e2-495a-bffe-82633416c829', resourceType: 'APP', actionType: 'APP_CREATE', resourceName: 'awdasdawdwd', ipAddress: '::1', metadata: { userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36', tooljetVersion: '2.22.2-ee2.8.3' } }, label: 'APP' }

各字段含义如下:

字段说明
level日志级别,审计日志一般为info
message人类可读的操作摘要,如PERFORM APP_CREATE OF ... APP
timestamp事件发生时间,格式YYYY-MM-DD HH:mm:ss
auditLog.userId执行操作的用户 UUID
auditLog.organizationId用户所属组织(工作区)UUID
auditLog.resourceId被操作资源的 UUID
auditLog.resourceType资源类型,如APP(应用)
auditLog.actionType操作类型,如APP_CREATE(创建应用)
auditLog.resourceName资源名称
auditLog.ipAddress发起请求的客户端 IP
auditLog.metadata.userAgent客户端浏览器 User-Agent
auditLog.metadata.tooljetVersion触发生成日志时的 ToolJet 版本号
label资源标签,如APP

日志的时间戳格式由 winston 的format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' })统一控制,而auditLog字段由审计日志格式化函数注入(见 server/src/modules/log-to-file/constants/index.ts):

export const logFormat = winston.format.combine( winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), auditLog(), logForm );

其中logForm定义了timestamp level [label]: message的纯文本输出形态;审计日志数据本身通过winston.format.prettyPrint()+json: true以可读的 JSON 对象形式写入文件。

日志的 JSON 化导出

值得强调的是,audit.log原始文件以 winston 的多行 pretty-print 格式写入(每条记录为一个多行 JSON 对象)。为了便于下游分析,系统会在两个时机将当天的audit.log转换成标准 JSON 数组文件audit.log.json

  1. 每日轮转时transport.on('rotate', ...)触发readObjectFromLines(oldFilename)
  2. 服务端关闭时ShutdownHook.onApplicationShutdown对当天文件执行同样的转换(见 server/src/modules/app/schedulers/shut-down.hook.ts)。

readObjectFromLines的核心逻辑是:逐行读取原始文件,按{边界切分多个多行对象,拼接为[ {...}, {...} ]数组,再以 2 空格缩进的标准 JSON 写入.json后缀文件(见 server/src/modules/log-to-file/constants/index.ts)。因此,原始audit.log面向人读,audit.log.json面向机器解析,可直接被日志采集器或脚本消费。

常见运维排查

  • 配置后没有日志产生:确认LOG_FILE_PATH已正确写入服务端环境(如.env文件,见下方示意),并重启服务端;模块加载器仅在启动阶段读取该变量。
  • 日志目录出现在错误位置LOG_FILE_PATH是相对于家目录的路径,请检查服务器家目录与预期是否一致;完整目录为~/{LOG_FILE_PATH}/tooljet_log/{pid}-{date}/audit.log
  • 轮转报错:检查tooljet_log目录写权限;transport 启动失败时会输出❌ Error while creating log file transport:错误信息,轮转失败时控制台会打印Rotating old log file - ...Log file generation error:日志。
  • 跨天找不到历史日志:日志按{process_id}-{date}分目录,查找历史记录时需带上对应的进程 ID 与日期。

.env配置示意:

# 启用审计日志落盘,路径相对家目录 LOG_FILE_PATH=rsyslog

小结

ToolJet 的日志文件功能通过单一环境变量LOG_FILE_PATH即可激活,为审计日志提供了"进程 + 日期"组织的每日轮转落盘机制。从 server/src/modules/app/loader.ts 的模块动态注册,到 server/src/modules/log-to-file/constants/index.ts 中基于winston-daily-rotate-file的 transport 实现,再到关闭时经ShutdownHook的 JSON 导出,整条链路清晰且可独立运维。启用后,审计日志即成为安全审计、行为追溯与合规分析的第一手数据源。

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

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

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

智能任务自动化协同AI工作流:规则引擎+多Agent实战指南

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

作者头像 李华
网站建设 2026/9/13 15:23:11

墨子活动报名系统v2.3.0:轻量级PHP闭环管理实践

简介:本资源是一套基于PHP开发的轻量级活动报名管理系统源码(v2.3.0),面向Web开发初学者、中小型活动组织者及PHP全栈实践者,解决线下/线上活动从发布、报名、审核到数据汇总的一站式管理需求。压缩包共2000个文件&…

作者头像 李华
网站建设 2026/9/13 15:22:23

6个月机器人工程师实战成长路线图

1. 这不是速成班,而是一份真实可行的工程师成长路线图“如何在6个月内成为一名机器人工程师”——看到这个标题,很多人第一反应是怀疑,甚至觉得是标题党。但作为带过三十多个机器人方向实习生、亲手搭建过工业分拣产线、也调试过服务机器人导…

作者头像 李华
网站建设 2026/9/13 15:20:10

编程语言的困境:为何类型、性能与生态之争至今无解

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

作者头像 李华