chore(env): update logging configuration in .env.example and add new dependencies in package-lock.json

This commit is contained in:
Fatih Kadir Akın
2025-12-20 18:44:44 +03:00
parent 7158ead89a
commit eb1b8dfc95
5 changed files with 235 additions and 2 deletions

View File

@@ -38,4 +38,7 @@ NEXTAUTH_SECRET="your-super-secret-key-change-in-production"
# OPENAI_EMBEDDING_MODEL=text-embedding-3-small # Optional: embedding model for AI search
# OPENAI_GENERATIVE_MODEL=gpt-4o-mini # Optional: generative model for AI generation
# GOOGLE_ANALYTICS_ID="G-XXXXXXXXX"
# GOOGLE_ANALYTICS_ID="G-XXXXXXXXX"
# Logging (optional)
# LOG_LEVEL="info" # Options: trace, debug, info, warn, error, fatal

129
package-lock.json generated
View File

@@ -42,6 +42,7 @@
"next-intl": "^4.5.8",
"next-themes": "^0.4.6",
"openai": "^6.10.0",
"pino": "^10.1.0",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-hook-form": "^7.68.0",
@@ -3162,6 +3163,12 @@
"node": ">=0.10"
}
},
"node_modules/@pinojs/redact": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
"license": "MIT"
},
"node_modules/@prisma/client": {
"version": "6.19.1",
"resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.19.1.tgz",
@@ -6702,6 +6709,15 @@
"node": ">= 0.4"
}
},
"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==",
"license": "MIT",
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
@@ -11775,6 +11791,15 @@
"devOptional": true,
"license": "MIT"
},
"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==",
"license": "MIT",
"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",
@@ -12000,6 +12025,43 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pino": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/pino/-/pino-10.1.0.tgz",
"integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==",
"license": "MIT",
"dependencies": {
"@pinojs/redact": "^0.4.0",
"atomic-sleep": "^1.0.0",
"on-exit-leak-free": "^2.1.0",
"pino-abstract-transport": "^2.0.0",
"pino-std-serializers": "^7.0.0",
"process-warning": "^5.0.0",
"quick-format-unescaped": "^4.0.3",
"real-require": "^0.2.0",
"safe-stable-stringify": "^2.3.1",
"sonic-boom": "^4.0.1",
"thread-stream": "^3.0.0"
},
"bin": {
"pino": "bin.js"
}
},
"node_modules/pino-abstract-transport": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
"integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
"license": "MIT",
"dependencies": {
"split2": "^4.0.0"
}
},
"node_modules/pino-std-serializers": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz",
"integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==",
"license": "MIT"
},
"node_modules/pkce-challenge": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.1.tgz",
@@ -12121,6 +12183,22 @@
}
}
},
"node_modules/process-warning": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
"integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT"
},
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
@@ -12219,6 +12297,12 @@
],
"license": "MIT"
},
"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==",
"license": "MIT"
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -12408,6 +12492,15 @@
"url": "https://paulmillr.com/funding/"
}
},
"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==",
"license": "MIT",
"engines": {
"node": ">= 12.13.0"
}
},
"node_modules/reflect.getprototypeof": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
@@ -12641,6 +12734,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safe-stable-stringify": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
@@ -12916,6 +13018,15 @@
"is-arrayish": "^0.3.1"
}
},
"node_modules/sonic-boom": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
"integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
"license": "MIT",
"dependencies": {
"atomic-sleep": "^1.0.0"
}
},
"node_modules/sonner": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/sonner/-/sonner-2.0.7.tgz",
@@ -12945,6 +13056,15 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/stable-hash": {
"version": "0.0.5",
"resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz",
@@ -13241,6 +13361,15 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/thread-stream": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
"integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
"license": "MIT",
"dependencies": {
"real-require": "^0.2.0"
}
},
"node_modules/tinyexec": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz",

View File

@@ -50,6 +50,7 @@
"next-intl": "^4.5.8",
"next-themes": "^0.4.6",
"openai": "^6.10.0",
"pino": "^10.1.0",
"react": "19.2.0",
"react-dom": "19.2.0",
"react-hook-form": "^7.68.0",

View File

@@ -65,7 +65,7 @@ export default defineConfig({
// Enable MCP (Model Context Protocol) features including API key generation
mcp: true,
// Enable comments on prompts
comments: true,
comments: false,
},
// Homepage customization

100
src/lib/logger.ts Normal file
View File

@@ -0,0 +1,100 @@
import pino from "pino";
const isDevelopment = process.env.NODE_ENV === "development";
export const logger = pino({
level: process.env.LOG_LEVEL || (isDevelopment ? "debug" : "info"),
// Structured JSON format for DigitalOcean App Platform log forwarding
formatters: {
level: (label) => ({ level: label }),
bindings: (bindings) => ({
pid: bindings.pid,
host: bindings.hostname,
app: "prompts-chat",
}),
},
// Add timestamp in ISO format for better log aggregation
timestamp: pino.stdTimeFunctions.isoTime,
// Base context added to all logs
base: {
env: process.env.NODE_ENV,
version: process.env.npm_package_version || "unknown",
},
// Redact sensitive fields
redact: {
paths: [
"password",
"token",
"apiKey",
"api_key",
"authorization",
"cookie",
"req.headers.authorization",
"req.headers.cookie",
],
censor: "[REDACTED]",
},
});
// Create child loggers for specific contexts
export const createLogger = (context: string) => {
return logger.child({ context });
};
// Pre-configured loggers for common use cases
export const dbLogger = createLogger("database");
export const authLogger = createLogger("auth");
export const apiLogger = createLogger("api");
// Helper for request logging
export const logRequest = (
method: string,
path: string,
statusCode: number,
duration: number,
userId?: string
) => {
const log = apiLogger.child({
method,
path,
statusCode,
duration: `${duration}ms`,
...(userId && { userId }),
});
if (statusCode >= 500) {
log.error("Request failed");
} else if (statusCode >= 400) {
log.warn("Request error");
} else {
log.info("Request completed");
}
};
// Helper for error logging with stack traces
export const logError = (
error: Error | unknown,
context?: string,
meta?: Record<string, unknown>
) => {
const errorObj = error instanceof Error ? error : new Error(String(error));
logger.error(
{
err: {
message: errorObj.message,
name: errorObj.name,
stack: errorObj.stack,
},
context,
...meta,
},
errorObj.message
);
};
export default logger;