From 4020dcc7dcaa00ecde081ebf39729ffb9e8261d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Fri, 11 Oct 2024 12:42:37 +0200 Subject: [PATCH 1/5] Add vercel transport for logger --- apps/avatax/src/logger.ts | 6 +-- packages/logger/index.ts | 2 +- packages/logger/node.ts | 1 + packages/logger/src/logger-context.test.ts | 3 +- .../logger/src/logger-sentry-transport.ts | 2 +- .../logger/src/logger-vercel-transport.ts | 38 +++++++++++++++++++ 6 files changed, 45 insertions(+), 7 deletions(-) create mode 100644 packages/logger/src/logger-vercel-transport.ts diff --git a/apps/avatax/src/logger.ts b/apps/avatax/src/logger.ts index 39f700a19..d04eb296d 100644 --- a/apps/avatax/src/logger.ts +++ b/apps/avatax/src/logger.ts @@ -1,7 +1,5 @@ import { attachLoggerConsoleTransport, createLogger, logger } from "@saleor/apps-logger"; -import packageJson from "../package.json"; - logger.settings.maskValuesOfKeys = ["metadata", "username", "password", "apiKey"]; if (process.env.NODE_ENV !== "production") { @@ -10,11 +8,11 @@ if (process.env.NODE_ENV !== "production") { if (typeof window === "undefined") { import("@saleor/apps-logger/node").then( - async ({ attachLoggerOtelTransport, attachLoggerSentryTransport, LoggerContext }) => { + async ({ attachLoggerSentryTransport, attachLoggerVercelTransport }) => { const loggerContext = await import("./logger-context").then((m) => m.loggerContext); attachLoggerSentryTransport(logger); - attachLoggerOtelTransport(logger, packageJson.version, loggerContext); + attachLoggerVercelTransport(logger, loggerContext); }, ); } diff --git a/packages/logger/index.ts b/packages/logger/index.ts index 87a90322b..5d46d7a67 100644 --- a/packages/logger/index.ts +++ b/packages/logger/index.ts @@ -1,2 +1,2 @@ -export { logger, createLogger } from "./src/logger"; +export { createLogger, logger } from "./src/logger"; export { attachLoggerConsoleTransport } from "./src/logger-console-transport"; diff --git a/packages/logger/node.ts b/packages/logger/node.ts index 570867bcd..b000b5e59 100644 --- a/packages/logger/node.ts +++ b/packages/logger/node.ts @@ -1,3 +1,4 @@ export { LoggerContext, wrapWithLoggerContext } from "./src/logger-context"; export * from "./src/logger-otel-transport"; export * from "./src/logger-sentry-transport"; +export * from "./src/logger-vercel-transport"; diff --git a/packages/logger/src/logger-context.test.ts b/packages/logger/src/logger-context.test.ts index cc214ccf0..3aa3fcc41 100644 --- a/packages/logger/src/logger-context.test.ts +++ b/packages/logger/src/logger-context.test.ts @@ -1,4 +1,5 @@ -import { describe, it, expect } from "vitest"; +import { describe, expect, it } from "vitest"; + import { LoggerContext } from "./logger-context"; describe("LoggerContext", () => { diff --git a/packages/logger/src/logger-sentry-transport.ts b/packages/logger/src/logger-sentry-transport.ts index ecbb0f9b7..f1dd8e995 100644 --- a/packages/logger/src/logger-sentry-transport.ts +++ b/packages/logger/src/logger-sentry-transport.ts @@ -1,6 +1,6 @@ -import { ILogObj, Logger } from "tslog"; import * as Sentry from "@sentry/nextjs"; import { SeverityLevel } from "@sentry/nextjs"; +import { ILogObj, Logger } from "tslog"; const loggerLevelToSentryLevel = (level: string): SeverityLevel => { switch (level) { diff --git a/packages/logger/src/logger-vercel-transport.ts b/packages/logger/src/logger-vercel-transport.ts new file mode 100644 index 000000000..eaab7f161 --- /dev/null +++ b/packages/logger/src/logger-vercel-transport.ts @@ -0,0 +1,38 @@ +import { ILogObj, Logger } from "tslog"; + +import { LoggerContext } from "./logger-context"; + +export const attachLoggerVercelTransport = ( + logger: Logger, + loggerContext?: LoggerContext, +) => { + logger.attachTransport((log) => { + const { message, attributes, _meta } = log; + + const bodyMessage = log._meta.name ? `[${log._meta.name}] ${message}` : message; + + const stringifiedMessage = JSON.stringify({ + message: bodyMessage, + ...attributes, + ...loggerContext?.getRawContext(), + _meta: { + ..._meta, + // used to filter out log in log drain + source: "saleor-app", + }, + }); + + // Prints Vercel log in proper level https://vercel.com/docs/observability/runtime-logs#level + if (_meta.logLevelName === "ERROR") { + console.error(stringifiedMessage); + return; + } + + if (_meta.logLevelName === "WARN") { + console.warn(stringifiedMessage); + return; + } + + console.log(stringifiedMessage); + }); +}; From 3a407bfb18e954ec04ff71f8fc090ea974abdcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Mon, 14 Oct 2024 10:38:51 +0200 Subject: [PATCH 2/5] Move to require --- apps/avatax/src/logger.ts | 13 ++++++------- apps/avatax/src/pages/api/manifest.ts | 9 +++++++++ apps/avatax/src/pages/index.tsx | 4 ++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/avatax/src/logger.ts b/apps/avatax/src/logger.ts index d04eb296d..75fe9838c 100644 --- a/apps/avatax/src/logger.ts +++ b/apps/avatax/src/logger.ts @@ -7,14 +7,13 @@ if (process.env.NODE_ENV !== "production") { } if (typeof window === "undefined") { - import("@saleor/apps-logger/node").then( - async ({ attachLoggerSentryTransport, attachLoggerVercelTransport }) => { - const loggerContext = await import("./logger-context").then((m) => m.loggerContext); + const appsLogger = require("@saleor/apps-logger/node"); - attachLoggerSentryTransport(logger); - attachLoggerVercelTransport(logger, loggerContext); - }, - ); + appsLogger.attachLoggerSentryTransport(logger); + + if (process.env.NODE_ENV === "production") { + appsLogger.attachLoggerVercelTransport(logger, require("./logger-context").loggerContext); + } } export { createLogger, logger }; diff --git a/apps/avatax/src/pages/api/manifest.ts b/apps/avatax/src/pages/api/manifest.ts index 71f7d2d4e..c7d8419f9 100644 --- a/apps/avatax/src/pages/api/manifest.ts +++ b/apps/avatax/src/pages/api/manifest.ts @@ -3,10 +3,14 @@ import { AppManifest } from "@saleor/app-sdk/types"; import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { withOtel } from "@saleor/apps-otel"; +import { createLogger } from "@/logger"; + import packageJson from "../../../package.json"; import { appWebhooks } from "../../../webhooks"; import { loggerContext } from "../../logger-context"; +const logger = createLogger("manifest"); + export default wrapWithLoggerContext( withOtel( createManifestHandler({ @@ -14,6 +18,11 @@ export default wrapWithLoggerContext( const iframeBaseUrl = process.env.APP_IFRAME_BASE_URL ?? appBaseUrl; const apiBaseURL = process.env.APP_API_BASE_URL ?? appBaseUrl; + logger.info("Generating manifest", { + iframeBaseUrl, + apiBaseURL, + }); + const manifest: AppManifest = { about: "App connects with AvaTax to dynamically calculate taxes", appUrl: iframeBaseUrl, diff --git a/apps/avatax/src/pages/index.tsx b/apps/avatax/src/pages/index.tsx index 5dbebc5e0..200a2358d 100644 --- a/apps/avatax/src/pages/index.tsx +++ b/apps/avatax/src/pages/index.tsx @@ -5,6 +5,8 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { useIsMounted } from "usehooks-ts"; +// const logger = createLogger("index"); + const IndexPage: NextPage = () => { const { appBridgeState } = useAppBridge(); const isMounted = useIsMounted(); @@ -20,6 +22,8 @@ const IndexPage: NextPage = () => { return Loading...; } + // logger.info("Index page"); + return (

Saleor AvaTax App

From 4f0f643e9b99591850c07a3119931996c30897a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:03:14 +0200 Subject: [PATCH 3/5] Last touches --- apps/avatax/src/lib/app-configuration-logger.ts | 2 +- apps/avatax/src/logger.ts | 10 +++++++--- .../use-case/calculate-taxes.use-case.ts | 2 +- .../src/modules/crud-settings/crud-settings.service.ts | 2 +- apps/avatax/src/pages/api/manifest.ts | 9 --------- .../src/pages/api/webhooks/checkout-calculate-taxes.ts | 2 +- apps/avatax/src/pages/index.tsx | 4 ---- 7 files changed, 11 insertions(+), 20 deletions(-) diff --git a/apps/avatax/src/lib/app-configuration-logger.ts b/apps/avatax/src/lib/app-configuration-logger.ts index 29c64c862..4f590750b 100644 --- a/apps/avatax/src/lib/app-configuration-logger.ts +++ b/apps/avatax/src/lib/app-configuration-logger.ts @@ -29,7 +29,7 @@ export class AppConfigurationLogger { appConfigName: resolvedAvataxConfig.config.name, shippingTaxCode: resolvedAvataxConfig.config.shippingTaxCode, companyCode: resolvedAvataxConfig.config.companyCode, - address: JSON.stringify(resolvedAvataxConfig.config.address), + address: resolvedAvataxConfig.config.address, isSandbox: resolvedAvataxConfig.config.isSandbox, isAutocommit: resolvedAvataxConfig.config.isAutocommit, isDocumentRecordingEnabled: resolvedAvataxConfig.config.isDocumentRecordingEnabled, diff --git a/apps/avatax/src/logger.ts b/apps/avatax/src/logger.ts index 75fe9838c..cf4ffee51 100644 --- a/apps/avatax/src/logger.ts +++ b/apps/avatax/src/logger.ts @@ -7,12 +7,16 @@ if (process.env.NODE_ENV !== "production") { } if (typeof window === "undefined") { - const appsLogger = require("@saleor/apps-logger/node"); + // Don't remove require - it's necessary for proper logger initialization + const { + attachLoggerSentryTransport, + attachLoggerVercelTransport, + } = require("@saleor/apps-logger/node"); - appsLogger.attachLoggerSentryTransport(logger); + attachLoggerSentryTransport(logger); if (process.env.NODE_ENV === "production") { - appsLogger.attachLoggerVercelTransport(logger, require("./logger-context").loggerContext); + attachLoggerVercelTransport(logger, require("./logger-context").loggerContext); } } diff --git a/apps/avatax/src/modules/calculate-taxes/use-case/calculate-taxes.use-case.ts b/apps/avatax/src/modules/calculate-taxes/use-case/calculate-taxes.use-case.ts index de7bb718b..d5054765c 100644 --- a/apps/avatax/src/modules/calculate-taxes/use-case/calculate-taxes.use-case.ts +++ b/apps/avatax/src/modules/calculate-taxes/use-case/calculate-taxes.use-case.ts @@ -221,7 +221,7 @@ export class CalculateTaxesUseCase { }); }, ).map((results) => { - this.logger.info("Taxes calculated", { calculatedTaxes: JSON.stringify(results) }); + this.logger.info("Taxes calculated", { calculatedTaxes: results }); ClientLogStoreRequest.create({ level: "info", diff --git a/apps/avatax/src/modules/crud-settings/crud-settings.service.ts b/apps/avatax/src/modules/crud-settings/crud-settings.service.ts index 16042aa3f..b3d0676d3 100644 --- a/apps/avatax/src/modules/crud-settings/crud-settings.service.ts +++ b/apps/avatax/src/modules/crud-settings/crud-settings.service.ts @@ -46,7 +46,7 @@ export class CrudSettingsManager { if (!validation.success) { this.logger.error("Error while validating metadata", { - error: JSON.stringify(validation.error), + error: validation.error, metadataKey: this.params.metadataKey, }); throw new Error("Error while validating metadata"); diff --git a/apps/avatax/src/pages/api/manifest.ts b/apps/avatax/src/pages/api/manifest.ts index c7d8419f9..71f7d2d4e 100644 --- a/apps/avatax/src/pages/api/manifest.ts +++ b/apps/avatax/src/pages/api/manifest.ts @@ -3,14 +3,10 @@ import { AppManifest } from "@saleor/app-sdk/types"; import { wrapWithLoggerContext } from "@saleor/apps-logger/node"; import { withOtel } from "@saleor/apps-otel"; -import { createLogger } from "@/logger"; - import packageJson from "../../../package.json"; import { appWebhooks } from "../../../webhooks"; import { loggerContext } from "../../logger-context"; -const logger = createLogger("manifest"); - export default wrapWithLoggerContext( withOtel( createManifestHandler({ @@ -18,11 +14,6 @@ export default wrapWithLoggerContext( const iframeBaseUrl = process.env.APP_IFRAME_BASE_URL ?? appBaseUrl; const apiBaseURL = process.env.APP_API_BASE_URL ?? appBaseUrl; - logger.info("Generating manifest", { - iframeBaseUrl, - apiBaseURL, - }); - const manifest: AppManifest = { about: "App connects with AvaTax to dynamically calculate taxes", appUrl: iframeBaseUrl, diff --git a/apps/avatax/src/pages/api/webhooks/checkout-calculate-taxes.ts b/apps/avatax/src/pages/api/webhooks/checkout-calculate-taxes.ts index ae05c0173..f6f68ef6b 100644 --- a/apps/avatax/src/pages/api/webhooks/checkout-calculate-taxes.ts +++ b/apps/avatax/src/pages/api/webhooks/checkout-calculate-taxes.ts @@ -45,7 +45,7 @@ const handler = checkoutCalculateTaxesSyncWebhook.createHandler(async (req, res, subscriptionErrorChecker.checkPayload(payload); logger.info("Tax base payload for checkout calculate taxes", { - payload: JSON.stringify(payload.taxBase), + payload: payload.taxBase, }); loggerContext.set(ObservabilityAttributes.CHANNEL_SLUG, ctx.payload.taxBase.channel.slug); diff --git a/apps/avatax/src/pages/index.tsx b/apps/avatax/src/pages/index.tsx index 200a2358d..5dbebc5e0 100644 --- a/apps/avatax/src/pages/index.tsx +++ b/apps/avatax/src/pages/index.tsx @@ -5,8 +5,6 @@ import { useRouter } from "next/router"; import { useEffect } from "react"; import { useIsMounted } from "usehooks-ts"; -// const logger = createLogger("index"); - const IndexPage: NextPage = () => { const { appBridgeState } = useAppBridge(); const isMounted = useIsMounted(); @@ -22,8 +20,6 @@ const IndexPage: NextPage = () => { return Loading...; } - // logger.info("Index page"); - return (

Saleor AvaTax App

From b8cf254e7d0180fbb4b8095091d82cda9a62c2bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:09:36 +0200 Subject: [PATCH 4/5] Fix test --- apps/avatax/src/lib/app-configuration-logger.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/avatax/src/lib/app-configuration-logger.test.ts b/apps/avatax/src/lib/app-configuration-logger.test.ts index a139344f9..1c61c6441 100644 --- a/apps/avatax/src/lib/app-configuration-logger.test.ts +++ b/apps/avatax/src/lib/app-configuration-logger.test.ts @@ -81,13 +81,13 @@ describe("AppConfigurationLogger", () => { ); expect(mockInfo).toHaveBeenCalledWith("Received configuration", { - address: JSON.stringify({ + address: { city: "test", country: "test", zip: "10111", state: "NY", street: "test", - }), + }, appConfigName: "config", channelSlug: "default-channel", companyCode: "test", From 098faaad1bf792c0ec7d26f3c63902c3a0c5d672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krzysztof=20=C5=BBuraw?= <9116238+krzysztofzuraw@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:16:08 +0200 Subject: [PATCH 5/5] Add changesets --- .changeset/empty-candles-tap.md | 15 +++++++++++++++ .changeset/forty-tools-beg.md | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 .changeset/empty-candles-tap.md create mode 100644 .changeset/forty-tools-beg.md diff --git a/.changeset/empty-candles-tap.md b/.changeset/empty-candles-tap.md new file mode 100644 index 000000000..1938018aa --- /dev/null +++ b/.changeset/empty-candles-tap.md @@ -0,0 +1,15 @@ +--- +"@saleor/apps-logger": patch +--- + +Added new transport `LoggerVercelTransport`. It is currently in experimental stage but it can be used to send logs directly to Vercel log drain. This transport has optional argument of `loggerContext` - if used you need to make sure that function is executed only on the server. + +Usage: + +```ts +import { logger } from "@saleor/apps-logger"; +import { attachLoggerVercelTransport } from "@saleor/apps-logger/node"; +import { loggerContext } from "./logger-context"; + +attachLoggerVercelTransport(logger, loggerContext); +``` diff --git a/.changeset/forty-tools-beg.md b/.changeset/forty-tools-beg.md new file mode 100644 index 000000000..d3b62bcb8 --- /dev/null +++ b/.changeset/forty-tools-beg.md @@ -0,0 +1,5 @@ +--- +"app-avatax": patch +--- + +Added new `LoggerVercelTransport` support. It will help us send logs to our infrastructure without need of OTEL unstable logs API.