1
\$\begingroup\$
//App.jsx
import React, { Component } from 'react';
import { initialiseLogger } from './logger';

class App extends Component {
  constructor(props) {
    super(props);
    initialiseLogger(props.environment);
  }
  render() {
    return (
      <Component />
    );
  }
}

export default App;

This it he top level of my React app. I initialise my logger here. And below is the logger. I am using our ui logger by my project. It exposes one function called configure that creates a logger based on some params. Each time it gets called it will create a new logger.

//logger.js
import LoggerFactory from '@company/ui-logger';
import appConfigurations from '../shared/appConfigurations';

const loggerContainer = {};

const initialiseLogger = (env) => {
  const url = appConfigurations.getLogUrl(env);
  const service = appConfigurations.getLogUrl(env);
  const version = appConfigurations.getComponentVersion(env);
  const apigeeClientId = appConfigurations.getComponentName(env);
  Object.freeze(
      Object.assign(
        loggerContainer,
        { logger: LoggerFactory.configure({ url, service, version, apigeeClientId }) }
      )
    );
  return loggerContainer.logger;
};
const getLogger = () => {
  if (!loggerContainer.logger) {
    // eslint-disable-next-line no-console
    console.error('A logger has not been initialised');
  }
  return loggerContainer.logger;
};

export { initialiseLogger, getLogger };

As you can see initialiseLogger gets some app config and creates a logger which then gets assigned inside a const object that then becomes immutable. I also expose a getLogger method that is going to be used in the other components to get the logger and then log what they want.

Example:

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { getLogger } from '../logger';

class ErrorBox extends Component {
  constructor() {
    super();
    this.state = {
      isVisible: false,
      apiErrors: [],
      uiErrors: []
    };
    this.logger = getLogger();
  }

  componentDidMount() {
    ...
  }

  componentWillUnmount() {
    ...
  }

  updateErrorList = () => {
    ...
  }

  componentDidCatch(error) {
    this.setState({
      isVisible: true,
      uiErrors: [error]
    });

    this.logger.error(
      { message: error.message },
      error.stack
    );
  }


  render() {
    ...
  }
}

export default ErrorBox;

I am not feeling 100% sure about this code. Should I go for a singleton pattern and just expose the getLogger function.

Something like

import LoggerFactory from '@company/ui-logger';
import appConfigurations from '../shared/appConfigurations';

const loggerContainer = {};

const initialiseLogger = (env) => {
  const url = appConfigurations.getLogUrl(env);
  const service = appConfigurations.getLogUrl(env);
  const version = appConfigurations.getComponentVersion(env);
  const apigeeClientId = appConfigurations.getComponentName(env);
  Object.freeze(
      Object.assign(
        loggerContainer,
        { logger: LoggerFactory.configure({ url, service, version, apigeeClientId }) }
      )
    );
  return loggerContainer.logger;
};
const getLogger = () => {
  if (!loggerContainer.logger) {
    initialiseLogger('env');
  }
  return loggerContainer.logger;
};

export default getLogger;

Or even

import LoggerFactory from '@company/ui-logger';
import appConfigurations from '../shared/appConfigurations';

const Logger = () => {
  let instance;

  const initialiseLogger = (env) => {
    const url = appConfigurations.getLogUrl(env);
    const service = appConfigurations.getLogUrl(env);
    const version = appConfigurations.getComponentVersion(env);
    const apigeeClientId = appConfigurations.getComponentName(env);
    return LoggerFactory.configure({ url, service, version, apigeeClientId });
  };

  return {
    getLogger() {
      if (!instance) {
        instance = initialiseLogger('env');
      }
      return instance;
    }
  };
};

export default Logger();

But i am not sure about my design of this singleton. Would the instance be visble to getLogger when I export it as a module to another compoent?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.