sinProject-Inc/talk

View on GitHub
src/lib/view/log/web_logger.ts

Summary

Maintainability
B
4 hrs
Test Coverage
import { FormattedDate } from '$lib/general/formatted_date'
import { WebLog } from './web_log'
import { WebLogLevel } from './web_log_level'
import { base } from '$app/paths'

export class WebLogger {
    public constructor(private readonly _page_name: string) {}

    private _save_to_local_storage(web_log: WebLog): void {
        const web_logs = JSON.parse(localStorage.getItem('web_logs') || '[]') as WebLog[]

        web_logs.push(web_log)

        localStorage.setItem('web_logs', JSON.stringify(web_logs))
    }

    private async _send(web_log: WebLog): Promise<void> {
        if (!navigator.onLine) {
            this._save_to_local_storage(web_log)

            return
        }

        const response = await fetch(`${base}/api/log`, {
            method: 'POST',
            headers: {
                // eslint-disable-next-line @typescript-eslint/naming-convention
                'Content-Type': 'application/json',
            },
            body: JSON.stringify(web_log),
        })

        if (response.status !== 200) {
            this._save_to_local_storage(web_log)

            return
        }

        WebLogger.send_stored_messages(this)
    }

    private _send_message(web_log_level: WebLogLevel, message: string): void {
        const web_log = new WebLog(
            web_log_level,
            `${FormattedDate.japan()} [${this._page_name}] ${message}`
        )

        this._send(web_log)
    }

    public debug(message: string): void {
        this._send_message(WebLogLevel.debug, message)
    }

    public info(message: string): void {
        this._send_message(WebLogLevel.info, message)
    }

    public warn(message: string): void {
        this._send_message(WebLogLevel.warn, message)
    }

    public error(message: string): void {
        this._send_message(WebLogLevel.error, message)
    }

    public static handle_network_change(web_logger: WebLogger): void {
        const online_text = navigator.onLine ? 'online' : 'offline'

        web_logger.warn(`Network changed: ${online_text}, user_agent: ${navigator.userAgent}`)
    }

    public static send_stored_messages(web_logger: WebLogger): void {
        const web_logs = JSON.parse(localStorage.getItem('web_logs') || '[]') as WebLog[]

        if (web_logs.length === 0) return

        web_logs.forEach((web_log) => web_logger._send(web_log))

        localStorage.removeItem('web_logs')
    }

    public static handle_error(web_logger: WebLogger, event: ErrorEvent): void {
        const message = `Unhandled Error: ${event.error.message}, stack: ${event.error.stack}, user_agent: ${navigator.userAgent}`

        web_logger.error(message)
    }

    public static handle_unhandled_rejection(
        web_logger: WebLogger,
        event: PromiseRejectionEvent
    ): void {
        const message = `Unhanded Rejection: ${event.reason.message}, stack: ${event.reason.stack}, user_agent: ${navigator.userAgent}`

        web_logger.error(message)
    }

    public add_event_listeners(): void {
        // console.debug('[log] add_network_event_listeners')

        window.addEventListener('offline', () => WebLogger.handle_network_change(this))
        window.addEventListener('online', () => WebLogger.handle_network_change(this))
        window.addEventListener('error', (event) => WebLogger.handle_error(this, event))

        window.addEventListener('unhandledrejection', (event) =>
            WebLogger.handle_unhandled_rejection(this, event)
        )
    }
}

// window.addEventListener('error', (event) => {})
//