Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update OTEL packages #1367

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .changeset/dull-bees-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
"@saleor/apps-logger": patch
"app-avatax": patch
"cms-v2": patch
"crm": patch
"data-importer": patch
"emails-and-messages": patch
"invoices": patch
"klaviyo": patch
"products-feed": patch
"search": patch
"segment": patch
"slack": patch
"smtp": patch
"app-taxjar": patch
---

Updated Open Telemetry SDK and API to latest versions
1 change: 1 addition & 0 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"**/schema.graphql",
"**/*-generator.ts",
"apps/*/src/**",
"packages/*/src/**",
"apps/*/e2e/data/**",
"**/*.bru",
"**/.eslintrc",
Expand Down
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@
"test": "turbo run test"
},
"dependencies": {
"@opentelemetry/api": "1.7.0",
"@opentelemetry/api-logs": "0.46.0",
"@opentelemetry/core": "1.19.0",
"@opentelemetry/exporter-logs-otlp-http": "0.46.0",
"@opentelemetry/exporter-trace-otlp-http": "0.46.0",
"@opentelemetry/instrumentation-http": "0.46.0",
"@opentelemetry/instrumentation-winston": "0.33.1",
"@opentelemetry/resources": "1.18.1",
"@opentelemetry/sdk-logs": "0.45.1",
"@opentelemetry/sdk-node": "0.45.1",
"@opentelemetry/sdk-trace-base": "1.18.1",
"@opentelemetry/sdk-trace-node": "1.18.1",
"@opentelemetry/semantic-conventions": "1.18.1",
"@opentelemetry/api": "1.8.0",
"@opentelemetry/api-logs": "0.51.1",
"@opentelemetry/core": "1.24.1",
"@opentelemetry/exporter-logs-otlp-http": "0.51.1",
"@opentelemetry/exporter-trace-otlp-http": "0.51.1",
"@opentelemetry/instrumentation-http": "0.51.1",
"@opentelemetry/instrumentation-winston": "0.37.0",
"@opentelemetry/resources": "1.24.1",
"@opentelemetry/sdk-logs": "0.51.1",
"@opentelemetry/sdk-node": "0.51.1",
"@opentelemetry/sdk-trace-base": "1.24.1",
"@opentelemetry/sdk-trace-node": "1.24.1",
"@opentelemetry/semantic-conventions": "1.24.1",
"@saleor/app-sdk": "0.50.1"
},
"devDependencies": {
Expand Down
41 changes: 21 additions & 20 deletions packages/logger/src/logger-otel-transport.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { context } from "@opentelemetry/api";
import { LogAttributeValue, logs } from "@opentelemetry/api-logs";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { logs } from "@opentelemetry/api-logs";
import {
SEMRESATTRS_SERVICE_NAME,
SEMRESATTRS_SERVICE_VERSION,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
} from "@opentelemetry/semantic-conventions";
import { ILogObj, Logger } from "tslog";
import { LoggerContext } from "./logger-context";
import { LogAttributes } from "@opentelemetry/api-logs/build/src/types/LogRecord";

export const attachLoggerOtelTransport = (
logger: Logger<ILogObj>,
Expand All @@ -27,19 +32,16 @@ export const attachLoggerOtelTransport = (
const serializedAttributes = Object.entries({
...(loggerContext?.getRawContext() ?? {}),
...attributes,
}).reduce(
(acc, [key, value]) => {
if (Array.isArray(value)) {
acc[key] = JSON.stringify(value);
} else {
// @ts-expect-error - Logger maps attribute as IMeta, but in the runtime Meta is only in log._meta field which is filtered out first
acc[key] = value;
}
}).reduce((acc, [key, value]) => {
if (Array.isArray(value)) {
acc[key] = JSON.stringify(value);
} else {
// @ts-expect-error - Logger maps attribute as IMeta, but in the runtime Meta is only in log._meta field which is filtered out first
acc[key] = value;
}

return acc;
},
{} as Record<string, LogAttributeValue>,
);
return acc;
}, {} as LogAttributes);

/**
* Try to serialize Error. Modern-errors has plugin to serialize
Expand All @@ -52,27 +54,26 @@ export const attachLoggerOtelTransport = (
*/
try {
const errorAttribute = serializedAttributes.error;
const ErrorConstructor = errorAttribute["constructor"];
const ErrorConstructor = errorAttribute!["constructor"];

// @ts-expect-error - ErrorConstructor is a class that could have serialize method. If not, safely throw and ignore
serializedAttributes.error = ErrorConstructor.serialize(serializedAttributes.error);
// @ts-expect-error - Additional mapping for Datadog
serializedAttributes.error.type = serializedAttributes.error.name;
} catch (e) {}

logs.getLogger("app-logger-otel").emit({
return logs.getLogger("app-logger-otel").emit({
body: log._meta.name ? `[${log._meta.name}] ${message}` : message,
context: context.active(),
severityText: log._meta.logLevelName,
attributes: {
...serializedAttributes,
// eslint-disable-next-line turbo/no-undeclared-env-vars
[SemanticResourceAttributes.SERVICE_NAME]: process.env.OTEL_SERVICE_NAME,
[SemanticResourceAttributes.SERVICE_VERSION]: appVersion,
[SEMRESATTRS_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME,
[SEMRESATTRS_SERVICE_VERSION]: appVersion,
// eslint-disable-next-line turbo/no-undeclared-env-vars
["commit-sha"]: process.env.VERCEL_GIT_COMMIT_SHA,
// eslint-disable-next-line turbo/no-undeclared-env-vars
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.ENV,
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: process.env.ENV,
},
});
});
Expand Down
20 changes: 13 additions & 7 deletions packages/otel/src/get-attributes-from-request.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { NextApiRequest } from "next";
import { SemanticAttributes } from "@opentelemetry/semantic-conventions";
import {
SEMATTRS_FAAS_EXECUTION,
SEMATTRS_HTTP_METHOD,
SEMATTRS_HTTP_TARGET,
SEMATTRS_HTTP_USER_AGENT,
SEMATTRS_NET_HOST_NAME,
} from "@opentelemetry/semantic-conventions";
import { SALEOR_API_URL_HEADER } from "@saleor/app-sdk/const";

const pruneEmptyKeys = (obj: Record<string, unknown>): Record<string, string> => {
Expand All @@ -18,16 +24,16 @@ const pruneEmptyKeys = (obj: Record<string, unknown>): Record<string, string> =>

export const getAttributesFromRequest = (request: NextApiRequest) => {
const attributes = {
[SemanticAttributes.FAAS_EXECUTION]: request.headers["x-vercel-proxy-signature-ts"] as string,
[SemanticAttributes.HTTP_USER_AGENT]: request.headers["user-agent"] as string,
[SemanticAttributes.HTTP_TARGET]: request.headers.referer as string,
[SemanticAttributes.NET_HOST_NAME]: request.headers.host as string,
[SemanticAttributes.HTTP_METHOD]: (request.method ?? "").toUpperCase(),
[SEMATTRS_FAAS_EXECUTION]: request.headers["x-vercel-proxy-signature-ts"] as string,
[SEMATTRS_HTTP_USER_AGENT]: request.headers["user-agent"] as string,
[SEMATTRS_HTTP_TARGET]: request.headers.referer as string,
[SEMATTRS_NET_HOST_NAME]: request.headers.host as string,
[SEMATTRS_HTTP_METHOD]: (request.method ?? "").toUpperCase(),
saleorApiUrl: request.headers[SALEOR_API_URL_HEADER] as string,
"url.path": request.url,
vercelRequestId: request.headers["x-vercel-id"],
requestId: request.headers["x-vercel-proxy-signature-ts"] as string,
} as const ;
} as const;

return pruneEmptyKeys(attributes);
};
19 changes: 11 additions & 8 deletions packages/otel/src/instrumentation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { Resource } from "@opentelemetry/resources";
import { NodeSDK } from "@opentelemetry/sdk-node";
import {
SemanticAttributes,
SemanticResourceAttributes,
SEMRESATTRS_SERVICE_NAME,
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
SEMATTRS_HTTP_ROUTE,
SEMATTRS_HTTP_STATUS_CODE,
SEMATTRS_HTTP_HOST,
} from "@opentelemetry/semantic-conventions";
import { type ClientRequest } from "node:http";
import { otelLogsProcessor } from "./otel-logs-setup";
Expand All @@ -18,14 +21,14 @@ if (process.env.ENABLE_DEBUG_OTEL_DIAG === "true") {
export const otelSdk = new NodeSDK({
resource: new Resource({
// eslint-disable-next-line turbo/no-undeclared-env-vars
[SemanticResourceAttributes.SERVICE_NAME]: process.env.OTEL_SERVICE_NAME,
[SEMRESATTRS_SERVICE_NAME]: process.env.OTEL_SERVICE_NAME,
// [SemanticResourceAttributes.SERVICE_VERSION]: pkg.version, TODO
// eslint-disable-next-line turbo/no-undeclared-env-vars
"commit-sha": process.env.VERCEL_GIT_COMMIT_SHA,
// eslint-disable-next-line turbo/no-undeclared-env-vars
[SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: process.env.ENV,
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: process.env.ENV,
}),
spanProcessor: batchSpanProcessor,
spanProcessors: [batchSpanProcessor],
logRecordProcessor: otelLogsProcessor,
textMapPropagator: new W3CTraceContextPropagator(),
instrumentations: [
Expand All @@ -37,11 +40,11 @@ export const otelSdk = new NodeSDK({
* TODO Fix this.
*/
applyCustomAttributesOnSpan: (span, req, response) => {
span.setAttribute(SemanticAttributes.HTTP_ROUTE, (req as ClientRequest)?.path);
span.setAttribute(SemanticAttributes.HTTP_HOST, (req as ClientRequest)?.host);
span.setAttribute(SEMATTRS_HTTP_ROUTE, (req as ClientRequest)?.path);
span.setAttribute(SEMATTRS_HTTP_HOST, (req as ClientRequest)?.host);

if (response.statusCode) {
span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, response.statusCode);
span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, response.statusCode);
}

if (response.statusCode && response.statusCode >= 400) {
Expand Down
4 changes: 2 additions & 2 deletions packages/otel/src/otel-exchange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type CombinedError, type Operation, makeOperation, mapExchange } from "
import { getOtelTracer } from "./otel-tracer";
import { GraphQLAttributeNames, ObservabilityAttributes } from "./lib/observability-attributes";
import { addInputVariableAttributes, addRequestHeaderAttributes } from "./otel-graphql-utils";
import { SemanticAttributes } from "@opentelemetry/semantic-conventions";
import { SEMATTRS_HTTP_URL } from "@opentelemetry/semantic-conventions";

type Definition = {
name: {
Expand Down Expand Up @@ -50,7 +50,7 @@ export const otelExchange = mapExchange({

span.setAttribute(ObservabilityAttributes.SALEOR_API_URL, operation.context.url);

span.setAttribute(SemanticAttributes.HTTP_URL, operation.context.url);
span.setAttribute(SEMATTRS_HTTP_URL, operation.context.url);

addRequestHeaderAttributes(span, operation.context.fetchOptions?.headers);
if (operation.variables) {
Expand Down
14 changes: 9 additions & 5 deletions packages/otel/src/otel-wrapper.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { SpanKind, SpanStatusCode, type Span } from "@opentelemetry/api";
import { SemanticAttributes } from "@opentelemetry/semantic-conventions";
import {
SEMATTRS_HTTP_METHOD,
SEMATTRS_HTTP_ROUTE,
SEMATTRS_HTTP_STATUS_CODE,
} from "@opentelemetry/semantic-conventions";
import { type NextApiHandler, type NextApiRequest, type NextApiResponse } from "next";
import { otelSdk } from "./instrumentation";

Expand Down Expand Up @@ -63,13 +67,13 @@ export const withOtel = (handler: NextApiHandler, staticRouteName: string): Next
const attributesFromRequest = getAttributesFromRequest(req);

return tracer.startActiveSpan(
`${attributesFromRequest[SemanticAttributes.HTTP_METHOD]} ${staticRouteName}`,
`${attributesFromRequest[SEMATTRS_HTTP_METHOD]} ${staticRouteName}`,
{
kind: SpanKind.SERVER,
attributes: attributesFromRequest,
},
async (span) => {
span.setAttribute(SemanticAttributes.HTTP_ROUTE, staticRouteName);
span.setAttribute(SEMATTRS_HTTP_ROUTE, staticRouteName);

const originalResEnd = res.end;

Expand All @@ -78,7 +82,7 @@ export const withOtel = (handler: NextApiHandler, staticRouteName: string): Next
*/
// @ts-expect-error - this is a hack to get around Vercel freezing lambda's
res.end = async function (this: unknown, ...args: unknown[]) {
span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, res.statusCode);
span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, res.statusCode);
span.end();

try {
Expand All @@ -97,7 +101,7 @@ export const withOtel = (handler: NextApiHandler, staticRouteName: string): Next

wrappingTarget.apply(thisArg, [req, res]);
} catch (error) {
span.setAttribute(SemanticAttributes.HTTP_STATUS_CODE, 500);
span.setAttribute(SEMATTRS_HTTP_STATUS_CODE, 500);

setErrorOnSpan(error, span);

Expand Down
Loading
Loading