我想从我的服务器监控一些网站。上下时间存储在数据库中。
目前我的桌子看起来像这样:
id (INT)
website_id (INT)
uptime (DATETIME)
downtime (DATETIME)
lastState (INT)
lastState存储最后一个HTTP-StatusCode
我的网站No 5例如有以下条目:
+----+------------+---------------------+---------------------+-----------+---------------------+---------------------+
| id | website_id | up | down | lastState | created_at | updated_at |
+----+------------+---------------------+---------------------+-----------+---------------------+---------------------+
| 5 | 5 | 2018-04-26 13:56:09 | 2018-04-27 10:42:14 | 503 | 2018-04-26 11:56:09 | 2018-04-26 11:56:09 |
| 13 | 5 | 2018-04-27 10:50:06 | 2018-05-10 08:32:13 | 503 | NULL | NULL |
| 20 | 5 | 2018-05-10 08:40:06 | 2018-05-14 03:02:14 | 503 | NULL | NULL |
| 23 | 5 | 2018-05-14 03:10:06 | NULL | 301 | NULL | NULL |
+----+------------+---------------------+---------------------+-----------+---------------------+---------------------+
我每10分钟检查一次网站,当主机关闭时,会创建一个新条目。我认为(或者更好,我希望)这是有道理的。
我对这种数据存储的唯一问题是我想计算正常运行时间百分比。我认为使用纯SQL是不可能的。
请与我分享您的想法。 谢谢!
答案 0 :(得分:0)
由于您的日志系统做得非常好,因此它很简单"在纯SQL中以日志计算网站正常运行时间
这是一种方法。它适用于任何最新版本的MySQL。如果您运行最新版本(8),则可以使用新的窗口函数,使用更少的指令来执行此操作
我分解每一步。 (请注意,我将您的表命名为monitoring
)
首先,我们要收集同一网站的并发日志的同一行,正常运行时间和停机时间:
SELECT m.website_id, m.uptime, m.downtime, m.lastState ,
COALESCE((
SELECT uptime
FROM monitoring mold
WHERE m.downtime < mold.uptime AND mold.website_id=m.website_id
GROUP BY website_id
), NOW()) AS lastuptime
FROM monitoring m
返回
| website_id | uptime | downtime | lastState | lastuptime |
|------------|----------------------|----------------------|-----------|----------------------|
| 5 | 2018-04-26T13:56:09Z | 2018-04-27T10:42:14Z | 503 | 2018-04-27T10:50:06Z |
| 5 | 2018-04-27T10:50:06Z | 2018-05-10T08:32:13Z | 503 | 2018-05-10T08:40:06Z |
| 5 | 2018-05-10T08:40:06Z | 2018-05-14T03:02:14Z | 503 | 2018-05-14T03:10:06Z |
| 5 | 2018-05-14T03:10:06Z | (null) | 301 | 2018-05-15T14:19:06Z |
请注意,lastuptime
列始终与同一网站的下一行的uptime
相同。如果没有&#34; next&#34;那么这意味着网站已启动,因此我们将NOW()作为参考日期时间。
接下来,通过上述查询,我们可以轻松地进行行内计算,以测量正常运行时间和停机时间之间的时差(秒)
SELECT
mm.*,
TIME_TO_SEC(TIMEDIFF(COALESCE(downtime, NOW()), uptime)) AS uptime_seconds,
TIME_TO_SEC(TIMEDIFF(lastuptime, COALESCE(downtime, NOW()))) AS downtime_seconds
FROM
(
SELECT m.website_id, m.uptime, m.downtime, m.lastState ,
COALESCE((
SELECT uptime
FROM monitoring mold
WHERE m.downtime < mold.uptime AND mold.website_id=m.website_id
GROUP BY website_id
), NOW()) AS lastuptime
FROM monitoring m
) mm
返回
| website_id | uptime | downtime | lastState | lastuptime | uptime_seconds | downtime_seconds |
|------------|----------------------|----------------------|-----------|----------------------|----------------|------------------|
| 5 | 2018-04-26T13:56:09Z | 2018-04-27T10:42:14Z | 503 | 2018-04-27T10:50:06Z | 74765 | 472 |
| 5 | 2018-04-27T10:50:06Z | 2018-05-10T08:32:13Z | 503 | 2018-05-10T08:40:06Z | 1114927 | 473 |
| 5 | 2018-05-10T08:40:06Z | 2018-05-14T03:02:14Z | 503 | 2018-05-14T03:10:06Z | 325328 | 472 |
| 5 | 2018-05-14T03:10:06Z | (null) | 301 | 2018-05-15T14:23:16Z | 126790 | 0 |
我们已经可以从这些结果中注意到您的停机时间大多是相同的(472或473秒)。
最后一步是计算每个网站的停机时间和正常运行时间的总秒数,并确定正常运行时间的百分比
SELECT website_id,
SUM(uptime_seconds) AS uptime_seconds,
SUM(downtime_seconds) AS downtime_seconds,
(100 - SUM(downtime_seconds)/SUM(uptime_seconds)*100) AS pourc_uptime
FROM
(
SELECT
mm.*,
TIME_TO_SEC(TIMEDIFF(COALESCE(downtime, NOW()), uptime)) AS uptime_seconds,
TIME_TO_SEC(TIMEDIFF(lastuptime, COALESCE(downtime, NOW()))) AS downtime_seconds
FROM
(
SELECT m.website_id, m.uptime, m.downtime, m.lastState ,
COALESCE((
SELECT uptime
FROM monitoring mold
WHERE m.downtime < mold.uptime AND mold.website_id=m.website_id
GROUP BY website_id
), NOW()) AS lastuptime
FROM monitoring m
) mm
) mmm
GROUP BY website_id
返回
| website_id | uptime_seconds | downtime_seconds | pourc_uptime |
|------------|----------------|------------------|--------------|
| 5 | 1641971 | 1417 | 99.9137 |
所以这只显示1个网站和几个日志(你发布的)的结果,但我相信它应该可以正常运行,即使你有100万行
您应该从这些查询中创建一些VIEWS,以使您的生活更轻松。