mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
feat: 加上 userId 的传递
This commit is contained in:
@@ -29,6 +29,7 @@ const mockRootEnd = mock(() => {})
|
||||
// Mock LangfuseOtelSpanAttributes (re-exported from @langfuse/core)
|
||||
const mockLangfuseOtelSpanAttributes: Record<string, string> = {
|
||||
TRACE_SESSION_ID: 'session.id',
|
||||
TRACE_USER_ID: 'user.id',
|
||||
OBSERVATION_TYPE: 'observation.type',
|
||||
OBSERVATION_INPUT: 'observation.input',
|
||||
OBSERVATION_OUTPUT: 'observation.output',
|
||||
@@ -74,6 +75,14 @@ mock.module('src/utils/debug.js', () => ({
|
||||
logForDebugging: mock(() => {}),
|
||||
}))
|
||||
|
||||
// Mock user data — resolveLangfuseUserId uses getCoreUserData().email and .deviceId
|
||||
mock.module('src/utils/user.js', () => ({
|
||||
getCoreUserData: mock(() => ({
|
||||
email: 'test-device-id',
|
||||
deviceId: 'test-device-id',
|
||||
})),
|
||||
}))
|
||||
|
||||
describe('Langfuse integration', () => {
|
||||
beforeEach(() => {
|
||||
// Reset env
|
||||
@@ -477,6 +486,70 @@ describe('Langfuse integration', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('createTrace with username', () => {
|
||||
test('sets user.id attribute when username is provided', async () => {
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||
mockSetAttribute.mockClear()
|
||||
const { createTrace } = await import('../tracing.js')
|
||||
const span = createTrace({
|
||||
sessionId: 's1',
|
||||
model: 'claude-3',
|
||||
provider: 'firstParty',
|
||||
username: 'user@example.com',
|
||||
})
|
||||
expect(span).not.toBeNull()
|
||||
expect(mockSetAttribute).toHaveBeenCalledWith('user.id', 'user@example.com')
|
||||
})
|
||||
|
||||
test('falls back to LANGFUSE_USER_ID env when username not provided', async () => {
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||
process.env.LANGFUSE_USER_ID = 'env-user@test.com'
|
||||
mockSetAttribute.mockClear()
|
||||
const { createTrace } = await import('../tracing.js')
|
||||
const span = createTrace({
|
||||
sessionId: 's1',
|
||||
model: 'claude-3',
|
||||
provider: 'firstParty',
|
||||
})
|
||||
expect(span).not.toBeNull()
|
||||
expect(mockSetAttribute).toHaveBeenCalledWith('user.id', 'env-user@test.com')
|
||||
delete process.env.LANGFUSE_USER_ID
|
||||
})
|
||||
|
||||
test('falls back to deviceId when neither username nor env is provided', async () => {
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||
delete process.env.LANGFUSE_USER_ID
|
||||
mockSetAttribute.mockClear()
|
||||
const { createTrace } = await import('../tracing.js')
|
||||
createTrace({ sessionId: 's1', model: 'claude-3', provider: 'firstParty' })
|
||||
// Falls back to getCoreUserData().deviceId (mocked as 'test-device-id')
|
||||
expect(mockSetAttribute).toHaveBeenCalledWith('user.id', 'test-device-id')
|
||||
})
|
||||
|
||||
test('username takes precedence over LANGFUSE_USER_ID env', async () => {
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||
process.env.LANGFUSE_SECRET_KEY = 'sk-test'
|
||||
process.env.LANGFUSE_USER_ID = 'env-user@test.com'
|
||||
mockSetAttribute.mockClear()
|
||||
const { createTrace } = await import('../tracing.js')
|
||||
createTrace({
|
||||
sessionId: 's1',
|
||||
model: 'claude-3',
|
||||
provider: 'firstParty',
|
||||
username: 'param-user@test.com',
|
||||
})
|
||||
const userIdCalls = mockSetAttribute.mock.calls.filter(
|
||||
(call: unknown[]) => Array.isArray(call) && call[0] === 'user.id',
|
||||
)
|
||||
expect(userIdCalls.length).toBe(1)
|
||||
expect((userIdCalls[0] as unknown[])[1]).toBe('param-user@test.com')
|
||||
delete process.env.LANGFUSE_USER_ID
|
||||
})
|
||||
})
|
||||
|
||||
describe('nested agent scenario', () => {
|
||||
test('sub-agent trace shares sessionId with parent', async () => {
|
||||
process.env.LANGFUSE_PUBLIC_KEY = 'pk-test'
|
||||
|
||||
Reference in New Issue
Block a user