diff --git a/packages/opentelemetry-plugin-http/src/utils.ts b/packages/opentelemetry-plugin-http/src/utils.ts index cfe8d9515e..1fb1cbdc99 100644 --- a/packages/opentelemetry-plugin-http/src/utils.ts +++ b/packages/opentelemetry-plugin-http/src/utils.ts @@ -217,6 +217,36 @@ export const setSpanWithError = ( span.setStatus(status); }; +/** + * + * @param headers + * @param Attributes + */ +export const setRequestContentLengthAttributes = ( + headers: OutgoingHttpHeaders | IncomingHttpHeaders, + attributes: Attributes +) => { + let isCompressed = false + + if (headers['content-encoding'] && headers['content-encoding'] !== 'identity') { + isCompressed = true + } + + if (isCompressed) { + if (headers as OutgoingHttpHeaders) { + attributes[HttpAttribute.HTTP_REQUEST_CONTENT_LENGTH] = headers['content-length'] + } else { + attributes[HttpAttribute.HTTP_RESPONSE_CONTENT_LENGTH] = headers['content-length'] + } + } else { + if (headers as OutgoingHttpHeaders) { + attributes[HttpAttribute.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED] = headers['content-length'] + } else { + attributes[HttpAttribute.HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED] = headers['content-length'] + } + } +}; + /** * Makes sure options is an url object * return an object with default value and parsed options @@ -356,14 +386,18 @@ export const getOutgoingRequestAttributesOnResponse = ( response: IncomingMessage, options: { hostname: string } ): Attributes => { - const { statusCode, statusMessage, httpVersion, socket } = response; + const { statusCode, statusMessage, httpVersion, headers, socket } = response; const { remoteAddress, remotePort } = socket; + + const attributes: Attributes = { [GeneralAttribute.NET_PEER_IP]: remoteAddress, [GeneralAttribute.NET_PEER_PORT]: remotePort, [HttpAttribute.HTTP_HOST]: `${options.hostname}:${remotePort}`, }; + // Place content-length func here? + if (statusCode) { attributes[HttpAttribute.HTTP_STATUS_CODE] = statusCode; attributes[HttpAttribute.HTTP_STATUS_TEXT] = ( @@ -424,6 +458,8 @@ export const getIncomingRequestAttributes = ( attributes[HttpAttribute.HTTP_USER_AGENT] = userAgent; } + // Place content-length func here? + const httpKindAttributes = getAttributesFromHttpKind(httpVersion); return Object.assign(attributes, httpKindAttributes); }; diff --git a/packages/opentelemetry-plugin-http/test/functionals/utils.test.ts b/packages/opentelemetry-plugin-http/test/functionals/utils.test.ts index e69d6b7252..9a290e551a 100644 --- a/packages/opentelemetry-plugin-http/test/functionals/utils.test.ts +++ b/packages/opentelemetry-plugin-http/test/functionals/utils.test.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { CanonicalCode, SpanKind, TraceFlags } from '@opentelemetry/api'; +import { Attributes, CanonicalCode, SpanKind, TraceFlags } from '@opentelemetry/api'; import { NoopLogger } from '@opentelemetry/core'; import { BasicTracerProvider, Span } from '@opentelemetry/tracing'; import { HttpAttribute } from '@opentelemetry/semantic-conventions'; @@ -309,4 +309,17 @@ describe('Utility', () => { assert.deepEqual(attributes[HttpAttribute.HTTP_ROUTE], undefined); }); }); + + describe('setRequestContentLengthAttributes', () => { + it('should set attributes', () => { + const attributes: Attributes = {} + let headers: http.OutgoingHttpHeaders = { + 'content-length': 1200 + } + + utils.setRequestContentLengthAttributes(headers, attributes) + + assert.strictEqual(attributes[HttpAttribute.HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED], 1200) + }) + }) }); diff --git a/packages/opentelemetry-semantic-conventions/src/trace/http.ts b/packages/opentelemetry-semantic-conventions/src/trace/http.ts index d54166c545..ae8e7e657b 100644 --- a/packages/opentelemetry-semantic-conventions/src/trace/http.ts +++ b/packages/opentelemetry-semantic-conventions/src/trace/http.ts @@ -26,6 +26,9 @@ export const HttpAttribute = { HTTP_CLIENT_IP: 'http.client_ip', HTTP_SCHEME: 'http.scheme', HTTP_RESPONSE_CONTENT_LENGTH: 'http.response_content_length', + HTTP_RESPONSE_CONTENT_LENGTH_UNCOMPRESSED: 'http.request_content_length_uncompressed', + HTTP_REQUEST_CONTENT_LENGTH: 'http.response_content_length', + HTTP_REQUEST_CONTENT_LENGTH_UNCOMPRESSED: 'http.request_content_length_uncompressed', // NOT ON OFFICIAL SPEC HTTP_ERROR_NAME: 'http.error_name',