绘制按天分组的 HTTP 状态代码

问题描述

我有一个带时间戳的 HTTP 状态代码流:

2021-02-09T10:54:00 200 50
2021-02-09T10:57:00 200 35
2021-02-09T11:00:00 200 50
2021-02-09T11:03:00 500 150
2021-02-09T11:06:00 500 350
2021-02-09T11:09:00 500 450
2021-02-09T11:12:00 500 1000
2021-02-09T11:15:00 404 35
2021-02-09T11:18:00 404 50
2021-02-09T11:21:00 200 50
2021-02-09T11:24:00 200 35
2021-02-09T11:27:00 200 50
2021-02-09T11:30:00 200 50

我已经设法设置 gnuplot 来对这些天进行分组:

set xdata time
set ydata time
set format y "%H:%M"
set timefmt "%Y-%m-%dT%H:%M:%s"
set xrange ["2021-02-08T00:00:00":"2021-02-14T23:59:59"]

plot 'availability.csv' using (timecolumn(1,"%Y-%m-%d")):(timecolumn(1,"%H-%M")):2…

我已经找到了很多样本​​,例如对一天求和(框/直方图)或标记每天的时间点(点)。但随着时间的推移,它们都不符合我的可用性目标。

我的目标是每天将一个酒吧分成 15 分钟的区块。每个块都应根据最大状态代码着色,例如HTTP.500=red,HTTP.404=yellow,HTTP.200=green(只有这三个,没有茶壶/重定向/诡异的,颜色就像红绿灯)。 Y 轴是一天中的小时,X 轴是一天。

  1. 我是否走在正确的轨道上,使用 gnuplot 可能吗?
  2. using 子句是什么样的?
  3. 如何将分箱到 15 分钟的间隔合并到第二列中?
  4. 如何为特定代码着色? (它不像根据频率计算颜色的热图)

解决方法

我会从以下内容开始。

  • import cv2 import numpy as np import PIL.ImageGrab x = 100 y = 100 w = 50 h = 50 pos = [x,y,w,h] # wrong #pos = [x,x+w,y+h] # correct print('bbox:',pos) print('---') img = PIL.ImageGrab.grab(pos) print('img:',img) print('type(img):',type(img)) print('img.size:',img.size) print('---') arr = np.array(img) print('arr:',arr) print('type(arr):',type(arr)) print('arr.size:',arr.size) print('arr.shape:',arr.shape) print('---') cv2.imshow('test',arr) print('Press ESC to exit') while cv2.waitKey(100) != 27: pass 不会从 timecolumn(1,"%H-%M") 之类的时间字符串中提取小时和分钟。据我所知,首先我们必须提取 "2021-02-08T12:34:56" 部分,然后将其转换为小时和分钟:

    12:34

  • 时间戳在内部以秒为单位存储,因此可以使用整数除法将其分箱为 15 分钟(= 900 秒):strptime("%H:%M",strcol(1)[12:17])

  • int(<seconds>)/900*900.0 这样的 gnuplot 命令计算表达式并绘制值。这用于...

  • “手动”选择 bin 内的最大值。该脚本遍历 bin 内的所有点并记住最大值。请阅读plot "a.dat" using 1:(<expression>,value)。我使用三元运算符两次:一次用于检查 bin,一次用于检查最大值

  • 关于颜色,请阅读help ternary

这是完整的脚本:

help set palette

结果如下:

max status code by 15 minute bins

我认为我们还没有完成,应该添加一个图例,检查 set xdata time set ydata time set format y "%H:%M" set timefmt "%Y-%m-%dT%H:%M:%S" set xrange ["2021-02-08T00:00:00":"2021-02-14T23:59:59"] set palette defined (200 "green",400 "yellow",500 "red") unset colorbox bin = 0 bin_before = 0 max_value = 0 plot 'availability.csv' using \ (timecolumn(1,"%Y-%m-%d")):\ (bin = (int(strptime("%H:%M",strcol(1)[12:17]))/900*900),bin):\ (y = $2,bin == bin_before ? (y>max_value ? max_value = y : max_value = max_value) \ : (max_value = y,bin_before = bin),max_value ) \ linecolor palette pt 5 ps 2 notitle splot 的可能性可能会很有趣。

,

有趣的挑战。我的建议如下。这可能不是最简单的,但我会说结果看起来很合理。它使用绘图样式 with boxxyerror(请参阅 help boxxyerror)。

从您的问题中,我知道您想要 15 分钟的分档并仅显示该时间间隔内最大状态的颜色。为什么不显示每个间隔不同状态的直方图?例如:如果区间内有以下HTTP状态:2x 200、1x 404和2x 500,那么这个区间的横条就会被分割成40%绿色、20%黄色和40%红色。

以下代码的基本作用:

  1. 创建一些随机测试数据(仅用于说明)
  2. 使用 smooth freq 对数据进行分箱(检查 help smooth),并为 3 种不同状态添加 1、2、3 秒的小偏移量。
  3. 重新安排一些表格
  4. 使用框的 x,y 位置创建最终表格,并对应分箱间隔内每个状态的相对贡献。

为了更好的理解:

数据块$Data的示例数据:

2021-02-10T12:30:00   200   407
2021-02-10T12:33:00   200   922
2021-02-10T12:36:00   404   615
2021-02-10T12:39:00   200   689
2021-02-10T12:42:00   200   628
2021-02-10T12:45:00   500   10
2021-02-10T12:48:00   200   185
2021-02-10T12:51:00   200   2
2021-02-10T12:54:00   404   743
2021-02-10T12:57:00   200   618

数据块$Histo3的示例数据:

1612960200  5  i
1612960201  4  i
1612960202  1  i
1612961100  5  i
1612961101  3  i
1612961102  1  i
1612961103  1  i

数据块$Histo4的示例数据:

        NaN     0   nan   12:30   0     
 2021-02-10     0   0.8   12:30   1     
 2021-02-10   0.8     1   12:30   2     
        NaN     0   nan   12:45   0     
 2021-02-10     0   0.6   12:45   1     
 2021-02-10   0.6   0.8   12:45   2     
 2021-02-10   0.8     1   12:45   3   
 

代码当然可以优化。所以,把它看作一个起点......

代码:

### status overview as date/time dependent histograms
reset session

# general settings
myDateFmt     = "%Y-%m-%d"                    # date only format
myTimeFmt     = "%H:%M:%S"                    # time only format
myDateTimeFmt = myDateFmt."T".myTimeFmt       # datetime format
SecPerDay     = 24*3600                       # seconds per day
myStatusList  = "200 404 500"                 # possible states
myColorList   = "0x00ff00 0xffff00 0xff0000"  # green,yellow,red

# create some random test data
set print $Data
    myTime = time(0)                                 # now
    myRandomStatus(x) = x<0.70 ? 1 : x<0.95 ? 2 : 3  # random status
    myInterval = 3                                   # interval in minutes
    do for [i=1:5000] {
        myTime = myTime + myInterval*60
        myStatus = word(myStatusList,myRandomStatus(rand(0)))  # random status
        myValue = int(rand(0)*1000)                       # random value 0-999
        print sprintf("%s   %s   %g",strftime("%Y-%m-%dT%H:%M:00",myTime),myStatus,myValue)
    }
set print

# functions
myStatusNo(col) = column(col)==200 ? 1 : column(col)==404 ? 2 : 3
myColor(i)      = int(i) ? int(word(myColorList,int(i))) : 1
myDayTime(t)    = tm_hour(t)*3600 + tm_min(t)*60 + tm_sec(t)

# binning 
BinWidthSec   = 900        # in seconds 900 sec = 15 min
BinTime(col)  = floor(myDayTime(timecolumn(col,myDateTimeFmt))/BinWidthSec)*BinWidthSec

set table $Histo1
    set format x "%.0f"
    plot $Data u (timecolumn(1,myDateFmt)+BinTime(1)):(1) smooth freq
    plot $Data u (timecolumn(1,myDateFmt)+BinTime(1)+myStatusNo(2)):(1) smooth freq
set table $Histo2
    plot $Histo1 u (sprintf("%.0f",$1)):2 w table   # remove empty lines etc.
set table $Histo3
    set format x "%.0f"
    plot $Histo2 u 1:2 smooth freq                  # sort the events by time
unset table

# create final table
myX(col1,col2) = int(column(col1))%4==0 ? (Sum=0.0,Total=column(col2),"NaN") : \
                 strftime(myDateFmt,column(col1))
myXRelStart(col1,col2) = Sum/Total
myXRelEnd(col1,col2) = int(column(col1))%4==0 ? NaN : (Sum=Sum+column(col2),Sum/Total)
BinTimeT(col) = strftime("%H:%M",column(col))

set table $Histo4
    plot $Histo3 u (sprintf("% 10s % 5g % 5g % 7s % 3d",\
         myX(1,2),myXRelStart(1,myXRelEnd(1,BinTimeT(1),tm_sec($1))) w table
unset table

# plot settings
set format x "%d.%m." timedate
set format y "%H:%M" timedate
set style fill transparent solid 0.5 noborder
set yrange [0:SecPerDay]
set tics out
set key out title "HTTP status"

plot $Histo4 u (timecolumn(1,myDateFmt)+($3+$2)/2*SecPerDay) : \
               (timecolumn(4,myTimeFmt)+BinWidthSec/2) : \
               (($3-$2)/2*SecPerDay) : (BinWidthSec/2.):(myColor($5)) \
               w boxxy lc rgb var notitle,\
     for [i=1:3] keyentry w boxes lc rgb myColor(i) title word(myStatusList,i)

### end of code

结果:

enter image description here