blob: 463e3f31c150d85b4dbfe906cd04382f708841e5 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.openwhisk.common
import java.io.PrintStream
import java.time.{Clock, Instant, ZoneId}
import java.time.format.DateTimeFormatter
import akka.event.Logging._
import akka.event.LoggingAdapter
import kamon.Kamon
import kamon.metric.{MeasurementUnit, Counter => KCounter, Gauge => KGauge, Histogram => KHistogram}
import kamon.statsd.{MetricKeyGenerator, SimpleMetricKeyGenerator}
import kamon.tag.TagSet
import org.apache.openwhisk.core.entity.ControllerInstanceId
trait Logging {
/**
* Prints a message on DEBUG level
*
* @param from Reference, where the method was called from.
* @param message Message to write to the log if not empty
*/
def debug(from: AnyRef, message: => String)(implicit id: TransactionId = TransactionId.unknown) = {
if (id.meta.extraLogging) {
emit(InfoLevel, id, from, message)
} else {
emit(DebugLevel, id, from, message)
}
}
/**
* Prints a message on INFO level
*
* @param from Reference, where the method was called from.
* @param message Message to write to the log if not empty
*/
def info(from: AnyRef, message: => String)(implicit id: TransactionId = TransactionId.unknown) = {
emit(InfoLevel, id, from, message)
}
/**
* Prints a message on WARN level
*
* @param from Reference, where the method was called from.
* @param message Message to write to the log if not empty
*/
def warn(from: AnyRef, message: => String)(implicit id: TransactionId = TransactionId.unknown) = {
emit(WarningLevel, id, from, message)
}
/**
* Prints a message on ERROR level
*
* @param from Reference, where the method was called from.
* @param message Message to write to the log if not empty
*/
def error(from: AnyRef, message: => String)(implicit id: TransactionId = TransactionId.unknown) = {
emit(ErrorLevel, id, from, message)
}
/**
* Prints a message to the output.
*
* @param loglevel The level to log on
* @param id <code>TransactionId</code> to include in the log
* @param from Reference, where the method was called from.
* @param message Message to write to the log if not empty
*/
protected[common] def emit(loglevel: LogLevel, id: TransactionId, from: AnyRef, message: => String): Unit
}
/**
* Implementation of Logging, that uses Akka logging.
*/
class AkkaLogging(loggingAdapter: LoggingAdapter) extends Logging {
def emit(loglevel: LogLevel, id: TransactionId, from: AnyRef, message: => String) = {
if (loggingAdapter.isEnabled(loglevel)) {
val logmsg: String = message // generates the message
if (logmsg.nonEmpty) { // log it only if its not empty
val name = if (from.isInstanceOf[String]) from else Logging.getCleanSimpleClassName(from.getClass)
loggingAdapter.log(loglevel, format(id, name.toString, logmsg))
}
}
}
protected def format(id: TransactionId, name: String, logmsg: String) = {
val currentId = if (id.hasParent) s"[$id] " else ""
s"[${id.root}] $currentId[$name] $logmsg"
}
}
/**
* Implementation of Logging, that uses the output stream.
*/
class PrintStreamLogging(outputStream: PrintStream = Console.out) extends Logging {
override def emit(loglevel: LogLevel, id: TransactionId, from: AnyRef, message: => String) = {
val now = Instant.now(Clock.systemUTC)
val time = Emitter.timeFormat.format(now)
val name = if (from.isInstanceOf[String]) from else Logging.getCleanSimpleClassName(from.getClass)
val level = loglevel match {
case DebugLevel => "DEBUG"
case InfoLevel => "INFO"
case WarningLevel => "WARN"
case ErrorLevel => "ERROR"
case LogLevel(_) => "UNKNOWN"
}
val logMessage = Seq(message).collect {
case msg if msg.nonEmpty =>
msg.split('\n').map(_.trim).mkString(" ")
}
val currentId = if (id.hasParent) id else ""
val parts = Seq(s"[$time]", s"[$level]", s"[${id.root}]", s"[$currentId]") ++ Seq(s"[$name]") ++ logMessage
outputStream.println(parts.mkString(" "))
}
}
/**
* A triple representing the timestamp relative to which the elapsed time was computed,
* typically for a TransactionId, the elapsed time in milliseconds and a string containing
* the given marker token.
*
* @param token the LogMarkerToken that should be defined in LoggingMarkers
* @param deltaToTransactionStart the time difference between now and the start of the Transaction
* @param deltaToMarkerStart if this is an end marker, this is the time difference to the start marker
*/
case class LogMarker(token: LogMarkerToken, deltaToTransactionStart: Long, deltaToMarkerStart: Option[Long] = None) {
override def toString() = {
val parts = Seq(LogMarker.keyword, token.toStringWithSubAction, deltaToTransactionStart) ++ deltaToMarkerStart
"[" + parts.mkString(":") + "]"
}
}
object LogMarker {
val keyword = "marker"
/** Convenience method for parsing log markers in unit tests. */
def parse(s: String) = {
val logmarker = raw"\[${keyword}:([^\s:]+):(\d+)(?::(\d+))?\]".r.unanchored
val logmarker(token, deltaToTransactionStart, deltaToMarkerStart) = s
LogMarker(LogMarkerToken.parse(token), deltaToTransactionStart.toLong, Option(deltaToMarkerStart).map(_.toLong))
}
}
private object Logging {
/**
* Given a class object, return its simple name less the trailing dollar sign.
*/
def getCleanSimpleClassName(clz: Class[_]) = {
val simpleName = clz.getSimpleName
if (simpleName.endsWith("$")) simpleName.dropRight(1)
else simpleName
}
}
private object Emitter {
val timeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneId.of("UTC"))
}
/**
* Used to record log message and make a metric name.
*
* @param component Component like invoker, controller, and docker. It is defined in LoggingMarkers.
* @param action Action of the component.
* @param state State of the action.
* @param subAction more specific identifier for "action", like `runc.resume`
* @param tags tags can be used for whatever granularity you might need.
*/
case class LogMarkerToken(
component: String,
action: String,
state: String,
subAction: Option[String] = None,
tags: Map[String, String] = Map.empty)(measurementUnit: MeasurementUnit = MeasurementUnit.none) {
private var finishToken: LogMarkerToken = _
private var errorToken: LogMarkerToken = _
// Using var is safe wrt thread-safety because Kamon makes sure the instances
// (given the same key) are always the same, so a missed update is not harmful
private var _counter: KCounter = _
private var _histogram: KHistogram = _
private var _gauge: KGauge = _
override val toString = component + "_" + action + "_" + state
val toStringWithSubAction: String =
subAction.map(sa => component + "_" + action + "." + sa + "_" + state).getOrElse(toString)
def asFinish: LogMarkerToken = {
if (finishToken == null) {
finishToken = copy(state = LoggingMarkers.finish)(measurementUnit)
}
finishToken
}
def asError: LogMarkerToken = {
if (errorToken == null) {
errorToken = copy(state = LoggingMarkers.error)(measurementUnit)
}
errorToken
}
def counter: KCounter = {
if (_counter == null) {
_counter = createCounter()
}
_counter
}
def histogram: KHistogram = {
if (_histogram == null) {
_histogram = createHistogram()
}
_histogram
}
def gauge: KGauge = {
if (_gauge == null) {
_gauge = createGauge()
}
_gauge
}
private def createCounter() = {
if (TransactionId.metricsKamonTags) {
Kamon.counter(createName(toString, "counter")).withTags(TagSet.from(tags))
} else {
Kamon.counter(createName(toStringWithSubAction, "counter")).withoutTags()
}
}
private def createHistogram() = {
if (TransactionId.metricsKamonTags) {
Kamon.histogram(createName(toString, "histogram"), measurementUnit).withTags(TagSet.from(tags))
} else {
Kamon.histogram(createName(toStringWithSubAction, "histogram"), measurementUnit).withoutTags()
}
}
private def createGauge() = {
if (TransactionId.metricsKamonTags) {
Kamon.gauge(createName(toString, "gauge"), measurementUnit).withTags(TagSet.from(tags))
} else {
Kamon.gauge(createName(toStringWithSubAction, "gauge"), measurementUnit).withoutTags()
}
}
/**
* Kamon 1.0 onwards does not include the metric type in the metric name which cause issue
* for us as we use same metric name for counter and histogram. So to be backward compatible we
* need to prefix the name with type
*/
private def createName(name: String, metricType: String) = {
s"$metricType.$name"
}
}
object LogMarkerToken {
def parse(string: String) = {
// Per convention the components are guaranteed to not contain '_'
// thus it's safe to split at '_' to get the components
val Array(component, action, state) = string.split('_')
val (generalAction, subAction) = action.split('.').toList match {
case Nil => throw new IllegalArgumentException("LogMarkerToken malformed")
case a :: Nil => (a, None)
case a :: s :: _ => (a, Some(s))
}
LogMarkerToken(component, generalAction, state, subAction)(MeasurementUnit.none)
}
}
object MetricEmitter {
def emitCounterMetric(token: LogMarkerToken, times: Long = 1): Unit = {
if (TransactionId.metricsKamon) {
token.counter.increment(times)
}
}
def emitHistogramMetric(token: LogMarkerToken, value: Long): Unit = {
if (TransactionId.metricsKamon) {
token.histogram.record(value)
}
}
def emitGaugeMetric(token: LogMarkerToken, value: Long): Unit = {
if (TransactionId.metricsKamon) {
token.gauge.update(value)
}
}
}
/**
* Name generator to make names compatible to pre Kamon 1.0 logic. Statsd reporter "normalizes"
* the key name by replacing all `.` with `_`. Pre 1.0 the metric category was added by Statsd
* reporter itself. However now we pass it explicitly. So to retain the pre 1.0 name we need to replace
* normalized name with one having category followed by `.` instead of `_`
*/
class WhiskStatsDMetricKeyGenerator(config: com.typesafe.config.Config) extends MetricKeyGenerator {
val simpleGen = new SimpleMetricKeyGenerator(config)
override def generateKey(name: String, tags: TagSet): String = {
val key = simpleGen.generateKey(name, tags)
if (key.contains(".counter_")) key.replace(".counter_", ".counter.")
else if (key.contains(".histogram_")) key.replace(".histogram_", ".histogram.")
else key
}
}
object LoggingMarkers {
val start = "start"
val finish = "finish"
val error = "error"
val counter = "counter"
val timeout = "timeout"
private val controller = "controller"
private val scheduler = "scheduler"
private val invoker = "invoker"
private val database = "database"
private val activation = "activation"
private val kafka = "kafka"
private val loadbalancer = "loadbalancer"
private val containerClient = "containerClient"
private val containerPool = "containerPool"
/*
* The following markers are used to emit log messages as well as metrics. Add all LogMarkerTokens below to
* have a reference list of all metrics. The list below contains LogMarkerToken singletons (val) as well as
* LogMarkerToken creation functions (def). The LogMarkerToken creation functions allow to include variable
* information in metrics, such as the controller / invoker id or commands executed by a container factory.
*
* When using LogMarkerTokens for emitting metrics, you should use the convenience functions only once to
* create LogMarkerToken singletons instead of creating LogMarkerToken instances over and over again for each
* metric emit.
*
* Example:
* val MY_COUNTER_GREEN = LoggingMarkers.MY_COUNTER(GreenCounter)
* ...
* MetricEmitter.emitCounterMetric(MY_COUNTER_GREEN)
*
* instead of
*
* MetricEmitter.emitCounterMetric(LoggingMarkers.MY_COUNTER(GreenCounter))
*/
/*
* Controller related markers
*/
def CONTROLLER_STARTUP(id: String) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(controller, s"startup", counter, None, Map("controller_id" -> id))(MeasurementUnit.none)
else LogMarkerToken(controller, s"startup$id", counter)(MeasurementUnit.none)
// Time of the activation in controller until it is delivered to Kafka
val CONTROLLER_ACTIVATION =
LogMarkerToken(controller, activation, start)(MeasurementUnit.time.milliseconds)
val CONTROLLER_ACTIVATION_BLOCKING =
LogMarkerToken(controller, "blockingActivation", start)(MeasurementUnit.time.milliseconds)
val CONTROLLER_ACTIVATION_BLOCKING_DATABASE_RETRIEVAL =
LogMarkerToken(controller, "blockingActivationDatabaseRetrieval", counter)(MeasurementUnit.none)
// Time that is needed to load balance the activation
val CONTROLLER_LOADBALANCER = LogMarkerToken(controller, loadbalancer, start)(MeasurementUnit.none)
// Time that is needed to produce message in kafka
val CONTROLLER_KAFKA = LogMarkerToken(controller, kafka, start)(MeasurementUnit.time.milliseconds)
def INVOKER_SHAREDPACKAGE(path: String) =
LogMarkerToken(invoker, "sharedPackage", counter, None, Map("path" -> path))(MeasurementUnit.none)
def INVOKER_CONTAINERPOOL_MEMORY(state: String) =
LogMarkerToken(invoker, "containerPoolMemory", counter, Some(state), Map("state" -> state))(MeasurementUnit.none)
// System overload and random invoker assignment
val MANAGED_SYSTEM_OVERLOAD =
LogMarkerToken(controller, "managedInvokerSystemOverload", counter)(MeasurementUnit.none)
val BLACKBOX_SYSTEM_OVERLOAD =
LogMarkerToken(controller, "blackBoxInvokerSystemOverload", counter)(MeasurementUnit.none)
/*
* Invoker related markers
*/
def INVOKER_STARTUP(i: Int) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(invoker, s"startup", counter, None, Map("invoker_id" -> i.toString))(MeasurementUnit.none)
else LogMarkerToken(invoker, s"startup$i", counter)(MeasurementUnit.none)
// Check invoker healthy state from loadbalancer
def LOADBALANCER_INVOKER_STATUS_CHANGE(state: String) =
LogMarkerToken(loadbalancer, "invokerState", counter, Some(state), Map("state" -> state))(MeasurementUnit.none)
val LOADBALANCER_ACTIVATION_START = LogMarkerToken(loadbalancer, "activations", counter)(MeasurementUnit.none)
def LOADBALANCER_ACTIVATIONS_INFLIGHT(controllerInstance: ControllerInstanceId) = {
if (TransactionId.metricsKamonTags)
LogMarkerToken(
loadbalancer,
"activationsInflight",
counter,
None,
Map("controller_id" -> controllerInstance.asString))(MeasurementUnit.none)
else
LogMarkerToken(loadbalancer + controllerInstance.asString, "activationsInflight", counter)(MeasurementUnit.none)
}
def LOADBALANCER_MEMORY_INFLIGHT(controllerInstance: ControllerInstanceId, actionType: String) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(
loadbalancer,
s"memory${actionType}Inflight",
counter,
None,
Map("controller_id" -> controllerInstance.asString))(MeasurementUnit.none)
else
LogMarkerToken(loadbalancer + controllerInstance.asString, s"memory${actionType}Inflight", counter)(
MeasurementUnit.none)
// Counter metrics for completion acks in load balancer
sealed abstract class CompletionAckType(val name: String) { def asString: String = name }
case object RegularCompletionAck extends CompletionAckType("regular")
case object ForcedCompletionAck extends CompletionAckType("forced")
case object HealthcheckCompletionAck extends CompletionAckType("healthcheck")
case object RegularAfterForcedCompletionAck extends CompletionAckType("regularAfterForced")
case object ForcedAfterRegularCompletionAck extends CompletionAckType("forcedAfterRegular")
// Convenience function to create log marker tokens used for emitting counter metrics related to completion acks.
def LOADBALANCER_COMPLETION_ACK(controllerInstance: ControllerInstanceId, completionAckType: CompletionAckType) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(
loadbalancer,
"completionAck",
counter,
None,
Map("controller_id" -> controllerInstance.asString, "type" -> completionAckType.asString))(MeasurementUnit.none)
else
LogMarkerToken(
loadbalancer + controllerInstance.asString,
"completionAck_" + completionAckType.asString,
counter)(MeasurementUnit.none)
// Time that is needed to execute the action
val INVOKER_ACTIVATION_RUN =
LogMarkerToken(invoker, "activationRun", start)(MeasurementUnit.time.milliseconds)
// Time that is needed to init the action
val INVOKER_ACTIVATION_INIT =
LogMarkerToken(invoker, "activationInit", start)(MeasurementUnit.time.milliseconds)
// Time needed to collect the logs
val INVOKER_COLLECT_LOGS =
LogMarkerToken(invoker, "collectLogs", start)(MeasurementUnit.time.milliseconds)
// Time in invoker
val INVOKER_ACTIVATION = LogMarkerToken(invoker, activation, start)(MeasurementUnit.none)
def INVOKER_DOCKER_CMD(cmd: String) =
LogMarkerToken(invoker, "docker", start, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.time.milliseconds)
def INVOKER_DOCKER_CMD_TIMEOUT(cmd: String) =
LogMarkerToken(invoker, "docker", timeout, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.none)
def INVOKER_RUNC_CMD(cmd: String) =
LogMarkerToken(invoker, "runc", start, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.time.milliseconds)
def INVOKER_KUBEAPI_CMD(cmd: String) =
LogMarkerToken(invoker, "kubeapi", start, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.none)
def INVOKER_MESOS_CMD(cmd: String) =
LogMarkerToken(invoker, "mesos", start, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.time.milliseconds)
def INVOKER_MESOS_CMD_TIMEOUT(cmd: String) =
LogMarkerToken(invoker, "mesos", timeout, Some(cmd), Map("cmd" -> cmd))(MeasurementUnit.none)
def INVOKER_CONTAINER_START(containerState: String, invocationNamespace: String, namespace: String, action: String) =
LogMarkerToken(
invoker,
"containerStart",
counter,
Some(containerState),
Map(
"containerState" -> containerState,
"initiator" -> invocationNamespace,
"namespace" -> namespace,
"action" -> action))(MeasurementUnit.none)
val INVOKER_CONTAINER_HEALTH = LogMarkerToken(invoker, "containerHealth", start)(MeasurementUnit.time.milliseconds)
val INVOKER_CONTAINER_HEALTH_FAILED_WARM =
LogMarkerToken(invoker, "containerHealthFailed", counter, Some("warm"), Map("containerState" -> "warm"))(
MeasurementUnit.none)
val INVOKER_CONTAINER_HEALTH_FAILED_PREWARM =
LogMarkerToken(invoker, "containerHealthFailed", counter, Some("prewarm"), Map("containerState" -> "prewarm"))(
MeasurementUnit.none)
val CONTAINER_CLIENT_RETRIES =
LogMarkerToken(containerClient, "retries", counter)(MeasurementUnit.none)
val CONTAINER_POOL_RESCHEDULED_ACTIVATION =
LogMarkerToken(containerPool, "rescheduledActivation", counter)(MeasurementUnit.none)
val CONTAINER_POOL_RUNBUFFER_COUNT =
LogMarkerToken(containerPool, "runBufferCount", counter)(MeasurementUnit.none)
val CONTAINER_POOL_RUNBUFFER_SIZE =
LogMarkerToken(containerPool, "runBufferSize", counter)(MeasurementUnit.information.megabytes)
val CONTAINER_POOL_ACTIVE_COUNT =
LogMarkerToken(containerPool, "activeCount", counter)(MeasurementUnit.none)
val CONTAINER_POOL_ACTIVE_SIZE =
LogMarkerToken(containerPool, "activeSize", counter)(MeasurementUnit.information.megabytes)
val CONTAINER_POOL_PREWARM_COUNT =
LogMarkerToken(containerPool, "prewarmCount", counter)(MeasurementUnit.none)
val CONTAINER_POOL_PREWARM_SIZE =
LogMarkerToken(containerPool, "prewarmSize", counter)(MeasurementUnit.information.megabytes)
val CONTAINER_POOL_IDLES_COUNT =
LogMarkerToken(containerPool, "idlesCount", counter)(MeasurementUnit.none)
def CONTAINER_POOL_PREWARM_COLDSTART(memory: String, kind: String) =
LogMarkerToken(containerPool, "prewarmColdstart", counter, None, Map("memory" -> memory, "kind" -> kind))(
MeasurementUnit.none)
def CONTAINER_POOL_PREWARM_EXPIRED(memory: String, kind: String) =
LogMarkerToken(containerPool, "prewarmExpired", counter, None, Map("memory" -> memory, "kind" -> kind))(
MeasurementUnit.none)
val CONTAINER_POOL_IDLES_SIZE =
LogMarkerToken(containerPool, "idlesSize", counter)(MeasurementUnit.information.megabytes)
val INVOKER_TOTALMEM_BLACKBOX = LogMarkerToken(loadbalancer, "totalCapacityBlackBox", counter)(MeasurementUnit.none)
val INVOKER_TOTALMEM_MANAGED = LogMarkerToken(loadbalancer, "totalCapacityManaged", counter)(MeasurementUnit.none)
val HEALTHY_INVOKER_MANAGED =
LogMarkerToken(loadbalancer, "totalHealthyInvokerManaged", counter)(MeasurementUnit.none)
val UNHEALTHY_INVOKER_MANAGED =
LogMarkerToken(loadbalancer, "totalUnhealthyInvokerManaged", counter)(MeasurementUnit.none)
val UNRESPONSIVE_INVOKER_MANAGED =
LogMarkerToken(loadbalancer, "totalUnresponsiveInvokerManaged", counter)(MeasurementUnit.none)
val OFFLINE_INVOKER_MANAGED =
LogMarkerToken(loadbalancer, "totalOfflineInvokerManaged", counter)(MeasurementUnit.none)
val HEALTHY_INVOKER_BLACKBOX =
LogMarkerToken(loadbalancer, "totalHealthyInvokerBlackBox", counter)(MeasurementUnit.none)
val UNHEALTHY_INVOKER_BLACKBOX =
LogMarkerToken(loadbalancer, "totalUnhealthyInvokerBlackBox", counter)(MeasurementUnit.none)
val UNRESPONSIVE_INVOKER_BLACKBOX =
LogMarkerToken(loadbalancer, "totalUnresponsiveInvokerBlackBox", counter)(MeasurementUnit.none)
val OFFLINE_INVOKER_BLACKBOX =
LogMarkerToken(loadbalancer, "totalOfflineInvokerBlackBox", counter)(MeasurementUnit.none)
// Kafka related markers
def KAFKA_QUEUE(topic: String) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(kafka, "topic", counter, None, Map("topic" -> topic))(MeasurementUnit.none)
else LogMarkerToken(kafka, topic, counter)(MeasurementUnit.none)
def KAFKA_MESSAGE_DELAY(topic: String) =
if (TransactionId.metricsKamonTags)
LogMarkerToken(kafka, "topic", start, Some("delay"), Map("topic" -> topic))(MeasurementUnit.time.milliseconds)
else LogMarkerToken(kafka, topic, start, Some("delay"))(MeasurementUnit.time.milliseconds)
// Time that is needed to produce message in kafka
val SCHEDULER_KAFKA = LogMarkerToken(scheduler, kafka, start)(MeasurementUnit.time.milliseconds)
val SCHEDULER_WAIT_TIME =
LogMarkerToken(scheduler, "waitTime", counter)(MeasurementUnit.none)
def SCHEDULER_KEEP_ALIVE(leaseId: Long) =
LogMarkerToken(scheduler, "keepAlive", counter, None, Map("leaseId" -> leaseId.toString))(MeasurementUnit.none)
def SCHEDULER_QUEUE = LogMarkerToken(scheduler, "queue", counter)(MeasurementUnit.none)
def SCHEDULER_QUEUE_CREATE = LogMarkerToken(scheduler, "queueCreate", start)(MeasurementUnit.time.milliseconds)
def SCHEDULER_QUEUE_UPDATE(reason: String) =
LogMarkerToken(scheduler, "queueUpdate", counter, None, Map("reason" -> reason))(MeasurementUnit.none)
def SCHEDULER_QUEUE_WAITING_ACTIVATION(action: String) =
LogMarkerToken(scheduler, "queueActivation", counter, Some(action), Map("action" -> action))(MeasurementUnit.none)
/*
* General markers
*/
val DATABASE_CACHE_HIT = LogMarkerToken(database, "cacheHit", counter)(MeasurementUnit.none)
val DATABASE_CACHE_MISS = LogMarkerToken(database, "cacheMiss", counter)(MeasurementUnit.none)
val DATABASE_SAVE =
LogMarkerToken(database, "saveDocument", start)(MeasurementUnit.time.milliseconds)
val DATABASE_BULK_SAVE =
LogMarkerToken(database, "saveDocumentBulk", start)(MeasurementUnit.time.milliseconds)
val DATABASE_DELETE =
LogMarkerToken(database, "deleteDocument", start)(MeasurementUnit.time.milliseconds)
val DATABASE_GET = LogMarkerToken(database, "getDocument", start)(MeasurementUnit.time.milliseconds)
val DATABASE_QUERY = LogMarkerToken(database, "queryView", start)(MeasurementUnit.time.milliseconds)
val DATABASE_ATT_GET =
LogMarkerToken(database, "getDocumentAttachment", start)(MeasurementUnit.time.milliseconds)
val DATABASE_ATT_SAVE =
LogMarkerToken(database, "saveDocumentAttachment", start)(MeasurementUnit.time.milliseconds)
val DATABASE_ATT_DELETE =
LogMarkerToken(database, "deleteDocumentAttachment", start)(MeasurementUnit.time.milliseconds)
val DATABASE_ATTS_DELETE =
LogMarkerToken(database, "deleteDocumentAttachments", start)(MeasurementUnit.time.milliseconds)
val DATABASE_BATCH_SIZE = LogMarkerToken(database, "batchSize", counter)(MeasurementUnit.none)
}