Swift 在服务器端的应用在业界非常热门,但是仍处于方兴未艾。其中有一个较大的影响因素,就是很少有Swift全栈工程师或者管理员知道如何通过浏览器或者手机监控服务器的运行。
幸运的是,Perfect公司公布了最新的免费开源项目Perfect SysInfo,即用于实时获取系统性能指标数据的一组函数库。
作为参考,本文的全部源代码可以在这里获得:
http://github.com/PerfectExamples/SystemMonitor-Demo
请确保您的系统已经安装了Swift 3.1工具链。
下载、编译和运行
请打开终端并执行如下命令行进行下载、编译和运行:
$ git clone https://github.com/PerfectExamples/SystemMonitor-Demo.git
$ cd SystemMonitor-Demo
$ swift build
$ ./.build/debug/SystemMonitor
如果成功的化,终端会输出类似 [INFO] Starting HTTP server localhost on 0.0.0.0:8888
的字样。
此时您可以打开浏览器并输入网址:http://localhost:8888
:
源码简介
注意,如果您还不熟悉 Perfect 服务器,请首先尝试学习 Perfect Template 服务器模板项目。
接口函数路由
本服务器包含两个基本路由,一个是/api
,用于读取服务器的JSON实时报告,而/**
则实际上就是映射了index.html
作为主页。
"routes":[
["method":"get", "uri":"/api", "handler":handler],
["method":"get", "uri":"/**", "handler":PerfectHTTPServer.HTTPHandler.staticFiles,
"documentRoot":"./webroot"]
]
系统信息
考虑到 SysInfo
能够提供的系统指标非常丰富,因此有必要只选择需要的指标进行监控。
下列代码过滤出了少量用于监控的指标,并转换为一个JSON字符串。请注意操作系统的差异:
- CPU 用量: 平均空闲事件、系统占用和用户占用,所有指标为百分比
- 空闲内存数量
- 网络吞吐量
- 磁盘吞吐量
extension SysInfo {
static var express: String? {
get {
#if os(Linux)
guard
let cpu = SysInfo.CPU["cpu"],
let mem = SysInfo.Memory["MemAvailable"],
let net = SysInfo.Net["enp0s3"],
let dsk = SysInfo.Disk["sda"],
let wr = dsk["writes_completed"],
let rd = dsk["reads_completed"]
else {
return nil
}
#else
guard
let cpu = SysInfo.CPU["cpu"],
let mem = SysInfo.Memory["free"],
let net = SysInfo.Net["en0"],
let dsk = SysInfo.Disk["disk0"],
let wr = dsk["bytes_written"],
let rd = dsk["bytes_read"]
else {
return nil
}
#endif
guard
let idl = cpu["idle"],
let user = cpu["user"],
let system = cpu["system"],
let nice = cpu["nice"],
let rcv = net["i"],
let snd = net["o"]
else {
return nil
}
let total = (idl + user + system + nice) / 100
let idle = idl / total
let usr = user / total
let sys = system / total
let MB = UInt64(1048576)
let report : [String: Int]
= ["idle": idle, "usr": usr, "sys": sys, "free": mem,
"rcv": rcv, "snd": snd,
"rd": Int(rd / MB), "wr": Int(wr / MB)]
do {
return try report.jsonEncodedString()
}catch {
return nil
}//end do
}
}
}
执行这段代码后,产生的JSON字符串应该看起来像这样:
{"rd":59891,"snd":0,"idle":92,"wr":79394,"sys":3,"usr":4,"free":5671,"rcv":11964}
其中
- idle:CPU空闲用量百分比,例子中为 92%
- sys: CPU系统用量百分比,例子中为3%
- usr: CPU用户用量百分比,例子中为4%
- free: 当前空闲内存,例子中为5.6GB
- rev: 当前主网卡收到数据量,大约12MB
- snd: 当前主网卡发出数据量,基本为0
- rd:当前主硬盘累积读取数据,约60GB
- wr:当前主硬盘累积写入数据,大约80GB
请求/响应 处理器
收到请求后,服务器立刻将系统信息的JSON字符串发回给客户:
func handler(data: [String:Any]) throws -> RequestHandler {
return {
_ , res in
guard let report = SysInfo.express else {
res.status = .badGateway
res.completed()
return
}//end
res.setHeader(.contentType, value: "text/json")
.appendBody(string: report)
.completed()
}
}
网页渲染监控数据
主页内容就相对简单了:即使用promises
(承诺线程)下载服务器数据并在某个绘图框架下渲染,比如使用 ChartJS
:
/// 构造一个图表
function setup(api) {
var ctx = document.getElementById(api).getContext("2d");
return new Chart(ctx, {
type: 'line',
data: { datasets: datagroups[api] },
options: {
scales: {
xAxes: [{
type: 'linear',
position: 'bottom'
}]
}
}
});
}//end setup
/// 从服务器下拉实时数据,JSON解码并在图表中渲染
function update(){
fetch('http://' + window.location.host + '/api',{method: 'get'})
.then( (resp) => { return resp.json() })
.then( (obj) => {
var chart = charts["cpu"];
var dset = chart.chart.config.data.datasets;
appendDataTo(dset, "CPU-idle", counter, obj.idle);
appendDataTo(dset, "CPU-user", counter, obj.usr);
appendDataTo(dset, "CPU-system", counter, obj.sys);
chart.update();
var chart = charts["mem"];
var dset = chart.chart.config.data.datasets;
appendDataTo(dset, "MEM-free", counter, obj.free);
chart.update();
var chart = charts["net"];
var dset = chart.chart.config.data.datasets;
appendDataTo(dset, "NET-recv", counter, obj.rcv);
appendDataTo(dset, "NET-snd", counter, obj.snd);
chart.update();
var chart = charts["ios"];
var dset = chart.chart.config.data.datasets;
appendDataTo(dset, "DISK-read", counter, obj.rd);
appendDataTo(dset, "DISK-write", counter, obj.wr);
chart.update();
counter += 1;
});
}//end function
/// repeatedly polling data every second
window.setInterval(update, 1000);
更多信息
关于本项目更多内容,请参考perfect.org。
关注Perfect 源代码仓库并给我们的项目加一个大星星✨:
https://github.com/PerfectlySoft/Perfect