Home Reference Source

src/utils/attach.js

import { Writable } from 'stream'
import Augment from '../utils/augment'
import { stripMetadata } from '../utils/metadata'
import errors from '../data/errors'
import config from '../config'
import debug from './debug'

/**
 * Attaches a transport stream to a writeable stream.
 *
 * @param {Array} transports - array of transports to attach to the stream
 * @param {Writable} toStream - the stream your transport will attach to
 * @param {Object} options - configuration options
 * @param {boolean} options.applyBackPressure
 */
const attach = (transports, toStream, { applyBackPressure = false } = {}) => {
  // Ensure all the streams are Writable
  for (let i = 0; i < transports.length; i++) {
    if (!(transports[i] instanceof Writable)) {
      throw new Error(errors.attach.notWritable)
    }
  }

  // Store refs to standard logging utilities
  const originalWrite = toStream.write

  debug(`attaching ${transports.length} transports to stream`)

  toStream.write = (message, encoding, fd) => {
    const log = message instanceof Augment ? message : new Augment(message)

    for (let i = 0; i < transports.length; i++) {
      const transport = transports[i]

      const written = transport.write(
        transport.acceptsObject ? log.data : log.data.message,
        encoding,
        fd
      )

      if (!written && applyBackPressure) {
        transport.once('drain', () => transport.write(...arguments))
      }
    }

    // When writing the log to the original stream,
    // strip the metadata if we're not in production
    originalWrite.apply(toStream, [
      process.env.NODE_ENV === 'production'
        ? log.data.message
        : stripMetadata(log.data.message),
    ])
  }

  return {
    detach: () => {
      toStream.write = originalWrite
    },
  }
}

export default attach