[![Build Status](https://travis-ci.org/reactgular/logger.svg?branch=develop)](https://travis-ci.org/reactgular/logger)
[![Coverage Status](https://coveralls.io/repos/github/reactgular/logger/badge.svg?branch=develop)](https://coveralls.io/github/reactgular/logger?branch=develop)
[![npm version](https://badge.fury.io/js/%40reactgular%2Flogger.svg)](https://badge.fury.io/js/%40reactgular%2Flogger)

## What is Logger?

Logger is a small Angular service for writing output to the browser's console. It helps make
console messages easier to filter by prefixing messages with the current class name. So if you have a component named `MainComponent` you
can filter by `Main:` and see only console messages from that component.

> Logger extends console so messages continue to display the current *filename* and *line number*.

For example;

```typescript
@Component({...})
export class MainComponent implements OnInit {
   private _log: LogService;
   
   private _subject: Subject<string> = new Subject();
   
   public constructor(log: LogService) {
      this._log = log.withPrefix(MainComponent.name);
   }
   
   public ngOnInit() {
      this._log.debug('Hello world!');
      // ^^^ outputs "Main: Hello world!"
   }
}
```

## Table Of Contents

- [What is Logger?](#what-is-logger)
- [Table Of Contents](#table-of-contents)
- [Why another console logger for Angular?](#why-another-console-logger-for-angular)
  * [Simple](#simple)
- [Installation](#installation)
- [LoggerConfig](#loggerconfig)
- [LogService](#logservice)
- [LogService Prefixes](#logservice-prefixes)
- [LogService Methods](#logservice-methods)
  * [LogService.debug()](#logservicedebug)
  * [LogService.error()](#logserviceerror)
  * [LogService.info()](#logserviceinfo)
  * [LogService.warn()](#logservicewarn)
  * [LogService.getPrefix()](#logservicegetprefix)
  * [LogService.setPrefix()](#logservicesetprefix)
  * [LogService.withPrefix()](#logservicewithprefix)

## Why another console logger for Angular? 

I've been copying and pasting the same log service between projects for several years. Everything else I tried
was either too complicated or *erased* the *file name* and *line number* from the browser's console output, and I just kept reusing my trusty
logger code. I decided it was time to make it a library that could be easily installed and reused.

### Simple

Logger works exactly the same as the *console* object in your browser. The only differences are:

- you have to inject LogService
- you have to give it a prefix

It can be added to your classes quickly with an extra parameter on the constructor and two more lines of code. I feel that it
greatly improves the readability of the console messages making this small extra work worthwhile.

For example;

```typescript
@Component({..})
export class MainComponent {
   private _log: LogService;
   
   constructor(log: LogService) {
      this._log = log.withPrefix(MainComponent.name);
   }
}
```

The prefix value can be anything that you want, but using `MainComponent.name` means that the value will be 
updated if you rename the class using an IDE that automatically updates all usages.

## Installation

To get started, install the package from npm.

```bash
npm install @reactgular/logger
```

then in `app.module.ts`, import the `LoggerModule`:

```typescript
import {NgModule} from '@angular/core';
import {LoggerModule} from '@reactgular/logger';

@NgModule({
    imports: [
        LoggerModule.forRoot({enabled: true})
    ]
})
export class AppModule {}
```

When you include the module in the import, you can pass a configuration object of type LoggerConfig.
If you are lazy loading, you can just use the `LoggerModule` module.

Options such as `enabled` can be passed to the module as the second argument in the `forRoot` method. When `enabled` is
set to *false* the log service gets replaced with a tiny *proxy* service and outputs nothing.

It's important for you add `LoggerModule.forRoot()` at the root of your modules.

## LoggerConfig

You can provide a config object of type `LoggerConfig`, as the first parameter for `LoggerModule.forRoot()`.

```typescript
@NgModule({
  imports: [
    LoggerModule.forRoot({
      console: window.console,
      enabled: !environment.production,
      levels: LOGGER_LEVEL.DEBUG | LOGGER_LEVEL.ERROR | LOGGER_LEVEL.INFO | LOGGER_LEVEL.LOG | LOGGER_LEVEL.WARN,
      tails: ['Component', 'Directive', 'Service', 'Factory', 'Pipe', 'Module', 'Resolver', 'Provider']
    })
  ]
})
export class AppModule {}
```

## LogService

The `LogService` object provides access to the browser's debugging console, because the specifics of how the console works
across different browsers varies the available methods are `debug()`, `log()`, `info()`, `error()` and `warn()`.

```typescript
constructor(log: LogService) {
   log.info('The constructor method was executed.');
}
```

## LogService Prefixes

When you're using the `LogService` with Angular classes like components, services, pipes, etc. The name of those classes can be used to set the
prefix string for each log message to the console. Using a prefix value of `"MainComponent"` can create *wide* console messages. So this function
creates a new `LogService` object with a *trimmed* prefix where the *tail* strings have been removed.

For example;

The following prefix `"MainComponent"` will be rewritten to `"Main"`.

```typescript
@Component({...})
export class MainComponent {
   private _log: LogService;
   constructor(log: LogService) {
      this._log = log.withPrefix(MainComponent.name);
   }
}
```

When you set the `tails` option in the `LoggerConfig` it replaces all the tails that are removed from prefixes. If you don't define an
array of strings to `fails` then these default values will be used.

```typescript
/**
 * Defaults list of tails to remove.
 */
export const LOGGER_TAILS_DEFAULT = ['Component', 'Directive', 'Service', 'Factory', 'Pipe', 'Module', 'Resolver', 'Provider'];
```

If you want to add additional tails to be removed you can configure the logger like this:

```typescript
import {LoggerModule, LOGGER_TRAILS_DEFAULT} from '@reactgular/logger';

@NgModule({
  imports: [
    LoggerModule.forRoot({
      tails: [...LOGGER_TAILS_DEFAULT, 'FooBar', 'Magic', 'Proxy']
    })
  ]
})
export class AppModule {}

```

## LogService Methods

This section documents methods available on the `LogService` object and gives a few usage examples.

### LogService.debug()

Outputs a message to the console with the log level "debug".

This method can be disabled by excluding `LOGGER_LEVEL.DEBUG` from the `levels` property of `LoggerConfig`.

> Starting with Chromium 58 this method only appears in Chromium browser consoles when level "Verbose" is selected.

### LogService.error()

Outputs an error message. You may use [string substitution](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions) and additional arguments with this method.

This method can be disabled by excluding `LOGGER_LEVEL.ERROR` from the `levels` property of `LoggerConfig`.

### LogService.info()

Informative logging of information. You may use [string substitution](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions) and additional arguments with this method.

This method can be disabled by excluding `LOGGER_LEVEL.INFO` from the `levels` property of `LoggerConfig`.

### LogService.warn()

Outputs a warning message. You may use [string substitution](https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions) and additional arguments with this method.

This method can be disabled by excluding `LOGGER_LEVEL.WARN` from the `levels` property of `LoggerConfig`.

### LogService.getPrefix()

Returns the prefix string used by the `LogService` object.

### LogService.setPrefix()

Sets a new prefix for the logger. This will change the *internal* prefix value used by the `LogService`. This function does not have the same
effect as `withPrefix()` which returns a new `LogService` object with a trail strings removed for the prefix.

### LogService.withPrefix()

Creates a new `LogService` object with the given prefix. 
