Created
May 10, 2022 23:53
-
-
Save p13i/815c1157d5795afa973a8ccdc0abebd2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Filename: | |
* Logger.ts | |
* Author: | |
* Pramod Kotipalli (p13i@stanford.edu) | |
* Description: | |
* A custom logging service for react-native/expo apps | |
* that provides more verbose options, including printing | |
* the device's name/brand to the console, useful when | |
* debugging multiple devices from the same console output. | |
* More importantly, this library adds time stamps to each | |
* log. | |
* Usage: | |
* // At the top of a file, say File.ts | |
* const logger = new Logger('File.ts'); | |
* | |
* // Inside a function: | |
* function apple(arg1, arg2) { | |
* logger.fn(apple, arg1, arg2); | |
* } | |
* | |
* // Anywhere: | |
* const someVar = 'banana'; | |
* logger.debug(`I am here with a ${someVar}`, `I can do multiple args`); | |
* // Or: | |
* logger.warn(...); | |
* logger.error(...); | |
* logger.info(...); | |
* | |
*/ | |
import {Platform} from "react-native"; | |
import {stringify} from "./stringify"; | |
import {padStringToLength} from "./padStringToLength"; | |
import * as Device from 'expo-device'; | |
const TIMESTAMP_LENGTH = 20; | |
const PHONE_DETAILS_LENGTH = 32; | |
const CONTEXT_LENGTH = 16; | |
export default class Logger { | |
public static instance: Logger = new Logger(`undefined`); | |
private readonly _deviceName: string; | |
private readonly _brand: string; | |
private readonly _context: string; | |
constructor(context: string | Function) { | |
this._deviceName = Device.deviceName; | |
this._brand = Device.brand; | |
this._context = typeof(context) === 'function' ? context.name : String(context); | |
} | |
public fn(functionName: string | Function, ...args: any[]) { | |
if (typeof functionName === 'function') { | |
functionName = functionName.name; | |
} | |
console.debug(this._formatFn(functionName, ...args)); | |
} | |
public debug(...args: any[]) { | |
console.debug(this._format(...args)); | |
} | |
public info(...args: any[]) { | |
console.info(this._format(...args)); | |
} | |
public warn(...args: any[]) { | |
console.warn(this._format(...args)); | |
} | |
public error(...args: any[]) { | |
console.warn(this._format(...args)); | |
console.error(...args); | |
} | |
private _format(...args: any[]) { | |
let {timestampString, phoneDetailsStr, contextStr} = this._getCommonStrings(); | |
let argsString = this._formatObjectArgs(...args); | |
return `${timestampString} ${phoneDetailsStr} ${contextStr} ${argsString}`; | |
} | |
private _getCommonStrings = () => { | |
let now = new Date(); | |
let timestampString = padStringToLength(`[${now.toISOString()}]`, TIMESTAMP_LENGTH); | |
let phoneDetailsStr = padStringToLength(`[${this._brand} ${Platform.OS} ${Platform.Version} ${this._deviceName}]`, PHONE_DETAILS_LENGTH); | |
let contextStr = padStringToLength(`[${this._context}]`, CONTEXT_LENGTH); | |
return {timestampString, phoneDetailsStr, contextStr}; | |
} | |
private _formatFn(functionName: string, ...args: any[]) { | |
let {timestampString, phoneDetailsStr, contextStr} = this._getCommonStrings(); | |
return `${timestampString} ${phoneDetailsStr} ${contextStr} ${functionName}(${args.length > 0 ? this._formatObjectArgs(...args) : ''})`; | |
} | |
private _formatObjectArgs(...args: any[]) { | |
return args.map((arg, index) => Logger._formatObjectArg(arg)).join(', '); | |
} | |
private static _formatObjectArg(arg: any): string { | |
if (typeof arg === 'object') { | |
return stringify(arg, /* depth: */ 1); | |
} | |
return String(arg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment