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

com.wavesplatform.metrics.Metrics.scala Maven / Gradle / Ivy

The newest version!
package com.wavesplatform.metrics

import java.net.URI
import java.util.concurrent.TimeUnit

import scala.concurrent.duration.FiniteDuration
import scala.util.Try
import scala.util.control.NonFatal

import com.wavesplatform.ResponsivenessLogs
import com.wavesplatform.utils.{Schedulers, ScorexLogging, Time}
import monix.eval.Task
import monix.execution.schedulers.SchedulerService
import org.influxdb.{InfluxDB, InfluxDBFactory}
import org.influxdb.dto.Point

object Metrics extends ScorexLogging {
  case class InfluxDbSettings(
      uri: URI,
      db: String,
      retentionPolicy: String,
      username: Option[String],
      password: Option[String],
      batchActions: Int,
      batchFlashDuration: FiniteDuration
  )

  case class Settings(
      enable: Boolean,
      nodeId: Int,
      influxDb: InfluxDbSettings,
      collectResponsivenessMetrics: Boolean,
      createResponsivenessCsv: Boolean,
      responsivenessMetricsRetentionPolicy: String
  )

  private[this] implicit val scheduler: SchedulerService = Schedulers.singleThread("metrics")

  private[this] var settings: Settings   = _
  private[this] var time: Time           = _
  private[this] var db: Option[InfluxDB] = None

  private[this] def currentTimestamp: Long =
    if (time == null) System.currentTimeMillis()
    else time.getTimestamp()

  def withRetentionPolicy(retentionPolicy: String)(f: => Unit): Unit =
    db.synchronized(db.foreach { db =>
      db.setRetentionPolicy(retentionPolicy)
      try f
      finally db.setRetentionPolicy("")
    })

  def write(b: Point.Builder, ts: Long = currentTimestamp): Unit = db.synchronized {
    db.foreach { db =>
      Task {
        try {
          db.write(
            b
            // Should be a tag, but tags are the strings now
            // https://docs.influxdata.com/influxdb/v1.3/concepts/glossary/#tag-value
              .addField("node", settings.nodeId)
              .tag("node", settings.nodeId.toString)
              .time(ts, TimeUnit.MILLISECONDS)
              .build()
          )
        } catch {
          case e: Throwable => log.warn(s"Failed to send data to InfluxDB (${e.getMessage})")
        }
      }.runAsyncLogErr
    }
  }

  def writeEvent(name: String): Unit = write(Point.measurement(name))

  def start(config: Settings, thatTime: Time): Boolean = synchronized {
    this.shutdown()
    settings = config
    time = thatTime
    if (settings.enable) {
      import config.{influxDb => dbSettings}

      log.info(s"Precise metrics are enabled and will be sent to ${dbSettings.uri}/${dbSettings.db}")
      try {
        val x = if (dbSettings.username.nonEmpty && dbSettings.password.nonEmpty) {
          InfluxDBFactory.connect(
            dbSettings.uri.toString,
            dbSettings.username.getOrElse(""),
            dbSettings.password.getOrElse("")
          )
        } else {
          InfluxDBFactory.connect(dbSettings.uri.toString)
        }
        x.setDatabase(dbSettings.db)
        x.enableBatch(dbSettings.batchActions, dbSettings.batchFlashDuration.toSeconds.toInt, TimeUnit.SECONDS)
        x.setRetentionPolicy("")

        try {
          val pong = x.ping()
          log.info(s"Metrics will be sent to ${dbSettings.uri}/${dbSettings.db}. Connected in ${pong.getResponseTime}ms.")
          db = Some(x)
        } catch {
          case NonFatal(e) =>
            log.warn("Can't connect to InfluxDB", e)
        }
      } catch {
        case NonFatal(e) => log.warn(s"Failed to connect to InfluxDB (${e.getMessage})")
      }
    }

    ResponsivenessLogs.enableMetrics = config.collectResponsivenessMetrics
    ResponsivenessLogs.enableCsv = config.createResponsivenessCsv
    ResponsivenessLogs.retentionPolicy = config.responsivenessMetricsRetentionPolicy

    db.nonEmpty
  }

  def shutdown(): Unit = synchronized {
    val dbValue = this.db
    this.db = None
    Try(dbValue.foreach(_.close()))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy