Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

acquia/ember-logging-service

Repository files navigation

ember-logging-service Build Status

This addon provides a general and extensible logging service that can be used throughout your application. This addon by itself will provide a basic logging service that can be used to trigger log events as well as register consumers to listen for events.

Example consumers include:

Installation

The addon can be installed using standard ember-cli syntax:

ember install ember-logging-service

Basic usage

The core functionality of ember-logging-service is a logging service that can be injected using Ember's standard dependency injection functionality.

import Ember from 'ember';

export default Ember.Component.extend({
  logger: Ember.inject.service(),

  trackSomethingAwesome() {
    this.get('logger').info('Something awesome happened!!!', { who: 'Kermit' });
  }
});

Concepts

Triggering events

The logging service categorizes each event with a 'level' and a 'tag'. The level is meant as an indicator of the severity. Currently the supported levels are: info, warning, and error. These values are defined on the "levels" property of the logger service. A tag is meant as a general user-defined categorization of a class of events.

For example, events tracking user behavior could all be tagged with 'user' such that a user login would be triggered with the level of "info" and the tag of "user". To trigger this type of event:

this.get('logger').info('user', 'Log in');

Similarly, navigation events could be tracked as: this.get('logger').info('navigation', 'About')

Helper functions are provided for each level for logging events. Each function can optionally accept additional data to be sent along with the event.

let logger = this.get('service');
logger.info('user', 'Log out');
logger.warning('user', 'Cancelled save');
logger.error('error', 'API authorization error', { status: 403, foo: bar });

Event consumers

Consumers can register with the logging service to listen for any events matching the a specific combination of event level and event tags. For example, one output may only care about error events and handle them accordingly by sending to Bugsnag or writing to a log. Other tracking systems may care about user interaction events for UX analyzation.

A consumer can be registered with the logger by minimally providing an id, a callback for events, a list of levels, and a list of tags.

For example: this.get('logger').registerConsumer('muppets', happyFunc, 'info', ['sesame', 'muppets', monsters']);

Typically consumers are registered with application instance initializers within a consumer addon.

When an event is sent to the logger service that matches the level and tag combination for a consumer, the consumer's callback function is triggered with a structured event and the context of the application at the time of the event (more below).

The event is structured with the following data:

  • name: the name of the event trigger
  • type: the tag associated with the event
  • level: the severity level (info, warn, error)
  • metadata: any additional data passed when the event was triggered

The context object is structured with the following keys:

  • application: Any application-specific context provided
  • user: Any user-specific context provided

Application/User Context

The logger service can automatically include application and user context along with each event. This is the second parameter sent to the consumer callback mentioned above. Because this information is specific to an application, it is generated by the application that consumes the logger service. The logger service allows the registration of one or more application context callbacks and user context callbacks. These callbacks are executed with each event to generate a POJO of contextual information that can be used to provide additional context to consumers. For example, it may be useful to provide customer API keys or the current route within the application to give context to a navigation or error event.

Both types of callbacks do not accept any parameters and return a POJO of custom information.

After installing the ember-logging-service addon an application instance initializer is automatically created at app/instance-initializers/register-logging-context.js

This provides a sample registration of empty application and user context callbacks. This can be used as a guide to provide your own data into the placeholder callbacks or to register your own service functions to provide the data.

Automatic Error Monitoring

When error handling is turned on, the logging service will automatically monitor any uncaught Ember or RSVP errors and send them as error level events.

Configuration

To enable ember-logging-service for an environment, include the following configuration information in your config/environment.js:

ENV['ember-logging-service'] {
  enabled: true
}

To enable ember-logging-service to handle basic error monitoring for an environment then include this additional property:

ENV['ember-logging-service'] {
  enabled: true,
  errorsEnabled: true
}

Constants

It can be useful to refer to levels, tags, and events as variables rather than hard-coding the values in your code. The service already provides the ability to refer to tags and levels by variable names rather than hard-coded strings.

For example:

  • this.get('logger.levels.info')
  • this.get('logger.levels.warn')
  • this.get('logger.levels.error')

If the logger is tracking the following tags: navigation, interaction, error:

  • this.get('logger.tags.navigation')
  • this.get('logger.tags.interaction')
  • this.get('logger.tags.error')

Consider an example where you are tracking a user interaction event for a usability tracking system as "Menu navigation", but for purposes of reporting, you UX department now requires you to track the event as "Interaction - navigation - menu". If you had been tracking this event in multiple places as this.get('logger').info(this.get('logger.tags.interaction'), 'Menu navigation') you would need to update this event name in multiple places.

You could handle this in a couple of ways:

  • Maintain a list of strings on paper :(
  • Create a configuration of events in JSON format
  • Utilize an Ember service to define constant values

The logger service provides an optional mechanism to help with this. If an object of event data is passed in the configuration, the logger will automatically register all of the tags and add the events into an object for easy reference.

Example configuration:

ENV['ember-logging-service'] {
  enabled: true,
  events: {
    navgiation: {
      ABOUT: 'About us',
      HOME: 'Home',
      CONTACT: 'Contact'
    },
    muppets: {
      KERMIT: 'Kermie',
      PIGGY: 'Piggy',
      SWEDISH_CHEF: 'Swedish Chef'
    }
  }
}

With the above, all of the events will be available from the logger service based on their tag:

let logger = this.get('logger');
console.log(logger.get('events.navigation.ABOUT')); // About us
console.log(logger.get('events.muppets.KERMIT')); // Kermie

This is not required for setting up the logger service and is only provided as a convenience mechanism.

Developing for ember-logging-service

Installation

  • git clone git@github.com:acquia/ember-logging-service.git this repository
  • cd ember-logging-service
  • npm install
  • bower install

Running

Running Tests

  • npm test (Runs ember try:each to test your addon against multiple Ember versions)
  • ember test
  • ember test --server

Building

  • ember build

For more information on using ember-cli, visit https://ember-cli.com/.