6

Referencing this question I am using this bit of code to find the line number of the caller to my custom logging function:

/**
 * eLog - displays calling line number & message & dumps vars as pretty json string
 * @param {string} msg - string to display in log message
 * @param {any} dispVars - any number of variables (ellipsis , aka Rest parameters) to dump
 */
function eLog(msg:string,...dispVars:any[]){
    let caller_line = (new Error).stack.split("\n")[4];
    console.log(`eLog->Line#${caller_line}->${msg}->`);
    console.log(JSON.stringify((new Error).stack.split("\n"),null,2));
    dispVars.forEach(value => {
        console.log(JSON.stringify(value,null,2));
    });
}

Called like this:

eLog("eLog Test",this);

And while this does do a proper dump of the .js file line #, I need the Source line#, the .ts line number. How can I generate this properly?

2 Answers 2

6

I went through this over the evening and came up with a function I am pleased with. Thanks for the help in getting started-

Separated it out into log.ts

require('source-map-support').install({
	environment: 'node'
});


/**
 * eLog - displays calling line number & message & dumps vars as pretty json string
 * @param {string} msg - string to display in log message
 * @param {any} dispVars - any number of variables (ellipsis , aka Rest parameters) to dump
 * {@link https://github.com/evanw/node-source-map-support usable by typescript node-source-map-support module}
 * {@link https://github.com/mozilla/source-map/ Mozilla source-map library & project}
 * {@link http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/ good introduction to sourcemaps}
 */
export function eLog(msg:string,...dispVars:any[]){
	/**
	 * go one line back for the caller
	 * @type {string}
	 */
	let stackLine = (new Error).stack.split("\n")[2];
	/**
	 * retrieve the file basename & positional data, after the last `/` to the `)` 
	 */
	// 
	let caller_line = stackLine.slice(stackLine.lastIndexOf('/'),stackLine.lastIndexOf(')'))
	/**
	 *  test for no `/` ; if there is no `/` then use filename without a prefixed path
	 */ 
	if ( caller_line.length == 0 ) {
		caller_line = stackLine.slice(stackLine.lastIndexOf('('),stackLine.lastIndexOf(')'))
	}
	// 
	/**
	 * filename_base - parse out the file basename; remove first `/` char and go to `:`
	 */
	let filename_base = caller_line.slice(0+1,caller_line.indexOf(':'));
	/**
	 * line_no - parse out the line number ; remove first `:` char and go to 2nd `:`
	 */
	let line_no = caller_line.slice(caller_line.indexOf(':')+1,caller_line.lastIndexOf(':'));
	/**
	 * line_pos - line positional - from the last `:` to the end of the string
	 */
	let line_pos = caller_line.slice(caller_line.lastIndexOf(':')+1);
	console.log(`eLog called by ${filename_base} on line# ${line_no} @ char# ${line_pos} said:\n${msg}`);
	// print out the input variables as pretty JSON strings
	dispVars.forEach(value => {
		console.log(JSON.stringify(value,null,2));
	});
}

Which can be called with a simple:

eLog("eLog Test",this);

from any file so long as the function is loaded (such as)

import { eLog } from './log'

I hope that helps somebody else.

Cheers guys. -Eric

Sign up to request clarification or add additional context in comments.

Comments

0

How can I generate this properly

a.) The code you have is fairly dependent upon the user runtime (e.g. will not work in IE).

b.) You will need sourcemaps for js -> ts to work. Stuff that makes it easy doesn't exist already. The defacto raw package to use sourcemaps is : https://www.npmjs.com/package/source-map

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.