evlog扩展开发完全指南:自建drain、插件与你的框架适配器只需3步
【免费下载链接】evlogDigging through logs is not observability. Its hope — wide events, structured errors, TypeScript-first, every runtime.项目地址https://gitcode.com/gh_mirrors/ev/evlog点击查看免费下载evlog是一款 TypeScript 优先的结构化日志库核心理念是宽事件wide events 结构化错误一个请求只产生一条带完整上下文的日志事件。当内置能力不够用时evlog 提供了统一的扩展工具包evlog/toolkit让你用同样简洁的3步完成三件事自建 drain把日志发往任意后端、写插件挂入日志生命周期、为你的框架编写适配器让不支持的框架也能用 evlog。先搞懂 evlog 的扩展架构evlog 的日志管线是一条流水线每个宽事件依次经过你的业务代码 │ emit ▼ 请求生命周期 → enrich补充字段→ tail sample尾部采样→ drain输出官方文档把扩展方式分成三类正好对应本文的3步你想做什么对应概念参考文档把日志发往没有内置适配器的后端自建drainCustom Drains 文档给每个事件加派生字段、响应生命周期事件写插件Plugins 文档让你的框架/运行时接入 evlog写框架适配器Custom Framework 文档好消息是这三样东西共享同一套工具包drain 和 enricher 本质上都是只选了一个钩子的插件所以学会了其中一件另外两件几乎零成本迁移。第1步自建 drain把宽事件发往任意后端drain是管线末端的一步接收宽事件并把它送到某处——HTTP API、消息队列、数据库、webhook、本地文件。evlog 已内置 Axiom、OTLP、Datadog、Sentry、PostHog、文件系统 等适配器如果你的目标平台不在列表里自己写一个只需两个纯函数。两个工厂函数覆盖所有场景你的目标后端使用HTTP 后端REST、JSON 摄取、厂商/v1/logs端点defineHttpDrain非 HTTP 传输gRPC、厂商 SDK、队列、原始 socketdefineDrain以内部 Loki 为例一个完整可运行的 drain 只有约 25 行import { defineHttpDrain } from evlog/toolkit export function createLokiDrain(overrides?: { url?: string, token?: string }) { return defineHttpDrain{ url: string, token: string }({ name: loki, resolve: () ({ url: overrides?.url ?? process.env.LOKI_URL!, token: overrides?.token ?? process.env.LOKI_TOKEN!, }), encode: (events, config) ({ url: ${config.url}/loki/api/v1/push, headers: { Content-Type: application/json, Authorization: Bearer ${config.token} }, body: JSON.stringify({ streams: events.map(e /* 转成 Loki 格式 */) }), }), }) }你只写两件事resolve()返回配置返回null则 drain 自动变 no-opencode()返回 HTTP 请求负载返回null表示本批跳过。重试默认2次、超时默认5000ms、错误隔离、身份头User-Agent: evlog/version和X-Evlog-Source全部由工厂自动处理不需要手写fetch。⚠️ 生产环境记得用createDrainPipeline包一层获得批量发送、失败重试和缓冲区保护——官方建议生产环境永远走 pipeline。第2步写一个插件挂入日志生命周期的任意环节当你要多件事一起干时比如每个事件加字段 事件发出时上报指标 按结果决定是否保留用definePlugin——evlog 的正规扩展点一个对象可以同时订阅多个生命周期钩子并共享状态import { definePlugin } from evlog export const tenantPlugin definePlugin({ name: tenant, onRequestStart({ logger, headers }) { const tenantId headers?.[x-tenant-id] if (tenantId) logger.set({ tenant: { id: tenantId } }) }, enrich({ event }) { event.region process.env.REGION }, })可用的钩子都是可选的按需取用钩子触发时机典型用途setup(ctx)注册时一次读取env、初始化共享状态onRequestStart(ctx)每个请求开始从请求头提取值写入 loggerenrich(ctx)每个事件发出前加派生字段地域、部署 IDkeep(ctx)尾部采样决策按结果强制保留status 400等drain(ctx)每个已发事件副作用告警、镜像到队列onRequestFinish(ctx)响应之后每请求的后处理extendLogger(logger)每个请求给 logger 增加自定义方法几个新手容易踩的坑钩子内部不要抛错保持防御式写法插件按name去重同名后注册覆盖前注册单一职责的扩展优先用工具包的drainPlugin()/enricherPlugin()简写读起来更直白。第3步为你的框架写适配器三行声明搞定如果你的框架还没有evlog/framework包自己接一个。工具包提供了与内置集成Hono、Express、Fastify、Elysia、NestJS完全相同的积木你只写框架特有的胶水代码。对于符合(ctx, next)中间件形状的 HTTP 框架用defineFrameworkIntegration声明式地写一个清单import { createLoggerStorage, defineFrameworkIntegration } from evlog/toolkit const { storage, useLogger } createLoggerStorage(...) const integration defineFrameworkIntegrationMyCtx({ name: my-framework, extractRequest: (ctx) ({ method, path, headers, requestId }), // ① 从哪读请求 attachLogger: (ctx, logger) { ctx.log logger }, // ② 把 logger 挂到哪 storage, }) export function evlog(options {}) { return async (ctx, next) { const { skipped, finish, runWith } integration.start(ctx, options) if (skipped) return next() await runWith(() next()) await finish({ status: ctx.status }) // ③ 响应结束后收尾 } }声明完路由过滤、drain 适配器、enricher、尾部采样、错误捕获、插件钩子、log.fork()、耗时统计全部免费获得。生命周期不贴合(ctx, next)的框架如拦截器模式可下沉到createMiddlewareLogger手写生命周期队列 worker、CLI、cron 这类非 HTTP 运行时则直接用createRequestLogger包住每个工作单元即可——enricher、drain 钩子和身份头依然全部生效。 参考实现就在仓库里直接照抄最快社区 drain 骨架完整契约 测试examples/community-adapter-skeleton/src/index.ts社区框架适配器骨架模拟一个MyFrameworkexamples/community-framework-skeleton/src/index.ts社区 enricher 骨架examples/community-enricher-skeleton/发布为社区包时记得把evlog声明为peerDependency而不是dependency避免用户安装时拉入第二份 evlog。常见问题drain 和插件有什么区别drain 只负责发出去是插件的一个特例插件可以订阅多个钩子并共享状态。单一目标用drainPlugin()包装即可。自建 drain 需要自己处理重试和超时吗不需要。defineHttpDrain默认重试2次、超时5000ms、错误隔离且目标宕机不影响业务管线继续运行。evlog/toolkit的 API 稳定吗官方标记为beta表面稳定所有内置集成都在用它但可能随社区反馈演化。总结evlog 的扩展设计非常统一drain、插件、框架适配器共享同一个工具包和同一套配置优先级显式 overrides →runtimeConfig→ 环境变量。掌握两个纯函数 声明式清单的心法你在半小时内就能让 evlog 接入任意后端、任意框架——这正是Digging through logs is not observability. Its hope. 之外的另一面让可扩展性成为默认值。延伸阅读扩展总览apps/docs/content/6.extend/0.overview.md自定义 drain 完整文档apps/docs/content/6.extend/8.custom-drains.md插件钩子详解apps/docs/content/6.extend/4.plugins.md框架适配器指南apps/docs/content/6.extend/10.custom-framework.md生产级 drain pipelineapps/docs/content/6.extend/9.drain-pipeline.md赞分享【免费下载链接】evlogDigging through logs is not observability. Its hope — wide events, structured errors, TypeScript-first, every runtime.项目地址https://gitcode.com/gh_mirrors/ev/evlog点击查看免费下载相关推荐Turbolinks自定义适配器开发扩展框架功能Turbolinks自定义适配器开发扩展框架功能 你是否在使用Turbolinks时遇到过这些问题默认进度条样式与应用风格不符需要在页面加载失败时执行自定前端StofDoctrineExtensionsBundle内部机制解析依赖注入和事件监听器的工作原理StofDoctrineExtensionsBundle内部机制解析依赖注入和事件监听器的工作原理 StofDoctrineExtensionsBundle是GrapesJS插件开发扩展框架功能的完整指南GrapesJS插件开发扩展框架功能的完整指南 本文深入探讨了GrapesJS插件系统的完整架构与开发实践。从核心的PluginManager设计理念出发详前端低代码UI组件创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Chat BI本地部署实战:Data Agent数据分析智能体全流程指南

Chat BI本地部署实战:Data Agent数据分析智能体全流程指南

【Data Agent】数据分析智能体初体验:可用的Chat BI本地部署全流程 Chat BI这个概念,这几年被反复提起,但真正敢在业务环境里用的并不多。大部分产品要么只能查固定报表,要么答案生成得天花乱坠但数字压根对不上。最近我花了几天…

2026/10/11 18:15:46 阅读更多 →
AI+HR智能体架构如何落地?从入口到生态底座的工程实现

AI+HR智能体架构如何落地?从入口到生态底座的工程实现

一、技术背景:从软件升级到架构跃迁 每一次企业软件的重大跃迁,改变的都不只是使用方式,更是企业运行的底层逻辑。今天,人工智能正在推动下一次更深层的变化:软件开始理解人的意图、感知企业的变化、参与业务决策&…

2026/10/11 18:15:46 阅读更多 →
OpenHarmony上Flutter歌单详情页开发实战:从页面拆解到音频播放

OpenHarmony上Flutter歌单详情页开发实战:从页面拆解到音频播放

在 OpenHarmony 设备上跑 Flutter 这件事,过去两年从我第一次调通环境到现在,身边问的人越来越多。坦白讲,这个组合早期多少带点“硬凑”的意味,但最近做音乐播放器项目的歌单详情模块时,我是真心觉得这套技术栈能干活…

2026/10/11 18:15:46 阅读更多 →

最新新闻

泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

泥石流滑坡目标检测数据集:YOLO+VOC双格式解析与YOLOv8训练避坑指南

简介:目标检测数据集聚焦泥石流与滑坡两类地质灾害场景,面向需要训练YOLO、Faster R-CNN等检测模型的算法工程师、研究生及防灾减灾研究人员。数据集以VOC与YOLO双格式组织,JPEGImages、Annotations、labels三个文件夹一一对应,共…

2026/10/11 20:37:23 阅读更多 →
Axure原型设计实战:组件对齐、动态面板与母版复用全解析

Axure原型设计实战:组件对齐、动态面板与母版复用全解析

简介:《Axure教程[汇编].pdf》是一份面向产品经理、UI/UX 设计师及软件开发人员的 Axure RP Pro 原型设计实战指南,内容结构完整,从基础操作到高级交互循序渐进。教程从新建项目、拖拽组件、编辑属性等基本操作讲起,逐步覆盖组件位…

2026/10/11 20:37:23 阅读更多 →
房屋租赁推荐系统

房屋租赁推荐系统

房屋租赁推荐系统选题背景与意义 随着城市化进程的不断加快以及人口流动性的显著提升,住房需求呈现出日益增长且结构复杂化的趋势。尤其是在一线及新一线城市,大量外来务工人员、高校毕业生以及年轻职场人士对短期或中长期住房租赁服务的需求持续攀升。传…

2026/10/11 20:37:23 阅读更多 →
基于VGG16的图像检索系统:毕业设计实战指南与避坑技巧

基于VGG16的图像检索系统:毕业设计实战指南与避坑技巧

简介:这份资源是一套基于VGG16的图像检索系统完整项目,面向深度学习入门者、图像处理方向学生及需要完成毕业设计的人群,帮助解决以图搜图场景下特征提取与相似度匹配的实现问题。项目使用Python与Keras搭建,涵盖图像预处理、VGG1…

2026/10/11 20:37:23 阅读更多 →
多前置仓模式下生鲜电商系统设计:库存、路由与履约实战

多前置仓模式下生鲜电商系统设计:库存、路由与履约实战

做生鲜电商的人应该都有体会:一个仓管不住,谈一百个仓就是灾难。万象生鲜系统走的是多前置仓模式,核心就是把库存压到离用户足够近的位置,用密度换时效。听起来不复杂,但真正落地时需要面对的是库存碎片化、订单路由、…

2026/10/11 20:37:23 阅读更多 →
LingBot-World 2.0源码结构全解读:wan目录如何把Wan2.2改造成因果世界模型

LingBot-World 2.0源码结构全解读:wan目录如何把Wan2.2改造成因果世界模型

【免费下载链接】lingbot-world-v2 Infinite Worlds with Versatile Interactions 项目地址: https://gitcode.com/gh_mirrors/li/lingbot-world-v2 点击查看 免费下载 LingBot-World 2.0(LingBot-World-Infinity) 是一款可无限交互的世界模…

2026/10/11 20:36:23 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

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

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

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

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

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

2026/10/11 14:36:54 阅读更多 →