@ broberg/ logger (英语)
服务器登录 broberg.ai车队。 四级,一型,和 (单位:千美元) 在写出行前将像证书一样的证书进行编辑。 。 。 .
在依赖之前先读一下极限. 编辑是 模式- 基于(~38) 模式通过
@broberg/secret-scan: API 密钥,令牌,JWTs,连接 字符串——任何有可识别形状的东西. 没错 没有 按字段编辑 名称。 测量,在公布的0.1.0:{ token: "sk-proj-AbCd…" } → "token": "[REDACTED:openai-api-key]" { gh: "ghp_AbCd…" } → "gh": "[REDACTED:github-token]" { auth: "Bearer eyJ…" } → "auth": "Bearer [REDACTED:jwt]" { password: "hemmelig123" } → "password": "hemmelig123" ← NOT redacted { apiKey: "kort" } → "apiKey": "kort" ← NOT redacted一个用户密码,一个PIN,一个国家ID——任何唯一标志是关键的东西 它坐落在下面 直接穿过. 不登录请求正文和 假设这个抓住它. 键名编辑被跟踪为空白; 直到它 船,选择你记录的田地.
该段将“一个秘密无法到达日志”改为“一个秘密无法到达日志” 意外,它承诺 超过机制提供。 一个保证是 确切地说,为什么有人停止检查, 所以一个过度的描述比没有更糟糕.
npm i @broberg/logger
import { createLogger } from "@broberg/logger";
const log = createLogger({ name: "discovery", pretty: process.env.NODE_ENV !== "production" });
log.info("served", { route: "/api/search", ms: 12 });
log.error(err, { route: "/api/search" });
const reqLog = log.child({ requestId }); // on every line, nests
为什么会这样
没错 没有 一个包裹周围 console.log 这将是200行
什么都没有,你应该只是使用 console。有两点可以证明一个包:
- 默认重排 . 每个消息和每个元数据值都运行
结束
@broberg/secret-scan在它离开之前 进程。 API 密钥粘贴到调试行、 查询字符串中的符号、 并authorization信头在请求的垃圾堆中深陷了三层——没有 他们到达了stdout. - 每个应用程序都有一个形状,所以一条行是可搜索的,无论哪条 计划释放出来.
如果一个变化对两者都不利,它不属于这里.
这不是另外两个日志形状的软件包
| 软件包 | 答复 |
|---|---|
@broberg/logger | 服务器在做什么? |
@broberg/event-log | 谁干的? (GDPR审计线索,业务活动) |
@upmetrics/sdk | 什么断了? (crashes,错误分组) |
API 密码
createLogger(options) → { debug, info, warn, error, child, level }
| 选项 | 默认 | |
|---|---|---|
name | – 说吧 – | 服务名称, 每行 |
level | LOG_LEVEL,则 info | 明确选项 击出 LOG_LEVEL |
pretty | false | false =单行JSON, true = 可读文本 |
redact | true | 在关闭前查看下方成本 |
sink | console | 完成线去的地方(可注入测试) |
bindings | {} | 字段合并到每行 |
now | Date | 可注射时钟 |
级别为 debug < info < warn < error没有 trace 或者说 fatal: 4个
足够了,每个额外的关卡 是一个决定 每个消费者然后必须做出.
warn编号 :error 去stderr,其余的去stdout.
log.error(err) 序列化一个 Error 作为 { name, message, stack } 从来没有
{}。在地上嵌入的错误也会被序列化 .
按字段名称调整(自0.3.0起,F063.2起)
模式的通过通过承认证书 形状 (单位:千美元) sk-… 键, a ghp_… (原始内容存档于2017-10-21). Sorry, a JWT. 一个用户的密码,一个PIN或一个CPR号码没有形状——用已公布的0.1.0来测量, {password:'hemmelig123'} 财务报告和审定财务报表 {apiKey:'kort'} 出场了 因此,现在的日志器 也编辑 字段名称无论价值如何
log.info("login", { user: { name: "ane", password: "hemmelig123" } });
// → {"…","user":{"name":"ane","password":"[REDACTED:field]"}}
- 默认列表 (单位:千美元)
DEFAULT_REDACT_KEYS:password, (中文(简体) ),passwd, (中文(简体) ),pwd, (中文(简体) ),passphrase, (中文(简体) ),pin, (中文(简体) ),cpr, (中文(简体) ),cprnr, (中文(简体) ),ssn, (中文(简体) ),secret, (中文(简体) ),clientSecret, (中文(简体) ),privateKey, (中文(简体) ),authorization, (中文(简体) ),cookie, (中文(简体) ),set-cookie, (中文(简体) ),apiKey, (中文(简体) ),x-api-key, (中文(简体) ),accessToken, (中文(简体) ),refreshToken, (中文(简体) ),idToken。 。 。 . - 对大小写和分隔符不敏感数字 :
apiKey, (中文(简体) ),api_key, (中文(简体) ),API-KEY是一个条目.Authorization被捕获为authorization。 。 。 . - 任何深度和孩子的束缚 (单位:千美元)
log.child({ apiKey })) (中文(简体) ). - 伸开它 带有一个选项——默认保留:
createLogger({ redactKeys: ["memberNumber"] })(那时)member_number还被抓住了). - 两张通行证都运行. 字段名称先取出,再取出序列行上~38图案. 一个不在名单上并且没有秘密形状的字段是逐字记录的——
passwordChangedAt没有password。 。 。 . redact: false关掉两个.
校正费用——计量的,未断言
红外线在每条序列线上运行 ~38 regex. 运行 npm run bench
在M1上,50 000个电话 与水槽丢弃:
redact: false 1.36 µs/call 733,000 calls/s
redact: true (default) 7.79 µs/call 128,000 calls/s
overhead: 6.4 µs/call (≈5.7× the un-redacted path)
字段名传 (0. 3. 0) , 测量为一台机器上相接的 A/ B
(cb-2,英特尔i5-7360) U 载重,2026年10月30日;新旧 dist 3个
负载击出两个:
0.2.3 (patterns only) 0.3.0 (field names + patterns)
redact: true 208–247 µs/call 239–260 µs/call
++10% (++20 μs) 在被修改的通话中. 机器上的绝对数字是 与上述M1表不相上下 ——同一张长椅测量出图案通过 8月在M1上为-230 μs对7.8 μs。 M1数字没有 从那时起就重新计量了 把它们当作八月的 而不是现在.
老实说 编辑是 日志调用的主要成本,这是
仍为128000行/秒——远远超过本舰队的任何应用产品. 转弯
它关闭 redact: false 除非你有一条有分寸的热路
决定线路不能携带证书。 号码在这里,所以这是一个
决定,不是猜测.
浩诺
import { requestLogger, errorLogger } from "@broberg/logger/hono";
app.use("*", requestLogger(log, { skip: (c) => c.req.path === "/health" }));
app.onError(errorLogger(log)); // <- do not skip this, see below
每个请求一行: method, (中文(简体) ), path, (中文(简体) ), status, (中文(简体) ), ms, (中文(简体) ), requestId级别
遵循状态( 5xx → 错误, 4xx ) 。 请求编号被取出
从收到的 x-request-id 如果打电话者发出了一个,以其他方式生成
反应回放 处理器得到一个请求范围的儿童记录器
打开 c.get("log"),所以它记录的一切 与它的要求有关.
requestLogger一个人不能告诉你为什么发生了500起. 胡诺捕到一 自己抛出处理器,变成500个反应,所以await next()平时解决,例外从未到达中间软件——你得到status: 500没有原因. 线errorLogger作为app.onError登录 以请求 ID 连接。 这个限制是 在测试套房里说 所以不能悄悄忘记它.
hono 是可选的对等点——只导入 /hono 把它拉进来.
保证
- 从来投出. 一个被打碎的水槽 一个圆形的参考物 一个物体
toJSON抛出——都吞下. 这在每一个应用程序的要求路径中, 和一个伐木工崩溃 请求严格比没有伐木者, 因为应用在你增加可观察性之前就起作用了. pretty: false发出一行有效的 JSON 每个呼叫.
非目标
没有运输、旋转、缓冲、取样或聚合。 楼梯是 合同;平台收集。 如果你发现自己加入了其中之一, 这是错的包裹.