-
Notifications
You must be signed in to change notification settings - Fork 0
🧹 [コード健全性向上] ログ出力の共通化 #52
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| import { ImageResponse } from "next/og"; | ||
| import { NextRequest } from "next/server"; | ||
|
|
||
| import { logger } from "@/lib/logger"; | ||
|
|
||
| export const runtime = "edge"; | ||
|
|
||
| export async function GET( | ||
|
|
@@ -30,7 +32,7 @@ | |
| publicRepos = data.public_repos ?? 0; | ||
| } | ||
| } catch (error) { | ||
| console.error(`Failed to fetch GitHub profile for OG image: ${username}`, error); | ||
| logger.error(`Failed to fetch GitHub profile for OG image: ${username}`, error); | ||
|
Comment on lines
34
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. メッセージ文字列に Line 35 のような動的メッセージは、 🩹 提案差分- logger.error(`Failed to fetch GitHub profile for OG image: ${username}`, error);
+ logger.error("Failed to fetch GitHub profile for OG image", { username }, error);🤖 Prompt for AI Agents |
||
| // fallback to defaults | ||
| } | ||
|
|
||
|
|
@@ -56,7 +58,7 @@ | |
| }} | ||
| > | ||
| {avatarUrl && ( | ||
| <img | ||
|
Check warning on line 61 in src/app/api/og/[username]/route.tsx
|
||
| src={avatarUrl} | ||
| alt="" | ||
| width={120} | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,25 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Centralized logger for the application. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Currently wraps console methods, but can be easily extended to use | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * external logging services (e.g., Sentry, Axiom, Datadog) in the future. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type LogFn = (message: string, ...args: unknown[]) => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface Logger { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info: LogFn; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| warn: LogFn; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error: LogFn; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const logger: Logger = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| info: (message, ...args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.info(message, ...args); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| warn: (message, ...args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.warn(message, ...args); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| error: (message, ...args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(message, ...args); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧹 Nitpick | 🔵 Trivial 🧩 Analysis chain🌐 Web query:
💡 Result: In Chrome/Edge DevTools, the “callsite” link on a console message is basically the top non-ignored JavaScript stack frame that ultimately invoked the console method. That’s why the two patterns behave differently: Why a wrapper changes the callsiteIf you do: const orig = console.log.bind(console);
function log(...args) {
// extra behavior
orig(...args);
}DevTools sees the stack as Why
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const logger: Logger = { | |
| info: (message, ...args) => { | |
| console.info(message, ...args); | |
| }, | |
| warn: (message, ...args) => { | |
| console.warn(message, ...args); | |
| }, | |
| error: (message, ...args) => { | |
| console.error(message, ...args); | |
| }, | |
| export const logger: Logger = { | |
| info: console.info.bind(console) as LogFn, | |
| warn: console.warn.bind(console) as LogFn, | |
| error: console.error.bind(console) as LogFn, | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lib/logger.ts` around lines 15 - 24, 現在の logger 定義 (export const logger:
Logger with info/warn/error arrow functions) wraps console calls and loses
original callsite info in DevTools; replace these wrappers by exporting the
bound console methods directly (e.g. set logger.info =
console.info.bind(console), same for warn and error) so the Debugger sees
correct callsites while keeping the Logger shape; update the logger constant
(info, warn, error) to use bound methods rather than arrow wrappers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
現在の LogFn 型は、最初の引数を文字列に限定しています。これは、ラップしている console メソッドよりも制限が厳しいです。console メソッドは、最初の引数として任意の型を受け入れることができます(例: console.error(errorObject))。
ロガーをより柔軟にし、console メソッドの完全な代替として機能させるために、シグネチャを可変長引数を受け入れるように変更することをお勧めします。これにより、将来的にSentryなどのエラー追跡ツールと統合する際にも、エラーオブジェクトを直接渡しやすくなります。
| type LogFn = (message: string, ...args: unknown[]) => void; | |
| interface Logger { | |
| info: LogFn; | |
| warn: LogFn; | |
| error: LogFn; | |
| } | |
| export const logger: Logger = { | |
| info: (message, ...args) => { | |
| console.info(message, ...args); | |
| }, | |
| warn: (message, ...args) => { | |
| console.warn(message, ...args); | |
| }, | |
| error: (message, ...args) => { | |
| console.error(message, ...args); | |
| }, | |
| }; | |
| type LogFn = (...args: unknown[]) => void; | |
| interface Logger { | |
| info: LogFn; | |
| warn: LogFn; | |
| error: LogFn; | |
| } | |
| export const logger: Logger = { | |
| info: (...args) => { | |
| console.info(...args); | |
| }, | |
| warn: (...args) => { | |
| console.warn(...args); | |
| }, | |
| error: (...args) => { | |
| console.error(...args); | |
| }, | |
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
React 19 Error Boundary automatic console.error logging behavior💡 Result:
In React 19, errors that are thrown during rendering and caught by an Error Boundary are still automatically logged by React (i.e., React calls
console.errorby default), but the shape/amount of logging changed:console.errornoise. [1]Can you turn off React’s automatic
console.errorfor caught errors?Not via Error Boundary APIs directly—React logs by default. What React 19 adds is root-level hooks so you can implement your own reporting behavior:
createRoot(container, { onCaughtError, onUncaughtError, onRecoverableError })[3]hydrateRoot(domNode, reactNode, { onCaughtError, onUncaughtError, onRecoverableError })[4]The
createRootdocs explicitly note: “By default, React will log all errors to the console.” and then show using these hooks for custom reporting. [3]Practical implication: if you also
console.error(...)insidecomponentDidCatch, you’ll get your log plus React’s default log (so it can look “duplicated”), unless you move logging toonCaughtError(or otherwise dedupe/filter on your side). [1][3]Sources: [1] React 19 “Better error reporting” section (React blog) https://react.dev/blog/2024/12/05/react-19 • [2] Example/observed behavior change after upgrading to React 19 https://andrei-calazans.com/posts/react-19-error-boundary-changed/ • [3]
createRootdocs (“By default, React will log all errors…”) https://react.dev/reference/react-dom/client/createRoot • [4]hydrateRootdocs (root error hooks) https://react.dev/reference/react-dom/client/hydrateRootReact 19 の Error Boundary による自動ログのため、エラーログが二重記録されます。
React 19 では Error Boundary に捕捉されたエラーが自動的に
console.errorに報告されます。このため、line 16 のlogger.error("User page error:", error)を残すと、React による自動ログと合わせて同じエラーが二重に記録されます。将来loggerを Sentry などの外部サービスに切り替えた場合、同じイベントが重複して送信されることになります。対応としては以下のいずれかを推奨します:
useEffectを削除する場合は、loggerとuseEffectの import も不要になります。🤖 Prompt for AI Agents