All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.util.events.Sink.scala Maven / Gradle / Ivy

The newest version!
package com.twitter.util.events

import com.twitter.app.GlobalFlag
import com.twitter.util.events.Event.Type

// Note: these flags should generally be specified via System properties
// to ensure that their values are available very early in the application's
// lifecycle.
private[events] object sinkEnabled extends GlobalFlag[Boolean](
  true,
  "Whether or not event capture is enabled. Prefer setting via System properties.")

private[events] object approxNumEvents extends GlobalFlag[Int](
  10000,
  "Approximate number of events to keep in memory. Prefer setting via System properties.")

/**
 * Where runtime events such as logging, stats and tracing can be
 * sent to allow for analysis.
 *
 * '''Note:''' while the API is public it should be considered as experimental
 * and subject to changes.
 *
 * ===Design notes===
 *  - Implementations must be thread-safe.
 *  - Implementations should have very low runtime overhead such that as
 *    many events as possible can be sent here. In particular, object
 *    allocations should be kept to a minimum.
 *  - `event` is expected to be called many orders of magnitude
 *    more frequently than `events`.
 */
trait Sink {

  /**
   * Event input is captured as individual fields in service of
   * avoiding an allocation to wrap the event.
   *
   * Note that callers should check [[recording]] before calling
   * into this method:
   *
   * {{{
   *   if (sink.recording) {
   *     sink.event(...)
   *   }
   * }}}
   */
  def event(
    etype: Event.Type,
    longVal: Long = Event.NoLong,
    objectVal: Object = Event.NoObject,
    doubleVal: Double = Event.NoDouble,
    traceIdVal: Long = Event.NoTraceId,
    spanIdVal: Long = Event.NoSpanId
  ): Unit

  /**
   * Returns all currently available events.
   *
   * '''Note:''' the events are not returned in any particular order.
   */
  def events: Iterator[Event]

  /**
   * Whether or not this [[Sink sink]] should be recording events.
   *
   * This is external to the [[event()]] and managed by caller because
   * there is some expense in capturing the data sent to that call.
   *
   * The expectation is for callers to do:
   * {{{
   *   if (sink.recording) {
   *     sink.event(...)
   *   }
   * }}}
   */
  def recording: Boolean = true

  /**
   * Update the current state of [[recording]].
   *
   * For Java compatibility see [[setRecording]].
   */
  def recording_=(enabled: Boolean): Unit = ()

  /**
   * Update the current state of [[recording]].
   *
   * Java compatibility for [[recording_=]].
   */
  def setRecording(enabled: Boolean): Unit = recording_=(enabled)

}

/**
 * Note: There is a Java-friendly API for this object: [[com.twitter.util.events.Sinks]].
 */
object Sink {

  /**
   * A sink that ignores all input.
   */
  val Null: Sink = new Sink {
    override def event(
      etype: Type,
      longVal: Long,
      objectVal: Object,
      doubleVal: Double,
      traceIdVal: Long,
      spanIdVal: Long
    ): Unit = ()

    override def events: Iterator[Event] = Iterator.empty
  }

  /**
   * An unsized sink. Convenient for testing.
   */
  def of(buffer: scala.collection.mutable.Buffer[Event]): Sink =
    new Sink {
      def events = buffer.iterator
      def event(e: Event.Type, l: Long, o: Object, d: Double, t: Long, s: Long) =
        buffer += Event(e, com.twitter.util.Time.now, l, o, d, t, s)
    }

  // exposed for testing
  private[events] def newDefault: Sink = {
    if (!sinkEnabled.apply()) {
      Null
    } else if (approxNumEvents() <= 0) {
      Null
    } else {
      SizedSink(approxNumEvents())
    }
  }

  /**
   * The global default `Sink`.
   */
  val default: Sink = newDefault

  // Java compatibility.
  private[events] val getDefault: Sink = default

  /**
   * Returns whether or not any event capture is enabled.
   * Note that this does not necessarily mean that events
   * are being [[Sink.recording recorded]], it only means
   * there is a place to store recorded events.
   */
  def enabled: Boolean = default ne Null
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy