Skip to content

Instantly share code, notes, and snippets.

@p13i
Created May 10, 2022 23:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save p13i/815c1157d5795afa973a8ccdc0abebd2 to your computer and use it in GitHub Desktop.
Save p13i/815c1157d5795afa973a8ccdc0abebd2 to your computer and use it in GitHub Desktop.
/*
* 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