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

com.twitter.ostrich.stats.GraphiteStatsLogger.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2009 Twitter, Inc.
 *
 * 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 com.twitter.ostrich
package stats

import java.net.{Socket, InetAddress}
import java.io.{IOException, OutputStreamWriter}
import com.twitter.conversions.time._
import com.twitter.logging.Logger
import com.twitter.ostrich.admin.config.StatsReporterConfig
import com.twitter.ostrich.admin.{AdminHttpService, PeriodicBackgroundProcess, StatsReporterFactory}
import com.twitter.util.Duration

/**
 * Write stats to Graphite.  Both a prefix and/or a service name can be
 * provided to be appended to the front of the metric keys.
 */
@deprecated("use GraphiteStatsLoggerFactory")
class GraphiteStatsLoggerConfig extends StatsReporterConfig {
  var period: Duration = 1.minute
  var serviceName: Option[String] = None
  var prefix: String = "unknown"
  var host: String = "localhost"
  var port: Int = 2013

  def apply() = { (collection: StatsCollection, admin: AdminHttpService) =>
    new GraphiteStatsLogger(host, port, period, prefix, serviceName, collection)
  }
}

class GraphiteStatsLoggerFactory(
    period: Duration = 1.minute,
    serviceName: Option[String] = None,
    prefix: String = "unknown",
    host: String = "localhost",
    port: Int = 2013)
  extends StatsReporterFactory {

  def apply(collection: StatsCollection, admin: AdminHttpService) =
    new GraphiteStatsLogger(host, port, period, prefix, serviceName, collection)
}

/**
 * Log all collected stats to Graphite
 */
class GraphiteStatsLogger(val host: String, val port: Int, val period: Duration, val prefix: String,
                          val serviceName: Option[String], collection: StatsCollection)
  extends PeriodicBackgroundProcess("GraphiteStatsLogger", period) {
  val logger = Logger.get()

  val listener = new StatsListener(collection)
  val hostname = InetAddress.getLocalHost.getCanonicalHostName

  def periodic() {
    try {
      write(new Socket(host, port))
    } catch {
      case e: IOException => logger.error("Error connecting to graphite: %s", e.getMessage)
    }
  }

  def write(sock: Socket) {
    val stats = listener.get()
    val statMap =
      stats.counters.map { case (key, value) => (key, value.doubleValue) } ++
      stats.gauges ++
      stats.metrics.flatMap { case (key, distribution) =>
        distribution.toMap.map { case (subkey, value) =>
          (key + "_" + subkey, value.doubleValue)
        }
      }
    val cleanedKeysStatMap = statMap.map { case (key, value) =>
      (key.replaceAll(":", "_").replaceAll("/", ".").replaceAll(" ", "_").toLowerCase(), value) }

    var writer: OutputStreamWriter = null
    try {
      val epoch = System.currentTimeMillis() / 1000

      writer = new OutputStreamWriter(sock.getOutputStream)

      try {
        cleanedKeysStatMap.foreach { case (key, value) => {
          writer.write("%s.%s.%s %.2f %d\n".formatLocal(java.util.Locale.US, prefix, serviceName.getOrElse("unknown"), key, value.doubleValue,
            epoch))
        }}
      } catch {
        case e: IOException => logger.error("Error writing data to graphite: %s", e.getMessage)
      }

      writer.flush()
    } catch {
      case e: Exception =>
        logger.error("Error writing to Graphite: %s", e.getMessage)
        if (writer != null) {
          try {
            writer.flush()
          } catch {
            case ioe: IOException =>
              logger.error("Error while flushing writer: %s", ioe.getMessage)
          }
        }
    } finally {
      if (sock != null) {
        try {
          sock.close();
        } catch {
          case ioe: IOException => logger.error("Error while closing socket: %s", ioe.getMessage)
        }
      }
      writer = null
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy