system.currenttimemillis() 是毫秒级绝对时间戳,用于日志排序、归档、耗时估算和可观测性;需在入口和finally块中采集start/end时间,避免日志中直接计算,配合traceid跨服务对齐,并与nanotime()明确分工。

System.currentTimeMillis() 在日志分析中不是用来测微秒级性能的,而是作为“时间锚点”——它提供稳定、可比、跨服务的毫秒级绝对时间戳,支撑排序、归档、耗时估算和基础可观测性。用对了场景,它轻量、高效、无需依赖;用错了,就会统计失真、排查困难。
记录请求全生命周期,覆盖所有执行路径
在 Web 接口或关键业务方法中,入口处记一次 start,出口(包括异常出口)再记一次 end,相减得耗时。重点不是“写了没”,而是“是否每条路径都覆盖”:
- 必须在 try 块开始前、业务逻辑真正执行前获取 start(比如参数校验之后、DB 操作之前)
- end 必须放在 finally 块里,确保即使抛异常也能采集到结束时间
- 避免在日志语句里直接拼接计算:logger.info("cost=" + (System.currentTimeMillis() - start)) —— 日志格式化本身有开销,会污染真实耗时
- 推荐写法:先算好 elapsed,再传入日志框架,如 log.info("req completed, cost={}ms", elapsed)
生成可排序、可查询的时间戳,用于日志归档与快速定位
它返回的是 Unix 时间戳(毫秒),天然支持数值排序和范围查询,是日志系统友好型时间表示:
- 文件命名:logs/app-20260612.log,内部每行日志开头带上 System.currentTimeMillis(),方便按时间切片和合并
- 跨服务对齐:配合 traceId 使用,虽不能精确到毫秒内顺序,但对秒级问题(如某服务延迟突增、超时集中发生)定位已足够可靠
- ELK 或数据库中建 timestamp 字段(BIGINT 类型),用 WHERE timestamp BETWEEN ? AND ? 快速筛选“过去5分钟所有 ERROR”,响应快、索引效率高
辅助识别长尾问题,但需结合分位统计而非平均值
单看平均耗时容易掩盖问题。真正有价值的是从大量 currentTimeMillis() 打点数据中提取 P95、P99 等分位值:
- 高频接口建议本地聚合:用 HdrHistogram 或滑动窗口在内存中实时计算,避免全量落盘压力
- 采样策略要保长尾:固定比例随机采样 + 超阈值强制采样(例如耗时 >1000ms 的请求 100% 记录)
- 发现负耗时或突增耗时,优先检查 NTP 同步状态、宿主机时钟偏移告警,而不是直接丢弃数据
明确与 nanoTime() 的分工,不混用、不错配
二者语义不同,混用会导致逻辑混乱或结果不可解释:
- 用 currentTimeMillis() 记录“事件发生时刻”:如订单创建时间、缓存写入时间、日志打印时间
- 用 nanoTime() 测量“代码执行间隔”:如 DAO 层 SQL 执行耗时、算法函数运行时间,结果只用于 JMH 报告或性能调优,不进业务日志
- 禁止用 nanoTime() 值做超时判断、写入数据库时间字段或参与业务逻辑(它没有业务时间语义)











