From 18e840fbda2081bf2f0c20a09079f7ef709ae248 Mon Sep 17 00:00:00 2001 From: William Conti <58711692+wconti27@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:26:37 -0500 Subject: [PATCH] tracing: fix http client synchronous errors causing spans to not finish (#5294) * ensure client http request span closes if request completely fails --- .../src/http/client.js | 5 +++++ packages/datadog-plugin-http/src/client.js | 4 +++- .../datadog-plugin-http/test/client.spec.js | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/datadog-instrumentations/src/http/client.js b/packages/datadog-instrumentations/src/http/client.js index 6ab01a34513..5afa47e5526 100644 --- a/packages/datadog-instrumentations/src/http/client.js +++ b/packages/datadog-instrumentations/src/http/client.js @@ -117,6 +117,11 @@ function patch (http, methodName) { } catch (e) { ctx.error = e errorChannel.publish(ctx) + // if the initial request failed, ctx.req will be unset, we must close the span here + // fix for: https://github.com/DataDog/dd-trace-js/issues/5016 + if (!ctx.req) { + finish() + } throw e } finally { endChannel.publish(ctx) diff --git a/packages/datadog-plugin-http/src/client.js b/packages/datadog-plugin-http/src/client.js index bf1e416e62f..94725ed95c8 100644 --- a/packages/datadog-plugin-http/src/client.js +++ b/packages/datadog-plugin-http/src/client.js @@ -102,7 +102,9 @@ class HttpClientPlugin extends ClientPlugin { addResponseHeaders(res, span, this.config) } - addRequestHeaders(req, span, this.config) + if (req) { + addRequestHeaders(req, span, this.config) + } this.config.hooks.request(span, req, res) diff --git a/packages/datadog-plugin-http/test/client.spec.js b/packages/datadog-plugin-http/test/client.spec.js index 73b2b949f62..6af6011b872 100644 --- a/packages/datadog-plugin-http/test/client.spec.js +++ b/packages/datadog-plugin-http/test/client.spec.js @@ -934,6 +934,24 @@ describe('Plugin', () => { }) }) } + + it('should record unfinished http requests as error spans', done => { + agent + .use(traces => { + expect(traces[0][0]).to.have.property('error', 1) + expect(traces[0][0].meta).to.not.have.property('http.status_code') + }) + .then(done) + .catch(done) + + try { + http.request('http://httpbin.org/get', { headers: { BadHeader: 'a\nb' } }, res => { + res.on('data', () => { }) + }) + } catch { + // expected to throw error + } + }) }) describe('with late plugin initialization and an external subscriber', () => {