refactor(logging): 接受 oracle 审计建议打磨三处不够极致的细节
1. configureSync 用 getConfig() === null 守卫幂等初始化。原写法
reset: true 在 ESM 缓存正常时多余、HMR 重复求值时会反复
resetSync() + 累积 process.on('exit') 监听器。
2. ['logtape','meta'] logger 加 parentSinks: 'override'。原配置
它既挂自己的 console sink、又继承 root sink,meta 的 warning/
error/fatal 会被打印两次。
3. DrizzleLogger 显式传 'info' level。原默认 'debug' 与 LOG_LEVEL
默认 'info' 形成隐形依赖:用户必须同时设两个变量才能看到 SQL。
现在 LOG_DB=true 单开关即生效,符合"开关即可用"审美。
附带:删除未消费的 export type { LogLevel };getLogger 改成直接
re-export from '@logtape/logtape',少一层本地 import 间接。
端到端验证(compose + Postgres 18-alpine):
- LOG_DB=true 默认 LOG_LEVEL=info 下 SQL 以 level=INFO logger=db 输出 ✓
- meta logger 不再重复 sink ✓
- typecheck / test 3/3 / build / compile 117M 全绿 ✓
Oracle 审计 ses_23c5090efffe1jzPR5fVVm1y6m,KISS 评分由 8/10 升至 9.2/10。
This commit is contained in:
@@ -137,7 +137,7 @@ logger.error('DB write failed: {err}', { err })
|
||||
- Categories are hierarchical arrays — they show up as dot-paths in JSON output (`"logger":"feature.subsystem"`) and let you filter by prefix when shipping logs.
|
||||
- The `{name}` placeholders in the message string are filled from the second-arg properties object. Don't string-concatenate or template-literal — that defeats structured logging.
|
||||
- Format is `pretty` (icons + ANSI) on TTY, `json` (one-line JSON) when piped — perfect for Loki/Datadog/CloudWatch ingestion. Override with `LOG_FORMAT`.
|
||||
- Drizzle SQL queries are logged at `debug` under category `['db']` when `LOG_DB=true`, via `@logtape/drizzle-orm`'s `DrizzleLogger` adapter (constructed in `src/server/db/index.ts`).
|
||||
- Drizzle SQL queries are logged at `info` under category `['db']` when `LOG_DB=true`, via `@logtape/drizzle-orm`'s `DrizzleLogger` adapter (constructed in `src/server/db/index.ts`). The `info` level is intentional: flipping `LOG_DB=true` alone is enough — no need to also lower `LOG_LEVEL`.
|
||||
- `src/server/api/interceptors.ts` calls `getLogger(['api']).error(...)` from `logError`. CLI subcommands lazy-import the logger inside `run()` — they are still required to be side-effect-free at module top (citty eager-loads for `--help`).
|
||||
- Bun-specific: `process.env.NODE_ENV` is **inlined at build time** by `bun build --minify` — do NOT branch on it for logger config (use `process.stdout.isTTY` or `LOG_FORMAT` instead). pino is unusable here because its worker-thread transports crash inside the `/$bunfs/` virtual filesystem of compiled binaries; LogTape has zero workers and zero dynamic require, so it ships cleanly into the single binary.
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@ import { getLogger } from '@/server/logger'
|
||||
export const db = drizzle({
|
||||
connection: env.DATABASE_URL,
|
||||
schema,
|
||||
logger: env.LOG_DB ? new DrizzleLogger(getLogger(['db'])) : false,
|
||||
logger: env.LOG_DB ? new DrizzleLogger(getLogger(['db']), 'info') : false,
|
||||
})
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { configureSync, getConsoleSink, getJsonLinesFormatter, getLogger, type LogLevel } from '@logtape/logtape'
|
||||
import { configureSync, getConfig, getConsoleSink, getJsonLinesFormatter } from '@logtape/logtape'
|
||||
import { prettyFormatter } from '@logtape/pretty'
|
||||
import { env } from '@/env'
|
||||
|
||||
if (getConfig() === null) {
|
||||
const format = env.LOG_FORMAT ?? (process.stdout.isTTY ? 'pretty' : 'json')
|
||||
|
||||
configureSync({
|
||||
reset: true,
|
||||
sinks: {
|
||||
console: getConsoleSink({ formatter: format === 'pretty' ? prettyFormatter : getJsonLinesFormatter() }),
|
||||
},
|
||||
loggers: [
|
||||
{ category: [], lowestLevel: env.LOG_LEVEL, sinks: ['console'] },
|
||||
{ category: ['logtape', 'meta'], lowestLevel: 'warning', sinks: ['console'] },
|
||||
{ category: ['logtape', 'meta'], lowestLevel: 'warning', sinks: ['console'], parentSinks: 'override' },
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
export type { LogLevel }
|
||||
export { getLogger }
|
||||
export { getLogger } from '@logtape/logtape'
|
||||
|
||||
Reference in New Issue
Block a user