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

wvlet.airframe.fluentd.MetricLogger.scala Maven / Gradle / Ivy

/*
 * Licensed 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 wvlet.airframe.fluentd
import java.util.concurrent.ConcurrentHashMap

import javax.annotation.PreDestroy
import wvlet.airframe.codec.MessageCodec
import wvlet.airframe.surface.Surface
import wvlet.log.LogSupport

abstract class MetricLogger extends AutoCloseable {
  protected def tagPrefix: Option[String]
  def withTagPrefix(newTagPrefix: String): MetricLogger

  protected def emitRaw(fullTag: String, event: Map[String, Any]): Unit
  protected def emitRawMsgPack(fullTag: String, event: Array[Byte]): Unit

  def emit(tag: String, event: Map[String, Any]): Unit = {
    emitRaw(enrichTag(tag), event)
  }

  def emitMsgPack(tag: String, event: Array[Byte]): Unit = {
    emitRawMsgPack(enrichTag(tag), event)
  }

  private def enrichTag(tag: String): String = {
    tagPrefix match {
      case None => tag
      case Some(prefix) =>
        s"${prefix}.${tag}"
    }
  }

  @PreDestroy
  override def close(): Unit
}

class TypedMetricLogger[T <: TaggedMetric](fluentdClient: MetricLogger, codec: MessageCodec[T]) {
  def emit(event: T): Unit = {
    fluentdClient.emitMsgPack(event.metricTag, codec.toMsgPack(event))
  }
}

class MetricLoggerFactory(fluentdClient: MetricLogger) extends LogSupport {
  def getLogger: MetricLogger = fluentdClient
  def getLoggerWithTagPrefix(tagPrefix: String): MetricLogger =
    fluentdClient.withTagPrefix(tagPrefix)

  import scala.collection.JavaConverters._
  import scala.reflect.runtime.{universe => ru}

  private val loggerCache = new ConcurrentHashMap[Surface, TypedMetricLogger[_]]().asScala

  def getTypedLogger[T <: TaggedMetric: ru.TypeTag]: TypedMetricLogger[T] = {
    loggerCache
      .getOrElseUpdate(Surface.of[T], {
        val codec = MessageCodec.of[T]
        new TypedMetricLogger[T](getLogger, codec)
      }).asInstanceOf[TypedMetricLogger[T]]
  }

  def getTypedLoggerWithTagPrefix[T <: TaggedMetric: ru.TypeTag](tagPrefix: String): TypedMetricLogger[T] = {
    loggerCache
      .getOrElseUpdate(Surface.of[T], {
        val codec = MessageCodec.of[T]
        new TypedMetricLogger[T](getLoggerWithTagPrefix(tagPrefix), codec)
      }).asInstanceOf[TypedMetricLogger[T]]
  }

  @PreDestroy
  def shutdown: Unit = {
    debug(s"Closing MetricLoggerFactory")
    fluentdClient.close()
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy