Use the bind method to wrap console.log and preserve the calling context

When it comes to logging message text while preserving the original context (class, line number), console output does the job perfectly with console.log.bind(console). However, the challenge arises when I also need to send the message to an HTTP server for logging.

For example 1: By using a getter & bind, I can pass console.log to the caller and retrieve the message and context (class, line number). But in this scenario, the getter function won't have access to arguments at runtime as they are passed directly to console. Therefore, I am unable to log the message.

Example 2: If I switch from a getter to a function, I will have access to arguments (i.e., the message) which I can then send to another location while simultaneously logging it using console.log. However, the console.log line will display my logger class instead of being bound.

Here is Example 1:


get debug() {
    let message = Array.prototype.slice.call(arguments);
    // send message over to some http server
    // ...

    return console.log.bind(console);
}

And here is Example 2:


public debug() {
    let message = Array.prototype.slice.call(arguments);
    // send message over to some http server
    // ...
    console.log.apply(console, args);
}

My question is whether there is a way to maintain the context for console.log while also obtaining the log message for further manipulation (such as sending it to an HTTP server).

Answer №1

The context, specifically the value of `this` during the execution of `console.log`, holds no significance in this scenario. It does not impact the file and line information logged by the function.

What truly matters for the accurate logging of file and line data by `console.log` is the location where the function is called. Since it is a built-in function written in native code, replacing it while maintaining functionality is impossible.

Thus, wrapping `console.log` to perform custom actions with its arguments will only obscure the actual calling site's details.


To attain the closest representation of the call site alongside the JS interpreter's understanding, one should manually create a stack trace using an `Error` instance and retrieve its `stack` property.

function debug(...args: any[]) {
  
  // Custom actions here...
  sendArgsToServer(args) 

  // Extracting the previous caller's line from the stack trace.
  const callSite = new Error().stack!.split('\n')[2].trim()

  // Logging with the desired call site appended at the end.
  console.log(...args, callSite)
}

function foo() {
  debug('my debug line')
}

foo()

Upon running this code in Chrome, the console displays:

The annotation `index.ts:132` indicates the invocation of `console.log()` within the debug function. Additionally, `index.ts:135:5` immediately following the logged statement marks the origin point of the `debug()` call.

In Chrome, clicking on these links directs you to the corresponding section of source mapped code within the sources pane.

This method likely provides the most comprehensive solution available for this situation.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Developing a personalized validation function using Typescript for the expressValidator class - parameter is assumed to have a type of 'any'

I'm seeking to develop a unique validation function for express-validator in typescript by extending the 'body' object. After reviewing the helpful resource page, I came across this code snippet: import { ExpressValidator } from 'expre ...

Identify the CSS class for the ionic component on the webpage

Currently, I am in the process of developing an application using ionic 2 and angular 2. Within this app, I am utilizing the ionic 2 component known as ModalController. Unfortunately, I have encountered a challenge when attempting to adjust the size of th ...

Why does the method of type assigning vary between actual and generic types?

There are no errors in the code shown below: type C = {b: string}; class Class { data: C; constructor(data: C) { this.data = data; } test() { const hack: C & {a?: any} = this.data; //no error } } However, when a g ...

Setting innerHTML does not affect the content of an SVG element

I am currently working on an Angular 7 application and I need to dynamically update the text value based on a dropdown selection. For example, if the id of the text element is 10, then I want to change the text from 'hi' to 'hello'. T ...

Ensuring TypeScript recognizes a class property as definitively initialized when set using a Promise constructor

I have a simple class definition that is giving me an error in TypeScript. class Container { resolveData: (s: string) => void // not definitely initialized error! data: Promise<string> constructor() { this.data = new Promise&l ...

Try using ngFor within the insertAdjacentHTML method

When a user clicks, I dynamically attach an element inside a template like this: this.optionValue = []; youClickMe(){ var moreput = ''; moreput += '<select">'; moreput += '<option *ngFor="let lup of opti ...

Oops! The program encountered an issue on the production environment, but it's running smoothly

When I execute Webpack using the command node node_modules/webpack/bin/webpack. js --env. prod An error message is displayed below. However, when running in --env. dev mode, the command executes without any issues. Can't resolve './../$$_gen ...

The operation of fetching multiple documents within a transaction loop is not functioning as anticipated

I am encountering an issue where I am attempting to retrieve multiple documents within a transaction and then update them all in the same transaction (due to their interdependence). Despite following the rule of ensuring all reads occur before any writes, ...

I am having trouble figuring out the issue with the state and how to properly implement it in Typescript

I am having difficulties sending emails using Nodemailer, TypeScript, and NextJS. The contact.tsx file within the state component is causing errors when using setform. As a beginner in TypeScript, I have been unable to find a solution to this issue. Any he ...

Generate dynamic property values based on calculations

I am facing a challenge with a form that I have designed. Could you guide me on how to dynamically update the value of the calculate field (contingency) whenever the user modifies the values of budget1 and budget2? I have attempted several approaches witho ...

Tips for incorporating a reference into a styled component div in a React application using TypeScript

Looking to include a reference to a styled component div. Here is the code snippet: const DragAndDrop: React.FC<any> = props => { const divRef= React.createRef(); return ( <Zone ref={divRef}/> ); } Encountering thi ...

Optimal strategies for managing server-side validation/errors in Angular applications

Back in the day, I used to retrieve HTTP responses with a TypeScript object. validateTokenHttp(token: string): Observable<User> { return this.http.get<User>(`${environment.api}/auth/verifyToken/${token}`); } Sometimes it would return a Us ...

Creating a Typescript interface for a anonymous function being passed into a React component

I have been exploring the use of Typescript in conjunction with React functional components, particularly when utilizing a Bootstrap modal component. I encountered some confusion regarding how to properly define the Typescript interface for the component w ...

Using Angular BehaviorSubject in different routed components always results in null values when accessing with .getValue or .subscribe

I am facing an issue in my Angular application where the JSON object saved in the service is not being retrieved properly. When I navigate to another page, the BehaviorSubject .getValue() always returns empty. I have tried using .subscribe but without succ ...

Trouble with 'import type' declaration causing build issues in a Next.js project

Having trouble importing the Metadata type from the next module. The code snippet below is directly from the Next.js documentation. THE ISSUE client.js:1 ./app/layout.tsx:3:12 Syntax error: Unexpected token, expected "from" 1 | import React from 'r ...

Struggling to make Cypress react unit testing run smoothly in a ReactBoilerplate repository

I have been struggling for the past 5 hours, trying to figure out how to make everything work. I even recreated a project's structure and dependencies and turned it into a public repository in hopes of receiving some assistance. It seems like there mi ...

Why does TypeScript keep throwing the "No inputs were found in the config file" error at me?

Why am I receiving the No inputs were found in config file error from TypeScript? I have set up my tsconfig.json in VS Code, but the error occurs when I try to build it. The terminal displays: error TS18003: No inputs were found in config file '/Use ...

I'm looking for the configuration of function definitions for the Jasmine npm module within an Angular project. Can

When a new Angular project is created, the *.spec.ts files provide access to Jasmine functions such as "describe", "beforeEach", and expect. Despite not having an import clause for them in spec.ts files, I can click on these functions and navigate to their ...

Error in Angular Apollo V3: Jest unable to locate module 'apollo-angular'

After recently updating angular apollo from version 2.6.0 to v3.0.0, my tests have been broken. I use jest for unit testing, and although the application compiles and runs without any issues, my tests cannot import any dependencies from 'apollo-angul ...

Retrieve a type from a Union by matching a string property

Looking at the following structure: type Invitation = | { __typename?: 'ClientInvitation' email: string hash: string organizationName: string } | { __typename?: 'ExpertInvitation' email: strin ...