diff --git a/src/app/chat/components/chat-input-bar.tsx b/src/app/chat/components/chat-input-bar.tsx index fddffeb8..1e92038b 100644 --- a/src/app/chat/components/chat-input-bar.tsx +++ b/src/app/chat/components/chat-input-bar.tsx @@ -26,13 +26,31 @@ export function ChatInputBar({ disabled = false }: ChatInputBarProps) { useKeyboardHeight({ targetRef: textareaRef, active: isFocused, - onKeyboardDismiss: () => setIsFocused(false), + onKeyboardDismiss: () => { + log.important("info", "[chat-input-bar] keyboard dismissed", { + contentLength: input.length, + hasContent, + disabled, + wasFocused: isFocused, + }); + setIsFocused(false); + }, }); const handleInputChange = (value: string) => { setInput(value); }; + const handleFocusChange = (focused: boolean) => { + log.important("info", "[chat-input-bar] focus change", { + focused, + contentLength: input.length, + hasContent, + disabled, + }); + setIsFocused(focused); + }; + const handleSend = () => { if (!hasContent) return; log.debug("[chat-input-bar] handleSend", { @@ -42,6 +60,12 @@ export function ChatInputBar({ disabled = false }: ChatInputBarProps) { disabled, isFocused, }); + log.important("info", "[chat-input-bar] send", { + contentLength: input.length, + hasContent, + disabled, + isFocused, + }); dispatch({ type: "ChatSendMessage", content: input }); setInput(""); textareaRef.current?.focus(); @@ -55,7 +79,7 @@ export function ChatInputBar({ disabled = false }: ChatInputBarProps) { value={input} onChange={handleInputChange} onSubmit={handleSend} - onFocusChange={setIsFocused} + onFocusChange={handleFocusChange} disabled={disabled} /> { timeoutIds.forEach((id) => window.clearTimeout(id)); @@ -98,7 +102,7 @@ export function useKeyboardHeight({ lastInputLift = nextLift; setInputLiftVar(nextLift); - log.debug("[keyboard] apply", { + log.important("info", "[keyboard] apply", { reason, inputLift: nextLift, fallback: nextLift === FALLBACK_INPUT_LIFT_PX, @@ -113,7 +117,7 @@ export function useKeyboardHeight({ applyLift(0, reason); blurKeyboardTarget(targetRef?.current); onKeyboardDismissRef.current?.(); - log.debug("[keyboard] released", { + log.important("info", "[keyboard] released", { reason, snapshot: formatSnapshot(readKeyboardSnapshot()), }); diff --git a/src/utils/logger-sentry-reporter.ts b/src/utils/logger-sentry-reporter.ts index 6347d740..1a5b2fcb 100644 --- a/src/utils/logger-sentry-reporter.ts +++ b/src/utils/logger-sentry-reporter.ts @@ -1,7 +1,7 @@ import * as Sentry from "@sentry/nextjs"; import type { CaptureContext, SeverityLevel } from "@sentry/nextjs"; -export type RemoteLogLevel = "warn" | "error" | "fatal"; +export type RemoteLogLevel = "debug" | "info" | "warn" | "error" | "fatal"; export interface SentryLogPayload { level: RemoteLogLevel; diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 22091916..f4805828 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -79,6 +79,11 @@ export class Logger { this.write("fatal", args); } + important(level: RemoteLogLevel, ...args: LogArgs): void { + Logger.reportProductionLog(level, this.component, args, true); + this.writeLocal(level, args); + } + /** * 把日志中的任意数据转成人眼友好的多行文本。 * - object / array: pretty JSON @@ -146,8 +151,11 @@ export class Logger { } private write(level: LogLevel, args: LogArgs): void { - Logger.reportImportantProductionLog(level, this.component, args); + Logger.reportProductionLog(level, this.component, args); + this.writeLocal(level, args); + } + private writeLocal(level: LogLevel, args: LogArgs): void { if (Logger.shouldUseBrowserConsole()) { Logger.writeBrowserConsole(level, this.component, args); return; @@ -184,12 +192,14 @@ export class Logger { ); } - private static reportImportantProductionLog( + private static reportProductionLog( level: LogLevel, component: string, args: LogArgs, + force = false, ): void { - if (!Logger.shouldReportToRemote(level)) return; + if (!force && !Logger.shouldReportToRemote(level)) return; + if (force && !AppEnvUtil.isProduction()) return; const { message, data } = Logger.toBrowserConsolePayload(args); reportSentryLog({