Skip to content

Commit e5cb670

Browse files
sabrennerbengl
authored andcommitted
fix(llmobs): llmobs data can be sent to agent proxy running on uds (#5679)
* pass path separately for request options * remove comment
1 parent 8a12aee commit e5cb670

File tree

4 files changed

+75
-24
lines changed

4 files changed

+75
-24
lines changed

packages/dd-trace/src/llmobs/writers/base.js

+33-12
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,18 @@ class BaseLLMObsWriter {
4141
this._destroyed = false
4242
}
4343

44+
get url () {
45+
if (this._agentless == null) return null
46+
47+
const baseUrl = this._baseUrl.href
48+
const endpoint = this._endpoint
49+
50+
// Split on protocol separator to preserve it
51+
// path.join will remove some slashes unnecessarily
52+
const [protocol, rest] = baseUrl.split('://')
53+
return protocol + '://' + path.join(rest, endpoint)
54+
}
55+
4456
append (event, byteLength) {
4557
if (this._buffer.length >= this._bufferLimit) {
4658
logger.warn(`${this.constructor.name} event buffer full (limit is ${this._bufferLimit}), dropping event`)
@@ -69,7 +81,7 @@ class BaseLLMObsWriter {
6981
const options = this._getOptions()
7082

7183
request(payload, options, (err, resp, code) => {
72-
parseResponseAndLog(err, code, events.length, options.url.href, this._eventType)
84+
parseResponseAndLog(err, code, events.length, this.url, this._eventType)
7385
})
7486
}
7587

@@ -87,17 +99,23 @@ class BaseLLMObsWriter {
8799

88100
setAgentless (agentless) {
89101
this._agentless = agentless
90-
this._url = this._getUrl()
91-
logger.debug(`Configuring ${this.constructor.name} to ${this._url.href}`)
102+
const { url, endpoint } = this._getUrlAndPath()
103+
104+
this._baseUrl = url
105+
this._endpoint = endpoint
106+
107+
logger.debug(`Configuring ${this.constructor.name} to ${this.url}`)
92108
}
93109

94-
_getUrl () {
110+
_getUrlAndPath () {
95111
if (this._agentless) {
96-
return new URL(format({
97-
protocol: 'https:',
98-
hostname: `${this._intake}.${this._config.site}`,
99-
pathname: this._endpoint
100-
}))
112+
return {
113+
url: new URL(format({
114+
protocol: 'https:',
115+
hostname: `${this._intake}.${this._config.site}`
116+
})),
117+
endpoint: this._endpoint
118+
}
101119
}
102120

103121
const { hostname, port } = this._config
@@ -107,8 +125,10 @@ class BaseLLMObsWriter {
107125
port
108126
}))
109127

110-
const proxyPath = path.join(EVP_PROXY_AGENT_BASE_PATH, this._endpoint)
111-
return new URL(proxyPath, base)
128+
return {
129+
url: base,
130+
endpoint: path.join(EVP_PROXY_AGENT_BASE_PATH, this._endpoint)
131+
}
112132
}
113133

114134
_getOptions () {
@@ -118,7 +138,8 @@ class BaseLLMObsWriter {
118138
},
119139
method: 'POST',
120140
timeout: this._timeout,
121-
url: this._url
141+
url: this._baseUrl,
142+
path: this._endpoint
122143
}
123144

124145
if (this._agentless) {

packages/dd-trace/test/llmobs/writers/base.spec.js

+38-8
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ describe('BaseLLMObsWriter', () => {
4949
writer.setAgentless(true)
5050

5151
expect(writer._agentless).to.be.true
52-
expect(writer._url.href).to.equal('https://intake.site.com/endpoint')
52+
expect(writer.url).to.equal('https://intake.site.com/endpoint')
5353
})
5454

5555
it('constructs an agent proxy writer', () => {
5656
writer = new BaseLLMObsWriter(options)
5757
writer.setAgentless(false)
5858

5959
expect(writer._agentless).to.be.false
60-
expect(writer._url.href).to.equal('http://localhost:8126/evp_proxy/v2/endpoint')
60+
expect(writer.url).to.equal('http://localhost:8126/evp_proxy/v2/endpoint')
6161
})
6262

6363
describe('with config url', () => {
@@ -73,7 +73,37 @@ describe('BaseLLMObsWriter', () => {
7373
writer = new BaseLLMObsWriter(options)
7474
writer.setAgentless(false)
7575

76-
expect(writer._url.href).to.equal('http://test-agent:12345/evp_proxy/v2/endpoint')
76+
expect(writer.url).to.equal('http://test-agent:12345/evp_proxy/v2/endpoint')
77+
})
78+
})
79+
80+
describe('with unix socket', () => {
81+
beforeEach(() => {
82+
options.config.url = new URL('unix:///var/run/datadog/apm.socket/')
83+
})
84+
85+
afterEach(() => {
86+
delete options.config.url
87+
})
88+
89+
it('constructs a writer with the correct url', () => {
90+
writer = new BaseLLMObsWriter(options)
91+
writer.setAgentless(false)
92+
93+
expect(writer.url).to.equal('unix:///var/run/datadog/apm.socket/evp_proxy/v2/endpoint')
94+
})
95+
96+
it('makes the request with the correct options', () => {
97+
writer = new BaseLLMObsWriter(options)
98+
writer.setAgentless(false)
99+
writer.makePayload = (events) => ({ events })
100+
101+
writer.append({ foo: 'bar' })
102+
writer.flush()
103+
104+
const requestOptions = request.getCall(0).args[1]
105+
expect(requestOptions.url.href).to.equal('unix:///var/run/datadog/apm.socket/')
106+
expect(requestOptions.path).to.equal('/evp_proxy/v2/endpoint')
77107
})
78108
})
79109

@@ -134,7 +164,8 @@ describe('BaseLLMObsWriter', () => {
134164
writer.flush()
135165

136166
const requestOptions = request.getCall(0).args[1]
137-
expect(requestOptions.url.href).to.equal('https://intake.site.com/endpoint')
167+
expect(requestOptions.url.href).to.equal('https://intake.site.com/')
168+
expect(requestOptions.path).to.equal('/endpoint')
138169
expect(requestOptions.headers['Content-Type']).to.equal('application/json')
139170
expect(requestOptions.headers['DD-API-KEY']).to.equal('test')
140171
})
@@ -148,7 +179,8 @@ describe('BaseLLMObsWriter', () => {
148179
writer.flush()
149180

150181
const requestOptions = request.getCall(0).args[1]
151-
expect(requestOptions.url.href).to.equal('http://localhost:8126/evp_proxy/v2/endpoint')
182+
expect(requestOptions.url.href).to.equal('http://localhost:8126/')
183+
expect(requestOptions.path).to.equal('/evp_proxy/v2/endpoint')
152184
expect(requestOptions.headers['Content-Type']).to.equal('application/json')
153185
expect(requestOptions.headers['X-Datadog-EVP-Subdomain']).to.equal('intake')
154186
})
@@ -188,16 +220,14 @@ describe('BaseLLMObsWriter', () => {
188220
writer.append({ foo: 'bar' })
189221

190222
const error = new Error('boom')
191-
let reqUrl
192223
request.callsFake((url, options, callback) => {
193-
reqUrl = options.url.href
194224
callback(error)
195225
})
196226

197227
writer.flush()
198228

199229
expect(logger.error).to.have.been.calledWith(
200-
'Error sending %d LLMObs %s events to %s: %s', 1, undefined, reqUrl, 'boom', error
230+
'Error sending %d LLMObs %s events to %s: %s', 1, undefined, 'https://intake.site.com/endpoint', 'boom', error
201231
)
202232
})
203233

packages/dd-trace/test/llmobs/writers/evaluations.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ describe('LLMObsEvalMetricsWriter', () => {
2222

2323
writer.flush = flush // just to stop the beforeExit flush call
2424

25-
expect(writer._url.href).to.equal('https://api.datadoghq.com/api/intake/llm-obs/v1/eval-metric')
25+
expect(writer.url).to.equal('https://api.datadoghq.com/api/intake/llm-obs/v1/eval-metric')
2626
expect(writer._eventType).to.equal('evaluation_metric')
2727
})
2828

@@ -32,7 +32,7 @@ describe('LLMObsEvalMetricsWriter', () => {
3232
hostname: 'localhost'
3333
})
3434
writer.setAgentless(false)
35-
expect(writer._url.href).to.equal('http://localhost:8126/evp_proxy/v2/api/intake/llm-obs/v1/eval-metric')
35+
expect(writer.url).to.equal('http://localhost:8126/evp_proxy/v2/api/intake/llm-obs/v1/eval-metric')
3636
expect(writer._eventType).to.equal('evaluation_metric')
3737
})
3838

packages/dd-trace/test/llmobs/writers/spans.spec.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ describe('LLMObsSpanWriter', () => {
3737
writer = new LLMObsSpanWriter(config)
3838
writer.setAgentless(true)
3939
expect(writer._agentless).to.equal(true)
40-
expect(writer._url.href).to.equal('https://llmobs-intake.datadoghq.com/api/v2/llmobs')
40+
expect(writer.url).to.equal('https://llmobs-intake.datadoghq.com/api/v2/llmobs')
4141
})
4242

4343
it('creates an agent proxy writer', () => {
4444
writer = new LLMObsSpanWriter(config)
4545
writer.setAgentless(false)
4646

4747
expect(writer._agentless).to.equal(false)
48-
expect(writer._url.href).to.equal('http://localhost:8126/evp_proxy/v2/api/v2/llmobs')
48+
expect(writer.url).to.equal('http://localhost:8126/evp_proxy/v2/api/v2/llmobs')
4949
})
5050

5151
it('computes the number of bytes of the appended event', () => {

0 commit comments

Comments
 (0)