From 1d35f43efd5e250498d2d30654be672e4e2d91c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Weng?=
Date: Sun, 21 Jan 2024 22:05:03 +0100
Subject: [PATCH] feat: add pino.js as Logger
---
.env | 5 +-
README.md | 11 +-
next.config.mjs | 4 +
package-lock.json | 442 +++++++++++++++++-
package.json | 3 +
.../[locale]/(unauth)/api/guestbook/route.ts | 67 ++-
src/components/GuestbookList.tsx | 3 +
src/libs/Env.mjs | 4 +-
src/libs/Logger.ts | 25 +
9 files changed, 532 insertions(+), 32 deletions(-)
create mode 100644 src/libs/Logger.ts
diff --git a/.env b/.env
index 7316490b..5fcde96b 100644
--- a/.env
+++ b/.env
@@ -16,6 +16,9 @@ NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
######## [BEGIN] SENSITIVE DATA ######## For security reason, don't update the following variables (secret key) directly in this file.
######## Please create a new file named `.env.local`, all environment files ending with `.local` won't be tracked by Git.
######## After creating the file, you can add the following variables.
-# DATABASE_AUTH_TOKEN=
CLERK_SECRET_KEY=your_clerk_secret_key
+
+# DATABASE_AUTH_TOKEN=
+
+# LOGTAIL_SOURCE_TOKEN=
######## [END] SENSITIVE DATA
diff --git a/README.md b/README.md
index f9c203c8..596c3e30 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
-🚀 Boilerplate and Starter for Next.js with App Router support, Tailwind CSS and TypeScript ⚡️ Made with developer experience first: Next.js, TypeScript, ESLint, Prettier, Husky, Lint-Staged, Jest, Testing Library, Commitlint, VSCode, PostCSS, Tailwind CSS, Authentication with [Clerk](https://clerk.com?utm_source=github&utm_medium=sponsorship&utm_campaign=nextjs-boilerplate), Database with DrizzleORM (SQLite, PostgreSQL, and MySQL) and [Turso](https://turso.tech/?utm_source=nextjsstarterbp), Error Monitoring with [Sentry](https://sentry.io/for/nextjs/?utm_source=github&utm_medium=paid-community&utm_campaign=general-fy25q1-nextjs&utm_content=github-banner-nextjsboilerplate-logo), Monitoring as Code with [Checkly](https://www.checklyhq.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate), Storybook, Multi-language (i18n), One-Click Deploy on [Netlify](https://www.netlify.com), and more.
+🚀 Boilerplate and Starter for Next.js with App Router support, Tailwind CSS and TypeScript ⚡️ Made with developer experience first: Next.js, TypeScript, ESLint, Prettier, Husky, Lint-Staged, Jest, Testing Library, Commitlint, VSCode, PostCSS, Tailwind CSS, Authentication with [Clerk](https://clerk.com?utm_source=github&utm_medium=sponsorship&utm_campaign=nextjs-boilerplate), Database with DrizzleORM (SQLite, PostgreSQL, and MySQL) and [Turso](https://turso.tech/?utm_source=nextjsstarterbp), Error Monitoring with [Sentry](https://sentry.io/for/nextjs/?utm_source=github&utm_medium=paid-community&utm_campaign=general-fy25q1-nextjs&utm_content=github-banner-nextjsboilerplate-logo), Logging with Pino.js and Log Management with [Better Stack](https://betterstack.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate), Monitoring as Code with [Checkly](https://www.checklyhq.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate), Storybook, Multi-language (i18n), One-Click Deploy on [Netlify](https://www.netlify.com), and more.
Clone this project and use it to create your own [Next.js](https://nextjs.org) project. You can check a [Next js templates demo](https://creativedesignsguru.com/demo/Nextjs-Boilerplate/).
@@ -129,6 +129,7 @@ Developer experience first, extremely flexible code structure and only keep what
- 🎉 Storybook for UI development
- 🚨 Error Monitoring with [Sentry](https://sentry.io/for/nextjs/?utm_source=github&utm_medium=paid-community&utm_campaign=general-fy25q1-nextjs&utm_content=github-banner-nextjsboilerplate-logo)
- ☂️ Code coverage with [Codecov](https://about.codecov.io/codecov-free-trial/?utm_source=github&utm_medium=paid-community&utm_campaign=general-fy25q1-nextjs&utm_content=github-banner-nextjsboilerplate-logo)
+- 📝 Logging with Pino.js and Log Management with [Better Stack](https://betterstack.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate)
- 🖥️ Monitoring as Code with [Checkly](https://www.checklyhq.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate)
- 🎁 Automatic changelog generation with Semantic Release
- 🔍 Visual testing with Percy (Optional)
@@ -365,6 +366,14 @@ NextJS Boilerplate relies on [Codecov](https://about.codecov.io/codecov-free-tri
Be sure to create the `CODECOV_TOKEN` as a Github Actions secret, do not paste it directly into your source code.
+### Logging
+
+The project uses Pino.js for logging. By default, for development environment, the logs are displayed in the console.
+
+For production environment, the project is already integrated with [Better Stack](https://betterstack.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate) to manage and query your logs using SQL. To use Better Stack, you need to create a [Better Stack](https://betterstack.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate) account and create a new source: go to your Better Stack Logs Dashboard > Sources > Connect source. Then, you need to give a name to your source and select Node.js as the platform.
+
+After creating the source, you able to see your source token and copy it. Then, in your environment variabless, you can paste the token in `LOGTAIL_SOURCE_TOKEN` variable. Now, all your logs will be automatically sent and ingested by Better Stack.
+
### Checkly monitoring
The project uses [Checkly](https://www.checklyhq.com/?utm_source=github&utm_medium=sponsorship&utm_campaign=next-js-boilerplate) to ensure that your production environment is always up and running. At regular intervals, Checkly runs the tests ending with `*.check.spec.ts` extension and notifies you if any of the tests fail. Additionally, you have the flexibility to execute tests across multiple locations to ensure that your application is available worldwide.
diff --git a/next.config.mjs b/next.config.mjs
index fe71e38d..d95523cb 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -19,6 +19,10 @@ export default withSentryConfig(
},
poweredByHeader: false,
reactStrictMode: true,
+ experimental: {
+ // Related to Pino error with RSC: https://github.com/orgs/vercel/discussions/3150
+ serverComponentsExternalPackages: ['pino'],
+ },
webpack: (config) => {
// config.externals is needed to resolve the following errors:
// Module not found: Can't resolve 'bufferutil'
diff --git a/package-lock.json b/package-lock.json
index de14bf5b..ef7acd89 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"@clerk/nextjs": "^4.29.4",
"@hookform/resolvers": "^3.3.4",
"@libsql/client": "^0.3.6",
+ "@logtail/pino": "^0.4.19",
"@sentry/nextjs": "^7.94.1",
"@spotlightjs/spotlight": "^1.2.7",
"@t3-oss/env-nextjs": "^0.7.3",
@@ -20,6 +21,8 @@
"next": "^14.1.0",
"next-intl": "^3.4.5",
"next-sitemap": "^4.2.3",
+ "pino": "^8.17.2",
+ "pino-pretty": "^10.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.49.3",
@@ -4859,6 +4862,80 @@
"win32"
]
},
+ "node_modules/@logtail/core": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/@logtail/core/-/core-0.4.19.tgz",
+ "integrity": "sha512-IjvMwSyv2LucVoS+2PXzAVG5cTd/50W3dENpC+ePMlAfbKAR5h4eTIOT9GC7zcEBtog6RBJChHApyj4rOvgbYA==",
+ "dependencies": {
+ "@logtail/tools": "^0.4.19",
+ "@logtail/types": "^0.4.19",
+ "serialize-error": "^8.1.0"
+ }
+ },
+ "node_modules/@logtail/node": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/@logtail/node/-/node-0.4.19.tgz",
+ "integrity": "sha512-Z8tIf4DBqnxBWw18XBXNfuA/FtarM3CRda58glySaoQex0yg/296gndsljIXfviy5AUOvOwGXkfde3i8YA23vA==",
+ "dependencies": {
+ "@logtail/core": "^0.4.19",
+ "@logtail/types": "^0.4.19",
+ "@msgpack/msgpack": "^2.5.1",
+ "@types/stack-trace": "^0.0.29",
+ "cross-fetch": "^3.0.4",
+ "minimatch": "^3.0.4",
+ "serialize-error": "^8.1.0",
+ "stack-trace": "^0.0.10"
+ }
+ },
+ "node_modules/@logtail/node/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@logtail/node/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@logtail/pino": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/@logtail/pino/-/pino-0.4.19.tgz",
+ "integrity": "sha512-7cCVTOEe3xHJ+Ln266AJDeYZpDEWgQWQelLJNXQr1msRe/IH+qfzUB19N/kFt4FdmheQhFsI2Jste47ZKS+0fQ==",
+ "dependencies": {
+ "@logtail/node": "^0.4.19",
+ "@logtail/types": "^0.4.19",
+ "pino-abstract-transport": "^1.0.0"
+ },
+ "peerDependencies": {
+ "pino": "^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@logtail/tools": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/@logtail/tools/-/tools-0.4.19.tgz",
+ "integrity": "sha512-6wtf5iJgKMpF2sn8mHOEA2GzluXlBjt6aK0YXzv6IuRhKL4dzk52jjkFWXwgVfA4xf53nhHRGA/SrGOPm6K9bQ==",
+ "dependencies": {
+ "@logtail/types": "^0.4.19"
+ }
+ },
+ "node_modules/@logtail/types": {
+ "version": "0.4.19",
+ "resolved": "https://registry.npmjs.org/@logtail/types/-/types-0.4.19.tgz",
+ "integrity": "sha512-VlrysIpc2H8faZkR0u07pUnuqAArLRgfCVbSD0dtvXgLbkCAGgCCqveAZk99uv6XVxXH/GhH3OUoUoFaGUSTwg==",
+ "dependencies": {
+ "js": "^0.1.0"
+ }
+ },
"node_modules/@mdx-js/react": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz",
@@ -4876,6 +4953,14 @@
"react": ">=16"
}
},
+ "node_modules/@msgpack/msgpack": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-2.8.0.tgz",
+ "integrity": "sha512-h9u4u/jiIRKbq25PM+zymTyW6bhTzELvOoUd+AvYriWOAKpLGnIamaET3pnHYoI5iYphAHBI4ayx0MehR+VVPQ==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/@ndelangen/get-tarball": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz",
@@ -10297,6 +10382,11 @@
"@types/node": "*"
}
},
+ "node_modules/@types/stack-trace": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz",
+ "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g=="
+ },
"node_modules/@types/stack-utils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
@@ -10853,7 +10943,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "dev": true,
"dependencies": {
"event-target-shim": "^5.0.0"
},
@@ -11448,6 +11537,14 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/atomic-sleep": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
+ "integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/atomically": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz",
@@ -13053,8 +13150,7 @@
"node_modules/colorette": {
"version": "2.0.20",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="
},
"node_modules/combined-stream": {
"version": "1.0.8",
@@ -13706,6 +13802,52 @@
"yarn": ">=1"
}
},
+ "node_modules/cross-fetch": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz",
+ "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==",
+ "dependencies": {
+ "node-fetch": "^2.6.12"
+ }
+ },
+ "node_modules/cross-fetch/node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/cross-fetch/node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/cross-fetch/node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/cross-fetch/node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -14199,6 +14341,14 @@
"node": ">=12"
}
},
+ "node_modules/dateformat": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
+ "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/debounce": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
@@ -17525,7 +17675,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "dev": true,
"engines": {
"node": ">=6"
}
@@ -17539,7 +17688,6 @@
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "devOptional": true,
"engines": {
"node": ">=0.8.x"
}
@@ -17789,6 +17937,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/fast-copy": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz",
+ "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA=="
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -17852,6 +18005,19 @@
"fastest-levenshtein": "^1.0.7"
}
},
+ "node_modules/fast-redact": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.3.0.tgz",
+ "integrity": "sha512-6T5V1QK1u4oF+ATxs1lWUmlEk6P2T9HqJG3e2DnHOdVgZy2rFJBoEnrIedcTXlkAHU/zKC+7KETJ+KGGKwxgMQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="
+ },
"node_modules/fastest-levenshtein": {
"version": "1.0.16",
"resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
@@ -22571,6 +22737,25 @@
"@sideway/pinpoint": "^2.0.0"
}
},
+ "node_modules/joycon": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
+ "integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/js": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/js/-/js-0.1.0.tgz",
+ "integrity": "sha512-ZBbGYOpact8QAH9RprFWL4RAESYwbDodxiuDjOnzwzzk9pBzKycoifGuUrHHcDixE/eLMKPHRaXenTgu1qXBqA==",
+ "dependencies": {
+ "commander": "~1.1.1"
+ },
+ "bin": {
+ "js": "bin/js"
+ }
+ },
"node_modules/js-base64": {
"version": "3.7.5",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz",
@@ -22610,6 +22795,17 @@
"js-yaml": "bin/js-yaml.js"
}
},
+ "node_modules/js/node_modules/commander": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-1.1.1.tgz",
+ "integrity": "sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==",
+ "dependencies": {
+ "keypress": "0.1.x"
+ },
+ "engines": {
+ "node": ">= 0.6.x"
+ }
+ },
"node_modules/jscodeshift": {
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.15.1.tgz",
@@ -22873,6 +23069,11 @@
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
+ "node_modules/keypress": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz",
+ "integrity": "sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA=="
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@@ -28483,6 +28684,14 @@
"integrity": "sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==",
"dev": true
},
+ "node_modules/on-exit-leak-free": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
+ "integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
@@ -29128,6 +29337,146 @@
"node": ">=6"
}
},
+ "node_modules/pino": {
+ "version": "8.17.2",
+ "resolved": "https://registry.npmjs.org/pino/-/pino-8.17.2.tgz",
+ "integrity": "sha512-LA6qKgeDMLr2ux2y/YiUt47EfgQ+S9LznBWOJdN3q1dx2sv0ziDLUBeVpyVv17TEcGCBuWf0zNtg3M5m1NhhWQ==",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0",
+ "fast-redact": "^3.1.1",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "v1.1.0",
+ "pino-std-serializers": "^6.0.0",
+ "process-warning": "^3.0.0",
+ "quick-format-unescaped": "^4.0.3",
+ "real-require": "^0.2.0",
+ "safe-stable-stringify": "^2.3.1",
+ "sonic-boom": "^3.7.0",
+ "thread-stream": "^2.0.0"
+ },
+ "bin": {
+ "pino": "bin.js"
+ }
+ },
+ "node_modules/pino-abstract-transport": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.1.0.tgz",
+ "integrity": "sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==",
+ "dependencies": {
+ "readable-stream": "^4.0.0",
+ "split2": "^4.0.0"
+ }
+ },
+ "node_modules/pino-abstract-transport/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/pino-abstract-transport/node_modules/readable-stream": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+ "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/pino-pretty": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.3.1.tgz",
+ "integrity": "sha512-az8JbIYeN/1iLj2t0jR9DV48/LQ3RC6hZPpapKPkb84Q+yTidMCpgWxIT3N0flnBDilyBQ1luWNpOeJptjdp/g==",
+ "dependencies": {
+ "colorette": "^2.0.7",
+ "dateformat": "^4.6.3",
+ "fast-copy": "^3.0.0",
+ "fast-safe-stringify": "^2.1.1",
+ "help-me": "^5.0.0",
+ "joycon": "^3.1.1",
+ "minimist": "^1.2.6",
+ "on-exit-leak-free": "^2.1.0",
+ "pino-abstract-transport": "^1.0.0",
+ "pump": "^3.0.0",
+ "readable-stream": "^4.0.0",
+ "secure-json-parse": "^2.4.0",
+ "sonic-boom": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "bin": {
+ "pino-pretty": "bin.js"
+ }
+ },
+ "node_modules/pino-pretty/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/pino-pretty/node_modules/help-me": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
+ "integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="
+ },
+ "node_modules/pino-pretty/node_modules/readable-stream": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
+ "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/pino-std-serializers": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-6.2.2.tgz",
+ "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="
+ },
"node_modules/pirates": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
@@ -30184,7 +30533,6 @@
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
"integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "dev": true,
"engines": {
"node": ">= 0.6.0"
}
@@ -30206,6 +30554,11 @@
"node": ">=8"
}
},
+ "node_modules/process-warning": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-3.0.0.tgz",
+ "integrity": "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="
+ },
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
@@ -30688,6 +31041,11 @@
"integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==",
"dev": true
},
+ "node_modules/quick-format-unescaped": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
+ "integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="
+ },
"node_modules/quick-lru": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
@@ -31192,6 +31550,14 @@
"node": ">=8.10.0"
}
},
+ "node_modules/real-require": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
+ "integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
"node_modules/recast": {
"version": "0.23.4",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.23.4.tgz",
@@ -31906,6 +32272,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safe-stable-stringify": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz",
+ "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -32025,6 +32399,11 @@
"integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==",
"dev": true
},
+ "node_modules/secure-json-parse": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz",
+ "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="
+ },
"node_modules/semantic-release": {
"version": "23.0.0",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-23.0.0.tgz",
@@ -32571,6 +32950,31 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
+ "node_modules/serialize-error": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz",
+ "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/serialize-error/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
@@ -32998,6 +33402,14 @@
"node": ">=12"
}
},
+ "node_modules/sonic-boom": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.0.tgz",
+ "integrity": "sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==",
+ "dependencies": {
+ "atomic-sleep": "^1.0.0"
+ }
+ },
"node_modules/source-map": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
@@ -33184,7 +33596,6 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "dev": true,
"engines": {
"node": ">= 10.x"
}
@@ -33194,6 +33605,14 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
+ "node_modules/stack-trace": {
+ "version": "0.0.10",
+ "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
+ "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/stack-utils": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
@@ -33633,7 +34052,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
"engines": {
"node": ">=8"
},
@@ -34427,6 +34845,14 @@
"node": ">=0.8"
}
},
+ "node_modules/thread-stream": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-2.4.1.tgz",
+ "integrity": "sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==",
+ "dependencies": {
+ "real-require": "^0.2.0"
+ }
+ },
"node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
diff --git a/package.json b/package.json
index 00c86b76..7e97998c 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"@clerk/nextjs": "^4.29.4",
"@hookform/resolvers": "^3.3.4",
"@libsql/client": "^0.3.6",
+ "@logtail/pino": "^0.4.19",
"@sentry/nextjs": "^7.94.1",
"@spotlightjs/spotlight": "^1.2.7",
"@t3-oss/env-nextjs": "^0.7.3",
@@ -39,6 +40,8 @@
"next": "^14.1.0",
"next-intl": "^3.4.5",
"next-sitemap": "^4.2.3",
+ "pino": "^8.17.2",
+ "pino-pretty": "^10.3.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.49.3",
diff --git a/src/app/[locale]/(unauth)/api/guestbook/route.ts b/src/app/[locale]/(unauth)/api/guestbook/route.ts
index ac7d1270..6d069ab0 100644
--- a/src/app/[locale]/(unauth)/api/guestbook/route.ts
+++ b/src/app/[locale]/(unauth)/api/guestbook/route.ts
@@ -2,6 +2,7 @@ import { eq, sql } from 'drizzle-orm';
import { NextResponse } from 'next/server';
import { db } from '@/libs/DB';
+import { logger } from '@/libs/Logger';
import { guestbookSchema } from '@/models/Schema';
import {
DeleteGuestbookValidation,
@@ -17,14 +18,22 @@ export const POST = async (request: Request) => {
return NextResponse.json(parse.error.format(), { status: 422 });
}
- const guestbook = await db
- .insert(guestbookSchema)
- .values(parse.data)
- .returning();
+ try {
+ const guestbook = await db
+ .insert(guestbookSchema)
+ .values(parse.data)
+ .returning();
- return NextResponse.json({
- id: guestbook[0]?.id,
- });
+ logger.info('A new guestbook has been created');
+
+ return NextResponse.json({
+ id: guestbook[0]?.id,
+ });
+ } catch (error) {
+ logger.error(error, 'An error occurred while creating a guestbook');
+
+ return NextResponse.json({}, { status: 500 });
+ }
};
export const PUT = async (request: Request) => {
@@ -35,16 +44,24 @@ export const PUT = async (request: Request) => {
return NextResponse.json(parse.error.format(), { status: 422 });
}
- await db
- .update(guestbookSchema)
- .set({
- ...parse.data,
- updatedAt: sql`(strftime('%s', 'now'))`,
- })
- .where(eq(guestbookSchema.id, parse.data.id))
- .run();
+ try {
+ await db
+ .update(guestbookSchema)
+ .set({
+ ...parse.data,
+ updatedAt: sql`(strftime('%s', 'now'))`,
+ })
+ .where(eq(guestbookSchema.id, parse.data.id))
+ .run();
+
+ logger.info('A guestbook entry has been updated');
+
+ return NextResponse.json({});
+ } catch (error) {
+ logger.error(error, 'An error occurred while updating a guestbook');
- return NextResponse.json({});
+ return NextResponse.json({}, { status: 500 });
+ }
};
export const DELETE = async (request: Request) => {
@@ -55,10 +72,18 @@ export const DELETE = async (request: Request) => {
return NextResponse.json(parse.error.format(), { status: 422 });
}
- await db
- .delete(guestbookSchema)
- .where(eq(guestbookSchema.id, parse.data.id))
- .run();
+ try {
+ await db
+ .delete(guestbookSchema)
+ .where(eq(guestbookSchema.id, parse.data.id))
+ .run();
+
+ logger.info('A guestbook entry has been deleted');
- return NextResponse.json({});
+ return NextResponse.json({});
+ } catch (error) {
+ logger.error(error, 'An error occurred while deleting a guestbook');
+
+ return NextResponse.json({}, { status: 500 });
+ }
};
diff --git a/src/components/GuestbookList.tsx b/src/components/GuestbookList.tsx
index fde959d2..0fe94702 100644
--- a/src/components/GuestbookList.tsx
+++ b/src/components/GuestbookList.tsx
@@ -1,4 +1,5 @@
import { db } from '@/libs/DB';
+import { logger } from '@/libs/Logger';
import { guestbookSchema } from '@/models/Schema';
import { DeleteGuestbookEntry } from './DeleteGuestbookEntry';
@@ -7,6 +8,8 @@ import { EditableGuestbookEntry } from './EditableGuestbookEntry';
const GuestbookList = async () => {
const guestbook = await db.select().from(guestbookSchema).all();
+ logger.info('Get all guestbook entries');
+
return (
{guestbook.map((elt) => (
diff --git a/src/libs/Env.mjs b/src/libs/Env.mjs
index 0aeb1df2..b4c950f7 100644
--- a/src/libs/Env.mjs
+++ b/src/libs/Env.mjs
@@ -8,15 +8,17 @@ export const Env = createEnv({
CLERK_SECRET_KEY: z.string().min(1),
DATABASE_URL: z.string().min(1),
DATABASE_AUTH_TOKEN: z.string().optional(),
+ LOGTAIL_SOURCE_TOKEN: z.string().optional(),
},
client: {
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(1),
},
// You need to destructure all the keys manually
runtimeEnv: {
+ CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
DATABASE_URL: process.env.DATABASE_URL,
DATABASE_AUTH_TOKEN: process.env.DATABASE_AUTH_TOKEN,
- CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
+ LOGTAIL_SOURCE_TOKEN: process.env.LOGTAIL_SOURCE_TOKEN,
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY:
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
},
diff --git a/src/libs/Logger.ts b/src/libs/Logger.ts
new file mode 100644
index 00000000..9752e4ed
--- /dev/null
+++ b/src/libs/Logger.ts
@@ -0,0 +1,25 @@
+import pino from 'pino';
+
+import { Env } from './Env.mjs';
+
+let options = {};
+
+if (Env.LOGTAIL_SOURCE_TOKEN) {
+ options = {
+ transport: {
+ target: '@logtail/pino',
+ options: { sourceToken: Env.LOGTAIL_SOURCE_TOKEN },
+ },
+ };
+} else {
+ options = {
+ transport: {
+ target: 'pino-pretty',
+ options: {
+ colorize: true,
+ },
+ },
+ };
+}
+
+export const logger = pino(options);