这个坑值得记一笔。自建 Langfuse 3.x,用 OTLP HTTP exporter 上报,endpoint 写成 https://lf.example.com/api/public/otel/v1/traces,日志一直报 OTLP export failed 404。

刚开始盯着「反向代理丢掉了 Authorization 头」,折腾了半个多小时,排掉了。

真正麻烦的地方在于,几个原因的现象几乎一样。endpoint 不需要再拼 v1/traces;缺少 Basic Auth 的 key 对;误用了 gRPC 的 4317 端口。

动手时先用 curl 探测正确的上报路径

curl -s -o /dev/null -w '%{http_code}' -X POST https://lf.example.com/api/public/otel/v1/traces

随后把 endpoint 改成不带子路径的基地址

python -c "print('OTEL_EXPORTER_OTLP_ENDPOINT=https://lf.example.com/api/public/otel')"

补上 Basic Auth 头再发一次

python -c "print('Authorization: Basic base64(pk:sk)')"

剩下的就是在 Langfuse 里确认 trace 是否出现

python check_traces.py --since 10m

我习惯把每一步的执行时间和结果记在一边,后面复盘省事。

改之前我把相关日志按时间截了一段存着,事后对时间线用得上。

中途换过一次思路,把范围缩到最小的那一层,反而快了。

中间停过一次,把已经改的东西回滚干净,再重新来一遍。

别只看报错消失,验证要多做一步。exporter 不再报 404,Langfuse 里能看到新的 trace,span 数量和本地一致。

提醒一点。OTLP 的路径拼接规则由 exporter 决定,配置里通常只写基地址,多写一段就会 404,鉴权头也要单独确认。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189