aboutsummaryrefslogtreecommitdiff
path: root/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala
diff options
context:
space:
mode:
Diffstat (limited to 'kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala')
-rw-r--r--kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala173
1 files changed, 173 insertions, 0 deletions
diff --git a/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala
new file mode 100644
index 00000000..d138ec8f
--- /dev/null
+++ b/kamon-system-metrics/src/main/scala/kamon/system/sigar/SigarLoader.scala
@@ -0,0 +1,173 @@
+/*
+ * =========================================================================================
+ * Copyright © 2013-2014 the kamon project <http://kamon.io/>
+ *
+ * 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 kamon.system.sigar
+
+import java.io._
+import java.util
+import java.util.logging.Logger
+import java.util.{ ArrayList, Date, List }
+
+import org.hyperic.sigar.{ OperatingSystem, Sigar, SigarProxy }
+
+import scala.annotation.tailrec
+import scala.collection.JavaConversions._
+import scala.io.Source
+
+object SigarHolder {
+ private lazy val sigarProxy = SigarLoader.sigarProxy
+ def instance() = sigarProxy
+}
+
+object SigarLoader {
+
+ val Version = "1.6.4"
+ val JavaLibraryPath = "java.library.path"
+ val TmpDir = "java.io.tmpdir"
+ val IndexFile = "/kamon/system/sigar/index"
+ val UsrPathField = "usr_paths"
+
+ private val log = Logger.getLogger("SigarLoader")
+
+ def sigarProxy = init(new File(System.getProperty(TmpDir)))
+
+ private[sigar] def init(baseTmp: File): SigarProxy = {
+ val tmpDir = createTmpDir(baseTmp)
+ for (lib ← loadIndex) copy(lib, tmpDir)
+
+ attachToLibraryPath(tmpDir)
+
+ try {
+ val sigar = new Sigar()
+ printBanner(sigar)
+ sigar
+ } catch {
+ case t: Throwable ⇒ {
+ log.severe("Failed to load sigar")
+ throw new RuntimeException(t)
+ }
+ }
+ }
+
+ private[sigar] val usrPathField = {
+ val usrPathField = classOf[ClassLoader].getDeclaredField(UsrPathField)
+ usrPathField.setAccessible(true)
+ usrPathField
+ }
+
+ private[sigar] def attachToLibraryPath(dir: File): Unit = {
+ val dirAbsolute = dir.getAbsolutePath
+ System.setProperty(JavaLibraryPath, newLibraryPath(dirAbsolute))
+ var paths = usrPathField.get(null).asInstanceOf[Array[String]]
+ if (paths == null) paths = new Array[String](0)
+ for (path ← paths) if (path == dirAbsolute) return
+ val newPaths = util.Arrays.copyOf(paths, paths.length + 1)
+ newPaths(newPaths.length - 1) = dirAbsolute
+ usrPathField.set(null, newPaths)
+ }
+
+ private[sigar] def newLibraryPath(dirAbsolutePath: String): String = {
+ Option(System.getProperty(JavaLibraryPath)).fold(dirAbsolutePath)(oldValue ⇒ s"$dirAbsolutePath${File.pathSeparator}$oldValue")
+ }
+
+ private[sigar] def copy(lib: String, tmpDir: File) {
+ val target = new File(tmpDir, lib)
+ if (target.exists()) return
+ write(classOf[Loader].getResourceAsStream(lib), target)
+ }
+
+ private[sigar] def createTmpDir(baseTmp: File): File = {
+ val tmpDir = new File(baseTmp, s"sigar-$Version")
+ if (!tmpDir.exists()) {
+ if (!tmpDir.mkdirs()) throw new RuntimeException(s"Could not create temp sigar directory: ${tmpDir.getAbsolutePath}")
+ }
+ if (!tmpDir.isDirectory) throw new RuntimeException(s"sigar temp directory path is not a directory: ${tmpDir.getAbsolutePath}")
+ if (!tmpDir.canWrite()) throw new RuntimeException(s"sigar temp directory not writeable: ${tmpDir.getAbsolutePath}")
+ tmpDir
+ }
+
+ private[sigar] def loadIndex(): List[String] = {
+ val libs = new ArrayList[String]()
+ val is = classOf[Loader].getResourceAsStream(IndexFile)
+
+ for (line ← Source.fromInputStream(is).getLines()) {
+ val currentLine = line.trim()
+ libs add currentLine
+ }
+ libs
+ }
+
+ private[sigar] def write(input: InputStream, to: File) {
+ val out = new FileOutputStream(to)
+ try {
+ transfer(input, out)
+ } finally {
+ out.close()
+ }
+ }
+
+ private[sigar] def transfer(input: InputStream, out: OutputStream) {
+ val buffer = new Array[Byte](8192)
+
+ @tailrec def transfer() {
+ val read = input.read(buffer)
+ if (read >= 0) {
+ out.write(buffer, 0, read)
+ transfer()
+ }
+ }
+ transfer()
+ }
+
+ private[sigar] def printBanner(sigar: Sigar) = {
+ def loadAverage(sigar: Sigar) = {
+ val average = sigar.getLoadAverage
+ (average(0), average(1), average(2))
+ }
+
+ def uptime(sigar: Sigar) = {
+ val uptime = sigar.getUptime
+ val now = System.currentTimeMillis()
+ new Date(now - (uptime.getUptime() * 1000).toLong)
+ }
+
+ def osInfo() = {
+ val NewLine = "\n"
+ val os = OperatingSystem.getInstance
+ val osInfo = new StringBuilder("------ OS Information ------").append(NewLine)
+ osInfo.append("Description: ").append(os.getDescription).append(NewLine)
+ .append("Name: ").append(os.getName).append(NewLine)
+ .append("Version: ").append(os.getVersion).append(NewLine)
+ .append("Arch: ").append(os.getArch).append(NewLine)
+ .toString()
+ }
+
+ val message =
+ """
+ |
+ | _____ _ __ __ _ _ _ _ _
+ | / ____| | | | \/ | | | (_) | | | | | |
+ || (___ _ _ ___| |_ ___ _ __ ___ | \ / | ___| |_ _ __ _ ___ ___| | ___ __ _ __| | ___ __| |
+ | \___ \| | | / __| __/ _ \ '_ ` _ \| |\/| |/ _ \ __| '__| |/ __/ __| | / _ \ / _` |/ _` |/ _ \/ _` |
+ | ____) | |_| \__ \ || __/ | | | | | | | | __/ |_| | | | (__\__ \ |___| (_) | (_| | (_| | __/ (_| |
+ ||_____/ \__, |___/\__\___|_| |_| |_|_| |_|\___|\__|_| |_|\___|___/______\___/ \__,_|\__,_|\___|\__,_|
+ | __/ |
+ | |___/
+ """.stripMargin + s"\nBoot Time: ${uptime(sigar)} \nLoad Average: ${loadAverage(sigar)} \n${osInfo()}"
+ log.info(message)
+ }
+ class Loader private[sigar]
+}