Skip to content

fix(langfuse): redact observation exports - #86

Open
XnLemon wants to merge 1 commit into
mainfrom
codex/phase2-langfuse-redaction
Open

fix(langfuse): redact observation exports#86
XnLemon wants to merge 1 commit into
mainfrom
codex/phase2-langfuse-redaction

Conversation

@XnLemon

@XnLemon XnLemon commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Objective

Close the Phase2 redaction gap where Langfuse observation input/output attributes could carry sensitive trace payloads.

Completed changes

  • Redacts Langfuse observation input/output values using the shared platform redactor before export.
  • Applies redaction before truncation and again after structured/fallback output generation so long secrets cannot leak via preserved head/tail fragments.
  • Covers invoke-agent, chat, tool, and workflow observation paths with secret redaction tests, including a long-token truncation regression case.

Validation

  • gofmt -w telemetry/langfuse/exporter.go telemetry/langfuse/exporter_test.go
  • go test ./telemetry/langfuse
  • go vet ./telemetry/langfuse
  • git diff --check
  • open-code-review subagent review: initially found 1 High issue around truncate-before-redact; fixed and re-reviewed clean at 0 High / 0 Medium / 0 Low. OCR CLI was installed, but LLM test was not configured, so strict manual review was used.

Risks / limitations

  • Observation export values may now be more aggressively masked if they contain strings matching the shared platform redaction rules.

Follow-up

  • Continue Phase2 closure with the next independently reviewable governance/security acceptance gap.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

English

  • Overview: Langfuse observation inputs and outputs are now processed through the shared platform redactor before export, including invoke-agent, chat/LLM, tool, and workflow paths. Redaction occurs before truncation and also covers structured and fallback serialization paths. Added tests verify secret masking and prevent long secrets from leaking through truncation.
  • Compatibility and behavioral risks: Exported observation values may be masked more aggressively when they match shared redaction rules. This can reduce debugging visibility, but preserves the existing export shape and public APIs. The key security requirement is to ensure every observation path—including fallback/error paths—continues to redact before truncation.
  • Recommended validation: Run formatting, Langfuse/package tests, go vet, and diff checks. Review coverage for structured JSON, fallback serialization, tool arguments, workflow request/response values, and long secrets to confirm neither full nor partial secret substrings are exported.
中文

中文

  • 变更概览: Langfuse 导出的 observation 输入和输出现在统一使用共享平台脱敏器处理,覆盖 invoke-agent、聊天/LLM、工具和工作流路径。脱敏在截断前执行,并覆盖结构化输出及回退序列化路径。新增测试验证秘密值会被遮盖,并防止长秘密通过截断逻辑泄漏。
  • 兼容性与行为风险: 匹配共享脱敏规则的 observation 值可能会被更严格地遮盖,从而降低部分调试信息可见性,但导出结构和公共 API 保持不变。需重点确认所有 observation 路径(包括回退和错误路径)都能在截断前完成脱敏。
  • 建议验证: 执行格式检查、Langfuse/相关包测试、go vet 和 diff 检查。重点验证结构化 JSON、回退序列化、工具参数、工作流请求/响应,以及长秘密场景,确保导出内容既不包含完整秘密,也不泄漏其头尾片段。

Walkthrough

Langfuse exporter observation values now use cached redaction across agent, LLM, tool, and workflow transformations. Truncation and fallback paths also redact values, with tests covering common secrets and long secret-bearing inputs.

Changes

Observation redaction

Layer / File(s) Summary
Redaction helpers and transformation entry points
telemetry/langfuse/exporter.go
Adds cached redaction helpers and routes agent and LLM observation attributes through them.
Redaction across truncation paths
telemetry/langfuse/exporter.go
Applies redaction across observation input, output, LLM input, JSON leaf, and fallback paths.
Tool and workflow wiring with redaction tests
telemetry/langfuse/exporter.go, telemetry/langfuse/exporter_test.go
Routes tool and workflow observations through redaction and verifies secret removal before and after truncation.

Estimated code review effort: 3 (Moderate) | ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly summarizes the Langfuse observation export redaction change.
Description check ✅ Passed Description matches the redaction-focused changes, validation, and follow-up scope in the diff.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/phase2-langfuse-redaction

Comment @coderabbitai help to get the list of available commands.

@XnLemon
XnLemon force-pushed the codex/phase2-trace-tieout branch from a47d369 to 83e8ed4 Compare July 11, 2026 13:38
@XnLemon
XnLemon force-pushed the codex/phase2-langfuse-redaction branch from bcb8d34 to f9ff772 Compare July 11, 2026 13:38
@XnLemon
XnLemon changed the base branch from codex/phase2-trace-tieout to main July 13, 2026 02:23
@XnLemon
XnLemon force-pushed the codex/phase2-langfuse-redaction branch from f9ff772 to cff3ba8 Compare July 13, 2026 02:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
telemetry/langfuse/exporter_test.go (1)

954-996: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Long-secret regression only covers the tool path.

The truncate-before-redact leak this test guards against also applies to truncateObservationInputMessages/truncateObservationOutputChoices (invoke-agent) and truncateObservationLLMInput (chat) — different helper functions than the truncateObservationJSONLeafValues path exercised here via transformExecuteTool. transformWorkflow shares the same helper so it's implicitly covered, but invoke-agent/chat are not.

中文 本测试防范的“先截断后脱敏导致泄露”问题同样存在于 `truncateObservationInputMessages`/`truncateObservationOutputChoices`(invoke-agent)以及 `truncateObservationLLMInput`(chat)中,这些是与本测试通过 `transformExecuteTool` 覆盖的 `truncateObservationJSONLeafValues` 不同的辅助函数。`transformWorkflow` 共用同一辅助函数,因此已被隐式覆盖,但 invoke-agent/chat 路径尚未被覆盖。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@telemetry/langfuse/exporter_test.go` around lines 954 - 996, Add regression
coverage for long-secret redaction before truncation in the invoke-agent and
chat paths, specifically exercising truncateObservationInputMessages,
truncateObservationOutputChoices, and truncateObservationLLMInput. Assert that
full secrets and representative prefixes/suffixes are absent after
transformation while the redaction marker remains, reusing the existing test
setup and helpers where applicable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@telemetry/langfuse/exporter.go`:
- Around line 162-166: Remove the redundant redaction performed when exporting
values already produced by otelObservationInput/otelObservationOutput and
buildLLMObservationInput/buildLLMObservationOutput. Update observationStringKV
or the affected exporter calls so these pre-truncated inputs and outputs are
converted to attributes without invoking the redactor a second time, while
preserving existing attribute construction.

---

Nitpick comments:
In `@telemetry/langfuse/exporter_test.go`:
- Around line 954-996: Add regression coverage for long-secret redaction before
truncation in the invoke-agent and chat paths, specifically exercising
truncateObservationInputMessages, truncateObservationOutputChoices, and
truncateObservationLLMInput. Assert that full secrets and representative
prefixes/suffixes are absent after transformation while the redaction marker
remains, reusing the existing test setup and helpers where applicable.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f2ce6f65-908b-4d0d-bb38-1f816afffee3

📥 Commits

Reviewing files that changed from the base of the PR and between 361e2a4 and cff3ba8.

📒 Files selected for processing (2)
  • telemetry/langfuse/exporter.go
  • telemetry/langfuse/exporter_test.go

Comment on lines +162 to 166
newAttributes = append(newAttributes, observationStringKV(observationInput, *input))
}
if output := otelObservationOutput(outputMessagesOTel); output != nil {
newAttributes = append(newAttributes, stringKV(observationOutput, *output))
newAttributes = append(newAttributes, observationStringKV(observationOutput, *output))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 Performance & Scalability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether otelObservationInput/otelObservationOutput/buildLLMObservationInput/buildLLMObservationOutput
# internally call the self-redacting truncate* helpers.
rg -n -A 15 'func otelObservationInput|func otelObservationOutput|func buildLLMObservationInput|func buildLLMObservationOutput' telemetry/langfuse/exporter.go

Repository: XnLemon/trpc-agent-go

Length of output: 1887


🏁 Script executed:

#!/bin/bash
# Inspect observationStringKV and the nearby transform helpers to see
# whether redaction happens again at the wrapper level.
rg -n -A 20 -B 5 'func observationStringKV|func transformExecuteTool|func transformWorkflow|truncateObservationInputMessages|truncateObservationOutputChoices|truncateObservationLLMInput|truncateObservationLLMResponse|truncateObservationJSONLeafValues' telemetry/langfuse/exporter.go

Repository: XnLemon/trpc-agent-go

Length of output: 11768


Avoid double redaction on the export hot path.
otelObservationInput/otelObservationOutput and buildLLMObservationInput/buildLLMObservationOutput already pass through the truncateObservation* helpers, and observationStringKV redacts again. That repeats the same redactor work for every exported observation.

中文 `otelObservationInput`/`otelObservationOutput` 以及 `buildLLMObservationInput`/`buildLLMObservationOutput` 已经经过 `truncateObservation*` 处理,而 `observationStringKV` 会再次脱敏。这样会让每个导出的 observation 重复执行同一套 redactor 工作。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@telemetry/langfuse/exporter.go` around lines 162 - 166, Remove the redundant
redaction performed when exporting values already produced by
otelObservationInput/otelObservationOutput and
buildLLMObservationInput/buildLLMObservationOutput. Update observationStringKV
or the affected exporter calls so these pre-truncated inputs and outputs are
converted to attributes without invoking the redactor a second time, while
preserving existing attribute construction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants