Skip to content

Commit

Permalink
Merge pull request #17 from mattcolegate/master
Browse files Browse the repository at this point in the history
Adding SwiftMetricsDash module
  • Loading branch information
tobespc authored Feb 8, 2017
2 parents e106ce4 + 7fa8bb8 commit 997cb84
Show file tree
Hide file tree
Showing 21 changed files with 1,887 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ let package = Package(
name: "SwiftMetrics",
targets: [
Target(name: "SwiftMetricsKitura", dependencies: ["SwiftMetrics"]),
Target(name: "SwiftMetricsBluemix", dependencies: ["SwiftMetricsKitura"])
Target(name: "SwiftMetricsBluemix", dependencies: ["SwiftMetricsKitura"]),
Target(name: "SwiftMetricsDash", dependencies: ["SwiftMetricsBluemix"])
],
dependencies: [
.Package(url: "https://github.com/RuntimeTools/omr-agentcore.git", majorVersion: 3),
.Package(url: "https://github.com/IBM-Swift/Kitura.git", majorVersion: 1, minor: 6),
.Package(url: "https://github.com/IBM-Swift/Kitura-Request.git", majorVersion: 0, minor: 7),
.Package(url: "https://github.com/IBM-Swift/SwiftyJSON.git", majorVersion: 15),
.Package(url: "https://github.com/IBM-Swift/Swift-cfenv.git", majorVersion: 2, minor: 0)
]
)
232 changes: 232 additions & 0 deletions Sources/SwiftMetricsDash/SwiftMetricsDash.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/**
* Copyright IBM Corporation 2016
*
* 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.
**/

import Kitura
import SwiftMetricsKitura
import SwiftMetricsBluemix
import SwiftMetrics
import SwiftyJSON
import KituraNet
import Foundation
import CloudFoundryEnv

public class SwiftMetricsDash {

var cpuDataStore:[JSON] = []
var httpDataStore:[JSON] = []
var memDataStore:[JSON] = []
var cpuData:[CPUData] = []

var monitor:SwiftMonitor
var SM:SwiftMetrics

public convenience init(swiftMetricsInstance : SwiftMetrics) throws {
try self.init(swiftMetricsInstance : swiftMetricsInstance , endpoint: nil)
}

public init(swiftMetricsInstance : SwiftMetrics , endpoint: Router!) throws {
// default to use passed in Router
var create = false
var router = Router()
if endpoint == nil {
create = true
} else {
router = endpoint
}
self.SM = swiftMetricsInstance
_ = SwiftMetricsKitura(swiftMetricsInstance: SM)
self.monitor = SM.monitor()
monitor.on(storeCPU)
monitor.on(storeMem)
monitor.on(storeHTTP)

try startServer(createServer: create, router: router)
}

func startServer(createServer: Bool, router: Router) throws {
let fm = FileManager.default
let currentDir = fm.currentDirectoryPath
var workingPath = ""
if currentDir.contains(".build") {
//we're below the Packages directory
workingPath = currentDir
} else {
//we're above the Packages directory
workingPath = CommandLine.arguments[0]
}
let i = workingPath.range(of: ".build")
var packagesPath = ""
if i == nil {
// we could be in bluemix
packagesPath="/home/vcap/app/"
} else {
packagesPath = workingPath.substring(to: i!.lowerBound)
}
packagesPath.append("Packages/")
let dirContents = try fm.contentsOfDirectory(atPath: packagesPath)
for dir in dirContents {
if dir.contains("SwiftMetrics") {
packagesPath.append("\(dir)/public")
}
}
router.all("/swiftdash", middleware: StaticFileServer(path: packagesPath))
router.get("/cpuRequest", handler: getcpuRequest)
router.get("/memRequest", handler: getmemRequest)
router.get("/envRequest", handler: getenvRequest)
router.get("/cpuAverages", handler: getcpuAverages)
router.get("/httpRequest", handler: gethttpRequest)
if createServer {
try Kitura.addHTTPServer(onPort: CloudFoundryEnv.getAppEnv().port, with: router)
Kitura.run()
}
}

func calculateAverageCPU() -> JSON {
var cpuLine = JSON([])
let tempArray = self.cpuData
if (tempArray.count > 0) {
var totalApplicationUse: Float = 0
var totalSystemUse: Float = 0
var time: Int = 0
for cpuItem in tempArray {
totalApplicationUse += cpuItem.percentUsedByApplication
totalSystemUse += cpuItem.percentUsedBySystem
time = cpuItem.timeOfSample
}
cpuLine = JSON([
"time":"\(time)",
"process":"\(totalApplicationUse/Float(tempArray.count))",
"system":"\(totalSystemUse/Float(tempArray.count))"])
}
return cpuLine
}


func storeHTTP(myhttp: HTTPData) {
let currentTime = NSDate().timeIntervalSince1970
let tempArray = self.httpDataStore
for httpJson in tempArray {
if(currentTime - (Double(httpJson["time"].stringValue)! / 1000) > 1800) {
self.httpDataStore.removeFirst()
} else {
break
}
}
let httpLine = JSON(["time":"\(myhttp.timeOfRequest)","url":"\(myhttp.url)","duration":"\(myhttp.duration)","method":"\(myhttp.requestMethod)","statusCode":"\(myhttp.statusCode)"])
self.httpDataStore.append(httpLine)
}


func storeCPU(cpu: CPUData) {
let currentTime = NSDate().timeIntervalSince1970
let tempArray = self.cpuDataStore
if tempArray.count > 0 {
for cpuJson in tempArray {
if(currentTime - (Double(cpuJson["time"].stringValue)! / 1000) > 1800) {
self.cpuDataStore.removeFirst()
} else {
break
}
}
}
self.cpuData.append(cpu);
let cpuLine = JSON(["time":"\(cpu.timeOfSample)","process":"\(cpu.percentUsedByApplication)","system":"\(cpu.percentUsedBySystem)"])
self.cpuDataStore.append(cpuLine)
}

func storeMem(mem: MemData) {
let currentTime = NSDate().timeIntervalSince1970
let tempArray = self.memDataStore
if tempArray.count > 0 {
for memJson in tempArray {
if(currentTime - (Double(memJson["time"].stringValue)! / 1000) > 1800) {
self.memDataStore.removeFirst()
} else {
break
}
}
}
let memLine = JSON([
"time":"\(mem.timeOfSample)",
"physical":"\(mem.applicationRAMUsed)",
"physical_used":"\(mem.totalRAMUsed)"
])
self.memDataStore.append(memLine)
}

public func getcpuRequest(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws {
response.headers["Content-Type"] = "application/json"
let tempArray = self.cpuDataStore
if tempArray.count > 0 {
try response.status(.OK).send(json: JSON(tempArray)).end()
self.cpuDataStore.removeAll()
} else {
try response.status(.OK).send(json: JSON([])).end()
}
}

public func getmemRequest(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws {
response.headers["Content-Type"] = "application/json"
let tempArray = self.memDataStore
if tempArray.count > 0 {
try response.status(.OK).send(json: JSON(tempArray)).end()
self.memDataStore.removeAll()
} else {
try response.status(.OK).send(json: JSON([])).end()
}
}

public func getenvRequest(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws {
response.headers["Content-Type"] = "application/json"
var responseData: [JSON] = []
for (param, value) in self.monitor.getEnvironmentData() {
switch param {
case "command.line":
let json: JSON = ["Parameter": "Command Line", "Value": value]
responseData.append(json)
case "environment.HOSTNAME":
let json: JSON = ["Parameter": "Hostname", "Value": value]
responseData.append(json)
case "os.arch":
let json: JSON = ["Parameter": "OS Architecture", "Value": value]
responseData.append(json)
case "number.of.processors":
let json: JSON = ["Parameter": "Number of Processors", "Value": value]
responseData.append(json)
default:
break
}
}
try response.status(.OK).send(json: JSON(responseData)).end()
}

public func getcpuAverages(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws {
response.headers["Content-Type"] = "application/json"
try response.status(.OK).send(json: self.calculateAverageCPU()).end()
}

public func gethttpRequest(request: RouterRequest, response: RouterResponse, next: @escaping () -> Void) throws {
response.headers["Content-Type"] = "application/json"
let tempArray = self.httpDataStore
if tempArray.count > 0 {
try response.status(.OK).send(json: JSON(tempArray)).end()
self.httpDataStore.removeAll()
} else {
try response.status(.OK).send(json: JSON([])).end()
}
}

}
6 changes: 6 additions & 0 deletions public/bootstrap-3.3.7-dist/css/bootstrap.min.css

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions public/bootstrap-3.3.7-dist/css/bootstrap.min.css.map

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions public/bootstrap-3.3.7-dist/js/bootstrap.min.js

Large diffs are not rendered by default.

124 changes: 124 additions & 0 deletions public/css/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
@viewport {
width: 320;
}

html {
background-color: #3b4b54;
}

body {
font: 12px Arial;
fill: white;
background-color: #3b4b54;
}

h1 {
font: 26px Arial;
font-weight: bold;
text-align: center;
color: white;
}

p {
font: 18px;
color: white;
}

svg {
margin: 3px;
background-color: #3f505a;
}

#envDiv {
background-color: #3f505a;
}

.cpuChart path,
.memChart path,
.httpThroughPutChart path,
.httpChart path {
stroke: #6decd7;
stroke-width: 2;
fill: none;
}


.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}

.axis2 path,
.axis2 line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}

.legend {
font: 12px Arial;
font-weight: bold;
text-anchor: left;
}

.grid .tick {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}

.grid path {
stroke-width: 0;
}

div.tooltip {
position: absolute;
text-align: center;
padding: 3px;
font: 12px sans-serif;
background: #b0f4e8;
border: 0px;
border-radius: 8px;
pointer-events: none;
}

.container {
width: 100%;
}

.chart {
margin: 0 auto;
display: block;
text-align: center;
}


g.arc {
fill: #6decd7;
}

g.pointer {
fill: #959f9f;
stroke: #000000;
}

g.label text {
text-anchor: middle;
text-align: center;
font-size: 12px;
}

.urlChart rect {
fill: #6decd7;
}

th, td {
padding: 5px;
border-bottom: 1px solid #696969;
color: white;
}

Loading

0 comments on commit 997cb84

Please sign in to comment.