Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add $log like functionality to Angular 2 #5458

Closed
juristr opened this Issue Nov 24, 2015 · 40 comments

Comments

Projects
None yet
@juristr
Copy link
Contributor

commented Nov 24, 2015

Directly writing console.log statements throughout the apps codebase is bad as you don't have any possibility to centrally deactivate it.

Are there any plans on integrating a $log like feature in Angular2, or even something a bit more advanced. I've quickly seen diary.js but it seems abandoned.

@robwormald

This comment has been minimized.

Copy link
Member

commented Nov 24, 2015

Not bad idea. Diary is a pretty simple lib, and should still work (with a bit of tinkering) - might be worth bringing into the main repo (and adding Dart support?) @IgorMinar ?

@jamesmorgan

This comment has been minimized.

Copy link

commented Feb 27, 2016

I am surprised I couldn't find a $log equalivant in angular? +1 for adding this feature.

@zoechi

This comment has been minimized.

Copy link
Contributor

commented Feb 28, 2016

In Dart it's print() and it can be redefined in zones.

@blaster151

This comment has been minimized.

Copy link

commented Mar 2, 2016

I concur, this is needed.

@cviccaro

This comment has been minimized.

Copy link

commented Mar 9, 2016

+1 I would like to see this as well. Currently I am trying to create my own LogService.. but am running into a problem wherein the file/line referenced in the console.log is that of the log.service.js file, and not the original file. Until I can solve that problem, I'll just be forced to use the global console everywhere. Anyone have any ideas?

consoleLog() and formatError() come from A1 (slightly modified for ES6):

export class LogService {

    enabled = true;

    constructor() {
        this.enabled = '<%= ENV %>' === 'dev';
        var methods = ['assert', 'debug', 'error', 'info', 'log', 'trace', 'warn'];
        methods.forEach((method) => {
            this[method] = this.consoleLog(method);
        });
    }

    assert(message) {
        //
    }
    debug(message, ...args) {
        //
    }
    error(message, ...args) {
        //
    }
    info(message, ...args) {
        //
    }
    log(message, ...args) {
        //
    }
    trace(message, ...args) {
        //
    }
    warn(message, ...args) {
        //
    }

    private formatError(arg) {
      if (arg instanceof Error) {
        if (arg.stack) {
          arg = (arg.message && arg.stack.indexOf(arg.message) === -1)
              ? 'Error: ' + arg.message + '\n' + arg.stack
              : arg.stack;
        } else if (arg.sourceURL) {
          arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
        }
      }
      return arg;
    }

    private consoleLog(type) {
        if (this.enabled) {
            let console = window.console || {},
              logFn = console[type] || console.log || noop,
              hasApply = false;

            let formatError = this.formatError;
            // Note: reading logFn.apply throws an error in IE11 in IE8 document mode.
            // The reason behind this is that console.log has type "object" in IE8...
            try {
                hasApply = !!logFn.apply;
            } catch (e) {
                //
            }

            if (hasApply) {
                return function(...args) {
                    var _args = [];
                    args.forEach(function(arg) {
                        _args.push(formatError(arg));
                    });
                    return logFn.apply(console, _args);
                };
            }
            // we are IE which either doesn't have window.console => this is noop and we do nothing,
            // or we are IE where console.log doesn't have apply so we log at least first 2 args
            return function(arg1, arg2) {
                logFn(arg1, arg2 === null ? '' : arg2);
            };
        }
        return function() {
            //
        };
    }
}


@sebastianovide

This comment has been minimized.

Copy link

commented Mar 12, 2016

+1 for $log equivalent

@jstuparitz

This comment has been minimized.

Copy link

commented Mar 29, 2016

+1 for $log

@seenimurugan

This comment has been minimized.

Copy link

commented Apr 22, 2016

+1 for $log equivalent

@juristr

This comment has been minimized.

Copy link
Contributor Author

commented Apr 26, 2016

I didn't look into what diary.js does, yet, but given the reactions from people we should maybe revive it? @robwormald ?

@marcalj

This comment has been minimized.

Copy link

commented Jun 29, 2016

Use the thumbs up button on first comment please!

@simpss

This comment has been minimized.

Copy link

commented Jul 10, 2016

After finding this request, I walked the internets and found this little library: https://github.com/koroandr/log4ts The docs aren't that good, but the source is easy to understand.

npm install log4ts --save

created a small wrapper around it. For some reason ngOnInit didn't fire so the initialization has to be called manually for now. This can surely be improved, I threw it together just to quickly test the library.

log level config:

import {LogLevel} from "log4ts/build/LogLevel";

export class AppConf {
    public static get LOG_LEVEL(): LogLevel { return LogLevel.ALL; }
}
import {Injectable} from '@angular/core';

import Logger from "log4ts/build/Logger"
import LoggerConfig from "log4ts/build/LoggerConfig"
import BasicLayout from "log4ts/build/layouts/BasicLayout";
import ConsoleAppender from "log4ts/build/appenders/ConsoleAppender";
import {IAppender} from "log4ts/build/IAppender";
import {ILayout} from "log4ts/build/ILayout";
import {LogLevel} from "log4ts/build/LogLevel";
import {AppConf} from "../../config/app.conf";

@Injectable()
export class LogService{

    public log: Logger;

    private appender: IAppender;
    private layout: ILayout;
    private config: LoggerConfig;

    constructor() {

    }

    init(){
        this.layout = new BasicLayout();
        this.appender = new ConsoleAppender();
        this.appender.setLayout(this.layout);
        this.config = new LoggerConfig(this.appender);
        this.config.setLevel(AppConf.LOG_LEVEL);
        this.log = new Logger();
        Logger.setConfig(this.config);
    }
}

and usage:

this.logService.log("Something that interests you");
this.logService.log.info("Something that interests you");
this.logService.log.fatal("Something that interests you");
this.logService.log.error("Something that interests you");
this.logService.log.debug("Something that interests you");
this.logService.log.warn("Something that interests you");
this.logService.log.trace("Something that interests you");
@astec

This comment has been minimized.

Copy link

commented Jul 11, 2016

@simpss too many dots to call, probably would be better if usage was something like:

this.logInfo("Something that interests you");
this.logFatal("Something that interests you");
this.logError("Something that interests you");
this.logDebug("Something that interests you");
this.logWarn("Something that interests you");
this.logTrace("Something that interests you");
@gorilla77

This comment has been minimized.

Copy link

commented Jul 12, 2016

@cviccaro You can use this to get the "correct" line number:

info = console.info.bind(console);
info("Log me");
@cviccaro

This comment has been minimized.

Copy link

commented Jul 13, 2016

@gorilla77 Thanks! I used it like this:

export class LoggerService {
    get log() {
        return console.log.bind(console);
    }

It was the only way I found I could get the appropriate line number to show up. I didn't realize what you wanted to do is to return the bound function from the logger service. I was, at first, trying to return an anonymous function like Angular1's logger.

@juristr

This comment has been minimized.

Copy link
Contributor Author

commented Aug 10, 2016

Ben Nadel (@bennadel) just published an article about this topic. Might be interesting for some of you: http://www.bennadel.com/blog/3129-implementing-a-log-inspired-logging-service-in-angular-2-rc-4.htm

@skdhir

This comment has been minimized.

Copy link

commented Jan 13, 2017

So is this feature implemented and available in new version? not very clear from comments.

@MickL

This comment has been minimized.

Copy link

commented Jan 31, 2017

@cviccaro Sorry i don't get it. How can you log a string without any arguments in log()?

I tried:

log(message) {
   // Server-side logging here
    return console.log(message);
  }

But i dont see correct line numbers. If i use console.log.bind(message) i dont see any console.log at all.

@cviccaro

This comment has been minimized.

Copy link

commented Jan 31, 2017

@MickL Sorry, that was a bit old. Try this approach to get correct line numbers:

import { Injectable } from '@angular/core';

@Injectable()
export class LoggerService {
	enabled = true;
	noop = () => {};

	constructor() {
                // You can do a check on your environment or some other flag to 
                // enable/disable logging
		// if ((<any>'<%= ENV %>') === 'prod') this.enabled = false;
	}

	get debug() {
		if (this.enabled) return console.debug.bind(console);
		return this.noop;
	}

	get error() {
		if (this.enabled) return console.error.bind(console);
		return this.noop;
	}

	get log() {
		if (this.enabled) return console.log.bind(console);
		return this.noop;
	}

	get info() {
		if (this.enabled) return console.info.bind(console);
		return this.noop;
	}

	get warn() {
		if (this.enabled) return console.warn.bind(console);
		return this.noop;
	}

}
@MickL

This comment has been minimized.

Copy link

commented Jan 31, 2017

I still dont get it. How can you call this.logger.log('HELLO WORLD'); if this is only a get function without any arguments? How can it know about 'HELLO WORLD'? Also i want to do more with this string like server side logging. But how without arguments?

@cviccaro

This comment has been minimized.

Copy link

commented Jan 31, 2017

@MickL ES6 Javascript can have properties with getters. They are useful for computed properties and bound functions. So when you instantiate the LoggerService, log is actually a property of it, which returns a properly bound console.log function ready to be used. So.. LoggerService.log is property that returns a function but is not a function in and of itself. To clarify, a simple example component:

export class SomeComponent {

constructor(private logger: LoggerService) {}

ngOninit() {
// Log variable will now be properly bound console.log function.  If you console.log this variable, you'll see the function outputted as a string.
let log = this.logger.log;

// The variable can then be used as a function
log('SomeComponent has initialized', this);

// But you'll use it this way.  The previous 2 lines of code were to help clarify how it works.
this.logger.log('SomeComponent has initialized.', this);


}

}
@MickL

This comment has been minimized.

Copy link

commented Jan 31, 2017

Oh i target ES5 :/

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 10, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 11, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 15, 2017

DzmitryShylovich added a commit to DzmitryShylovich/angular that referenced this issue Feb 15, 2017

@uberspeck

This comment has been minimized.

Copy link

commented Feb 24, 2017

@cviccaro , i've implemented your logger and I'm getting an error...

undefined is not an object (evaluating '_this.logger.log')

My implementation...

import { Pipe, PipeTransform } from '@angular/core';

import { LoggerService } from '../../../logger/logger.service';

@Pipe({
  name: 'afterDate'
})
export class AfterDatePipe implements PipeTransform {

  constructor(
    private logger: LoggerService
  ){ }

  transform(items:Array<any>, date): Array<any> {
    return items.filter( (item, index, array) => {
      this.logger.log('testing', this);
    });
  }

}

EDIT
I should add that I'm importing it into my AppModule and added the LoggerService to the providers array

@4nandP 4nandP referenced this issue Mar 28, 2017

Open

log source #15

@RainingNight

This comment has been minimized.

Copy link

commented Apr 21, 2017

+1 for $log equivalent

@k1r0s

This comment has been minimized.

Copy link

commented Jun 1, 2017

Hey guys, just keep an eye on this, it could be use to loggin, but many many use cases too

https://stackoverflow.com/questions/39407298/how-to-implement-aop-in-angular-2/44290042#44290042

@samudurand

This comment has been minimized.

Copy link

commented Jun 2, 2017

any update on a logging service in Angular 2 ?

@Toxicable Toxicable referenced this issue Jun 10, 2017

Closed

feat(core): introduce Logger Service #17399

2 of 3 tasks complete
@harikrishnan-u01

This comment has been minimized.

Copy link

commented Jul 27, 2017

Is there any fix planned for implementing $log as part of Angular 5 release?

@jesujcastillom

This comment has been minimized.

Copy link

commented Aug 2, 2017

+1

@mtpultz

This comment has been minimized.

Copy link

commented Aug 2, 2017

Can you please stop using +1 and just hit subscribe, and/or add an emote to peoples responses where you agree or disagree. This +1-itis drives everyone crazy with useless notifications while we all patiently wait for features that are marked for implementation at some point based on the issues labels. This is why subscribe and emotes were added. Yes, everyone wants this feature you're not adding any weight to the conversation unless you're providing some sort of insight into implementation. Lets try and make the next notification for this feature be the actual closing of the issue.

@Toxicable

This comment has been minimized.

Copy link
Contributor

commented Aug 3, 2017

The implementation of this issue is currently blocked on the fact that Services are not easily tree shakable see here:
#17399 (review)
Feel free to suggest a designed where these issues have been reduce if you want to seee this in core sooner.

@Anish895

This comment has been minimized.

Copy link

commented Dec 22, 2017

how to generate .log extension in angular 4 .. Is there any possible way to create and use??

@ngbot ngbot bot added this to the Backlog milestone Jan 23, 2018

@splincode

This comment has been minimized.

Copy link
Contributor

commented Jul 26, 2018

@juristr Is the issue relevant?

@ocombe

This comment has been minimized.

Copy link
Contributor

commented Jul 26, 2018

@splincode please stop spamming old issues asking if they are still relevant, I assume that you have good intentions, but it's annoying.

@splincode

This comment has been minimized.

Copy link
Contributor

commented Jul 26, 2018

@ocombe I just wanted to know whether to close the old tasks, if they are not relevant
mhevery Recently closed several obsolete tasks, thanks to this

@juristr

This comment has been minimized.

Copy link
Contributor Author

commented Jul 26, 2018

It's somehow relevant but it's an old issue and I think ppl have found other ways (i.e. external libs or custom impl) and moved ahead. I'm closing this as there are way more important features to be implemented 🙂

For those interested, creating a custom logger could look like this one here:
https://github.com/angular/angular/blob/master/aio/src/app/shared/logger.service.ts

@juristr juristr closed this Jul 26, 2018

@splincode

This comment has been minimized.

Copy link
Contributor

commented Jul 26, 2018

@juristr Thank you for having responded, I am grateful to you!!!

Also I develop an improved version of the logging for Angular
https://github.com/splincodewd/client-logger

@msalehisedeh

This comment has been minimized.

Copy link

commented Jan 19, 2019

looks like this conversation halted back in July and i am a late comer in this conversation. But, checkout @sedeh/smart-console on npm and let me know what you think.
Live demo is on https://smart-console.stackblitz.io/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.