import { format } from 'date-fns'; import { takeRight } from 'lodash'; import { Span, Level, Colors, JSONStackTrace, FormattedLine } from './types'; const spaceSpan: Span = { text: ' ' }; function logLevelToSpan(level: Level): Span { switch (level) { case 'debug': case 'DBG': return { fgColor: Colors.Grey, text: 'DBG', fontWeight: 'bold', }; case 'info': case 'INF': return { fgColor: Colors.Green, text: 'INF', fontWeight: 'bold', }; case 'warn': case 'WRN': return { fgColor: Colors.Yellow, text: 'WRN', fontWeight: 'bold', }; case 'error': case 'ERR': return { fgColor: Colors.Red, text: 'ERR', fontWeight: 'bold', }; default: return { text: level }; } } export function formatTime( time: number | string | undefined, spans: Span[], line: string ) { let nl = line; if (time) { let date = ''; if (typeof time === 'number') { // time is a number, so it is the number of seconds OR milliseconds since Unix Epoch (1970-01-01T00:00:00.000Z) // we need to know if time's unit is second or millisecond // 253402214400 is the numer of seconds between Unix Epoch and 9999-12-31T00:00:00.000Z // if time is greater than 253402214400, then time unit cannot be second, so it is millisecond const timestampInMilliseconds = time > 253402214400 ? time : time * 1000; date = format(new Date(timestampInMilliseconds), 'Y/MM/dd hh:mmaa'); } else { date = time; } spans.push({ fgColor: Colors.Grey, text: date }, spaceSpan); nl += `${date} `; } return nl; } export function formatLevel( level: Level | undefined, spans: Span[], line: string ) { let nl = line; if (level) { const levelSpan = logLevelToSpan(level); spans.push(levelSpan, spaceSpan); nl += `${levelSpan.text} `; } return nl; } export function formatCaller( caller: string | undefined, spans: Span[], line: string ) { let nl = line; if (caller) { const trim = takeRight(caller.split('/'), 2).join('/'); spans.push( { fgColor: Colors.Magenta, text: trim, fontWeight: 'bold' }, spaceSpan ); spans.push({ fgColor: Colors.Blue, text: '>' }, spaceSpan); nl += `${trim} > `; } return nl; } export function formatMessage( message: string, spans: Span[], line: string, hasKeys: boolean ) { let nl = line; if (message) { spans.push({ fgColor: Colors.Magenta, text: `${message}` }, spaceSpan); nl += `${message} `; if (hasKeys) { spans.push({ fgColor: Colors.Magenta, text: `|` }, spaceSpan); nl += '| '; } } return nl; } export function formatKeyValuePair( key: string, value: unknown, spans: Span[], line: string, isLastKey: boolean ) { let nl = line; const strValue = typeof value !== 'string' ? JSON.stringify(value) : value; spans.push( { fgColor: Colors.Blue, text: `${key}=` }, { fgColor: key === 'error' || key === 'ERR' ? Colors.Red : Colors.Magenta, text: strValue, } ); if (!isLastKey) spans.push(spaceSpan); nl += `${key}=${strValue}${!isLastKey ? ' ' : ''}`; return nl; } export function formatStackTrace( stackTrace: JSONStackTrace | undefined, lines: FormattedLine[] ) { if (stackTrace) { stackTrace.forEach(({ func, line: lineNumber, source }) => { const line = ` at ${func} (${source}:${lineNumber})`; const spans: Span[] = [ spaceSpan, spaceSpan, spaceSpan, spaceSpan, { text: 'at ', fgColor: Colors.Grey }, { text: func, fgColor: Colors.Red }, { text: `(${source}:${lineNumber})`, fgColor: Colors.Grey }, ]; lines.push({ line, spans }); }); } }