const handleError = err => { this.emit('error', request, err); const { message, stack } = err; span.setTag(Tags.ERROR, true); span.log({ message, stack }); if (shouldWriteHead) { shouldWriteHead = false; let statusCode = 500; if (err.code === TEMPLATE_NOT_FOUND) { statusCode = 404; } span.setTag(Tags.HTTP_STATUS_CODE, statusCode); response.writeHead(statusCode, responseHeaders); // To render with custom error template if (typeof err.presentable === 'string') { response.end(`${err.presentable}`); } else { response.end(INTERNAL_SERVER_ERROR); } span.finish(); } else { contentLengthStream.end(); } }
span.setTag(Tags.HTTP_STATUS_CODE, 500); response.writeHead(500, responseHeaders); resultStream.pipe(contentLengthStream).pipe(response); span.addTags({ [Tags.ERROR]: true, [Tags.HTTP_STATUS_CODE]: 500 }); span.log({
it('should start and finish span with https', async () => { // WARNING: nock doesn't work well with https instrumentation // create real request await request('https://risingstack.com') expect(cls.startChildSpan).to.be.calledWith(tracer, instrumentation.OPERATION_NAME, { tags: { [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, [Tags.HTTP_URL]: 'https://risingstack.com:443/', [Tags.HTTP_METHOD]: 'GET' } }) expect(mockChildSpan.setTag).to.have.calledWith(Tags.HTTP_STATUS_CODE, 200) expect(mockChildSpan.finish).to.have.callCount(1) })
it('should start and finish span with http', async () => { nock('http://risingstack.com') .get('/foo') .reply(200) await request({ uri: 'http://risingstack.com/foo', query: { token: 'secret' } }) expect(cls.startChildSpan).to.be.calledWith(tracer, instrumentation.OPERATION_NAME, { tags: { [Tags.SPAN_KIND]: Tags.SPAN_KIND_RPC_CLIENT, [Tags.HTTP_URL]: 'http://risingstack.com:80/foo', [Tags.HTTP_METHOD]: 'GET' } }) expect(mockChildSpan.setTag).to.have.calledWith(Tags.HTTP_STATUS_CODE, 200) expect(mockChildSpan.finish).to.have.callCount(1) })
/** * Observe HTTP request metrics * @method _reportHttpRequestFinish * @private * @param {Span} span */ _reportHttpRequestFinish (span) { assert(span instanceof Span, 'span is required') this._metricshttpRequestDurationSeconds() .labels( PrometheusReporter.getParentService(span), span.getTag(Tags.HTTP_METHOD), span.getTag(Tags.HTTP_STATUS_CODE) ) .observe(span.duration() / 1000) }
it('should skip client HTTP requests', function () { // init const prometheusReporter = new PrometheusReporter() const httpRequestDurationSeconds = prometheusReporter._metricshttpRequestDurationSeconds() const metricsStub = { observe: this.sandbox.spy() } this.sandbox.stub(httpRequestDurationSeconds, 'labels').callsFake(() => metricsStub) // generate data const tracer = new Tracer('service') const span = tracer.startSpan('http_request') span.setTag(Tags.HTTP_METHOD, 'GET') span.setTag(Tags.HTTP_STATUS_CODE, 200) span.setTag(Tags.SPAN_KIND_RPC_SERVER, false) // or not set clock.tick(100) span.finish() prometheusReporter.reportFinish(span) // assert expect(httpRequestDurationSeconds.labels).to.have.callCount(0) expect(metricsStub.observe).to.have.callCount(0) })
requestSpan.setTag(Tags.HTTP_STATUS_CODE, 200) requestSpan.setTag(Tags.SPAN_KIND_RPC_CLIENT, true)
/** * Called by Tracer when a span is finished * @method reportFinish * @param {Span} span */ reportFinish (span) { assert(span instanceof Span, 'span is required') // Ignore by tag value const isIgnored = Object.entries(this._options.ignoreTags).some(([tagKey, regexp]) => { const tagValue = span.getTag(tagKey) return tagValue && tagValue.match(regexp) }) if (isIgnored) { return } // Operation metrics this._reportOperationFinish(span) // HTTP Request if (span.getTag(Tags.SPAN_KIND) === Tags.SPAN_KIND_RPC_SERVER && (span.getTag(Tags.HTTP_URL) || span.getTag(Tags.HTTP_METHOD) || span.getTag(Tags.HTTP_STATUS_CODE))) { this._reportHttpRequestFinish(span) } }
expect(mockSpan.setTag).to.be.calledWith(Tags.HTTP_STATUS_CODE, 200) expect(mockSpan.finish).to.have.callCount(1) }) .end() expect(mockSpan.setTag).to.be.calledWith(Tags.HTTP_STATUS_CODE, 400) expect(mockSpan.setTag).to.be.calledWith(Tags.ERROR, true) expect(mockSpan.finish).to.have.callCount(1)
spans.forEach((span) => span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode)) [Tags.HTTP_STATUS_CODE]: res.statusCode })
spans.forEach((span) => span.setTag(Tags.HTTP_STATUS_CODE, res.statusCode)) [Tags.HTTP_STATUS_CODE]: res.statusCode })
const span1 = tracer.startSpan('http_request', { childOf: parentSpan1 }) span1.setTag(Tags.HTTP_METHOD, 'GET') span1.setTag(Tags.HTTP_STATUS_CODE, 200) span1.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_SERVER) clock.tick(100) const span2 = tracer.startSpan('http_request', { childOf: parentSpan2 }) span2.setTag(Tags.HTTP_METHOD, 'POST') span2.setTag(Tags.HTTP_STATUS_CODE, 201) span2.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_SERVER) clock.tick(300)
expect(mockSpan.setTag).to.be.calledWith(Tags.HTTP_STATUS_CODE, 200) expect(mockSpan.finish).to.have.callCount(1) }) .end() expect(mockSpan.setTag).to.be.calledWith(Tags.HTTP_STATUS_CODE, 400) expect(mockSpan.setTag).to.be.calledWith(Tags.ERROR, true) expect(mockSpan.finish).to.have.callCount(1)
span1.setTag(Tags.HTTP_URL, 'http://127.0.0.1/foo') span1.setTag(Tags.HTTP_METHOD, 'GET') span1.setTag(Tags.HTTP_STATUS_CODE, 200) span1.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_SERVER) clock.tick(100) span2.setTag(Tags.HTTP_URL, 'http://127.0.0.1/bar') span2.setTag(Tags.HTTP_METHOD, 'GET') span2.setTag(Tags.HTTP_STATUS_CODE, 200) span2.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_SERVER) clock.tick(300)
span.setTag(Tags.HTTP_STATUS_CODE, 200) span.setTag(Tags.SPAN_KIND, Tags.SPAN_KIND_RPC_SERVER) clock.tick(100)