天天看点

利用zabbix生成awstats日志分析图表并用Python调用zabbix API批量添加item

  awstats作为一款日志分析软件,功能不错,但是界面过于简单,也没有图表功能,这里我采取了一种变通的方法,将awstats的分析结果(pv、hits(文件数)、bandwidth、visits(独立ip))添加到zabbix,并通过zabbix生成趋势图表。

    在前两篇文章中,我们队awstats的使用及其工作方式进行了简明扼要的介绍:awstats对每个站点进行分析之后,会生成一个“awstats012016.txt”格式的“数据库”文件;awstats的展示页面便是从该文件中取数据生成的。

<a href="http://kaifly.blog.51cto.com/3209616/1719248" target="_blank">    1. 多server多站点情况下awstats日志分析</a>

<a href="http://kaifly.blog.51cto.com/3209616/1770137" target="_blank">    2. awstats CGI模式下动态生成页面缓慢的改进</a>

    这篇文章的思路就是从这个文本格式的‘数据库文件’中取得我们想要的数据,然后通过自定义的脚本将其添加到zabbix中,最终满足我们生成pv趋势图表的需求。

    而完成此任务的关键就是分析似‘awstats052016.txt’的数据文件的内容格式(ps:以笔者“多年”shell经验来看,”分析源文件格式“和“生成目标文件格式”这俩“格式”在日常的shell编程中占用了很大一部分时间。扯远了O(∩_∩)O~)

    首先是自定义脚本作为zabbix的key,从对应的‘数据文件’中取得pv、hits、bandwidth、visits的值。用shell实现如下

cat web_pv.sh

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

<code>#!/bin/sh</code>

<code>#从例如api/awstats052016.txt这样的awstats数据库文件里取得昨天的pv等统计(因为awstats本身就是统计到昨天的日志)</code>

<code>#by  ljk  20160506</code>

<code>#blog    http://kaifly.blog.51cto.com/</code>

<code>#shell脚本的$1 $2分别代表站点名称(格式如www或bbs)和统计项(pv 文件数 字节 独立ip)</code>

<code>basedir=</code><code>'/usr/local/awstats-7.4/result'</code>

<code>date_f1=$(</code><code>date</code> <code>+%m%Y -d </code><code>'1 day ago'</code><code>)</code>

<code>date_f2=$(</code><code>date</code> <code>+%Y%m%d -d </code><code>'1 day ago'</code><code>)</code>

<code>cd</code> <code>$basedir/$1</code>

<code>#下面关于awk的用法中有一个小技巧,匹配到指定的项之后,停止继续搜索余下的内容。这对于体积较大的文件可以节约不少时间</code>

<code>content=`</code><code>awk</code> <code>'$1 == "'</code><code>$date_f2</code><code>'" {{print} {exit}}'</code> <code>awstats$date_f1\.txt`</code>

<code>case</code> <code>$2 </code><code>in</code>

<code>    </code><code>"pages"</code><code>)</code>

<code>        </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $2}'</code><code>;;    </code><code>#pv</code>

<code>    </code><code>"hits"</code><code>)</code>

<code>        </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $3}'</code><code>;;    </code><code>#hits/文件数</code>

<code>    </code><code>"bandwidth"</code><code>)</code>

<code>        </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $4}'</code><code>;;    </code><code>#bandwidth/字节</code>

<code>    </code><code>"visits"</code><code>)</code>

<code>        </code><code>echo</code> <code>$content|</code><code>awk</code> <code>'{print $5}'</code><code>;;    </code><code>#visits/独立ip</code>

<code>    </code><code>*)</code>

<code>        </code><code>echo</code> <code>"unknow value"</code><code>;;</code>

<code>esac</code>

然后在awstats所在的server的zabbix的‘userparameter.conf’文件中添用户自定义key,并重启zabbix_agentd

<code>UserParameter=web_pv[*],</code><code>/bin/sh</code> <code>/usr/local/zabbix/etc/zabbix_agentd</code><code>.conf.d</code><code>/web_pv</code><code>.sh $1 $2</code>

接着在zabbix_server端通过zabbix_get命令尝试获取这些值,key格式为“web_pv[站点名,监控项]”,例如

能取到值,说明自定义key是ok的。

    接下来就是在zabbix里添加各站点的item了,这里通过Python实现(zbx接口通过json传递数据,处理json python比shell方便太多了)

    首先在zabbix里创建一个template,名为Template site PV,这一步手动创建即可

然后开始通过Python自动化添加items

cat shells/add_web-pv_item_to_zabbix.py

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

<code>#!/bin/env python3</code>

<code>"""</code>

<code>将各站点的4种(pages,hits,bandwidth,visits)item添加/更新到zabbix的 'Template Site-PV'</code>

<code>by ljk  20160507</code>

<code>import</code> <code>os,requests</code>

<code>basedir</code><code>=</code><code>'/usr/local/services/awstats-7.4/result/'</code>

<code>items</code><code>=</code><code>[</code><code>'pages'</code><code>,</code><code>'hits'</code><code>,</code><code>'bandwidth'</code><code>,</code><code>'visits'</code><code>]</code>

<code>url</code><code>=</code><code>'http://192.168.1.199/api_jsonrpc.php'</code>

<code>zbx_api_headers</code><code>=</code><code>{</code><code>'Content-Type'</code><code>:</code><code>'application/json-rpc'</code><code>}    </code><code>#定义通过zabbix api操作时必带的header</code>

<code>#取得用于zabbix api认证的token,通过用户名密码请求api生成</code>

<code>#生成方式请参考api文档,有个这个token,可以省去账号密码认证</code>

<code>api_auth</code><code>=</code><code>"738024dfda33cc6020fb1f5e3617"</code> 

<code>#这里我在前期实验的时候,手动添加了几个item了,所以这里先取出template里已经存在的item,以便后期创建时过滤掉这些item</code>

<code>exist_items_filter</code><code>=</code><code>{    </code><code>#通过zabbix api查询已经存在的web_pv[*,*]的item,这里是json格式的过滤条件</code>

<code>    </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>

<code>    </code><code>"method"</code><code>: </code><code>"item.get"</code><code>,</code>

<code>    </code><code>"params"</code><code>: {</code>

<code>        </code><code>"output"</code><code>:[</code>

<code>            </code><code>"name"</code><code>,</code>

<code>        </code><code>],</code>

<code>        </code><code>"search"</code><code>: {</code>

<code>            </code><code>"key_"</code><code>:</code><code>"web_pv"</code>

<code>        </code><code>}</code>

<code>    </code><code>},</code>

<code>    </code><code>"auth"</code><code>:api_auth,</code>

<code>    </code><code>"id"</code><code>: </code><code>0</code>

<code>}</code>

<code>exist_items</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>exist_items_filter)</code>

<code>os.chdir(basedir)</code>

<code>sites</code><code>=</code><code>os.listdir(path</code><code>=</code><code>'.'</code><code>)</code>

<code>def</code> <code>create_item():</code>

<code>    </code><code>for</code> <code>site </code><code>in</code> <code>sites:</code>

<code>        </code><code>for</code> <code>item </code><code>in</code> <code>items:</code>

<code>            </code><code>if</code> <code>site</code><code>+</code><code>'-'</code><code>+</code><code>item </code><code>not</code> <code>in</code> <code>exist_items.text:</code>

<code>                </code><code>#先给不同情况下的units和multiplier赋值</code>

<code>                </code><code>if</code> <code>item</code><code>=</code><code>=</code><code>'pages'</code> <code>or</code> <code>item</code><code>=</code><code>=</code><code>'hits'</code><code>:</code>

<code>                    </code><code>units</code><code>=</code><code>'万'</code>

<code>                    </code><code>multiplier</code><code>=</code><code>0.0001</code>

<code>                </code><code>elif</code> <code>item</code><code>=</code><code>=</code><code>'bandwidth'</code><code>:</code>

<code>                    </code><code>units</code><code>=</code><code>'B'</code>

<code>                    </code><code>multiplier</code><code>=</code><code>1</code>

<code>                </code><code>else</code><code>:</code>

<code>                    </code><code>units</code><code>=</code><code>''</code>

<code>                </code><code>#定义创建item的json数据格式</code>

<code>                </code><code>num</code><code>=</code><code>10</code>

<code>                </code><code>create_item_post</code><code>=</code><code>{</code>

<code>                    </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>

<code>                    </code><code>"method"</code><code>: </code><code>"item.create"</code><code>,</code>

<code>                    </code><code>"params"</code><code>: {</code>

<code>                        </code><code>"name"</code><code>: site</code><code>+</code><code>','</code><code>+</code><code>item,</code>

<code>                        </code><code>"key_"</code><code>: </code><code>"www_pv["</code><code>+</code><code>site</code><code>+</code><code>','</code><code>+</code><code>item</code><code>+</code><code>"]"</code><code>,</code>

<code>                        </code><code>"hostid"</code><code>: </code><code>"10134"</code><code>,</code>

<code>                        </code><code>"type"</code><code>: </code><code>0</code><code>,</code>

<code>                        </code><code>"value_type"</code><code>: </code><code>3</code><code>,</code>

<code>                        </code><code>"history"</code><code>: </code><code>7</code><code>,</code>

<code>                        </code><code>"delay"</code><code>: </code><code>28800</code><code>,</code>

<code>                        </code><code>"units"</code><code>: units,</code>

<code>                        </code><code>"applications"</code><code>: [</code><code>774</code><code>],</code>

<code>                        </code><code>"interfaceid"</code><code>: </code><code>"0"</code><code>,</code>

<code>                        </code><code>"formula"</code><code>: multiplier</code>

<code>                    </code><code>},</code>

<code>                    </code><code>"auth"</code><code>: api_auth,</code>

<code>                    </code><code>"id"</code><code>: num</code>

<code>                </code><code>}</code>

<code>                </code><code>try</code><code>:</code>

<code>                    </code><code>create_item_result</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>create_item_post)            </code>

<code>                    </code><code>#打印处理每个条目的结果</code>

<code>                    </code><code>print</code><code>(</code><code>'{}-{}: return_code {} details {}'</code><code>.</code><code>format</code><code>(site,item,create_item_result.status_code,create_item_result.json))</code>

<code>                    </code><code>num</code><code>+</code><code>=</code><code>1</code>

<code>                </code><code>except</code><code>:</code>

<code>                    </code><code>print</code><code>(</code><code>'{}-{}: error'</code><code>.</code><code>format</code><code>(site,item))</code>

<code>                    </code><code>import</code> <code>sys</code>

<code>                    </code><code>sys.exit(</code><code>255</code><code>)</code>

<code>#create_item()</code>

<code>#update函数,其实是我在执行create_item()的时候将key的名字写错了,无奈在写一个update_item()吧</code>

<code>def</code> <code>update_item():</code>

<code>    </code><code>num</code><code>=</code><code>100</code>    <code>#对应zbx api中的id字段,随意指定,确保每次调用api时该值不同即可(这里用自增的方式)</code>

<code>    </code><code>#定义更新item的json数据格式</code>

<code>    </code><code>update</code><code>=</code><code>{</code>

<code>        </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>

<code>        </code><code>"method"</code><code>: </code><code>"item.update"</code><code>,</code>

<code>        </code><code>"params"</code><code>: {</code>

<code>            </code><code>"itemid"</code><code>: "",</code>

<code>            </code><code>"key_"</code><code>: ""</code>

<code>        </code><code>},</code>

<code>        </code><code>"auth"</code><code>: api_auth,</code>

<code>        </code><code>"id"</code><code>: num</code>

<code>    </code><code>}</code>

<code>    </code><code>#取得site pv模板下所有错误的item(key以www_py开头的),hostid的值实际为template site PV模板的templateid</code>

<code>    </code><code>wrong_items_filter</code><code>=</code><code>{</code>

<code>            </code><code>"jsonrpc"</code><code>: </code><code>"2.0"</code><code>,</code>

<code>            </code><code>"method"</code><code>: </code><code>"item.get"</code><code>,</code>

<code>            </code><code>"params"</code><code>: {</code>

<code>               </code><code>"output"</code><code>:[</code><code>"key_"</code><code>,</code><code>"hostid"</code><code>],</code>

<code>                </code><code>"search"</code><code>: {</code><code>"hostid"</code><code>:</code><code>"10134"</code><code>,</code><code>"key_"</code><code>:</code><code>"www_pv"</code><code>}</code>

<code>            </code><code>},</code>

<code>            </code><code>"auth"</code><code>: api_auth,</code>

<code>            </code><code>"id"</code><code>: </code><code>0</code>

<code>    </code><code>wrong_items</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>wrong_items_filter).json()[</code><code>'result'</code><code>]    </code><code>#wrong_items为list</code>

<code>    </code><code>for</code> <code>wrong_item </code><code>in</code> <code>wrong_items:</code>

<code>        </code><code>if</code> <code>wrong_item[</code><code>'hostid'</code><code>] !</code><code>=</code> <code>'10119'</code><code>:    </code><code>#img2从template site pv继承而来 所以这里每个item对应两条记录对应template site pv的hostid:10134和img2的hostid:10119,所以不需要修改img2的</code>

<code>            </code><code>update[</code><code>'params'</code><code>][</code><code>'itemid'</code><code>]</code><code>=</code><code>wrong_item[</code><code>'itemid'</code><code>]</code>

<code>            </code><code>update[</code><code>'params'</code><code>][</code><code>'key_'</code><code>]</code><code>=</code><code>wrong_item[</code><code>'key_'</code><code>].replace(</code><code>'www'</code><code>,</code><code>'web'</code><code>,</code><code>1</code><code>)            </code>

<code>            </code><code>try</code><code>:</code>

<code>                </code><code>update_item_result</code><code>=</code><code>requests.post(url,headers</code><code>=</code><code>zbx_api_headers,json</code><code>=</code><code>update)</code>

<code>                </code><code>print</code><code>(</code><code>'{} ---- details {}'</code><code>.</code><code>format</code><code>(wrong_item[</code><code>'key_'</code><code>],update_item_result.json()))</code>

<code>                </code><code>num</code><code>+</code><code>=</code><code>1</code>

<code>            </code><code>except</code><code>:</code>

<code>                </code><code>print</code><code>(</code><code>'{}-{}: error'</code><code>.</code><code>format</code><code>(site,item))</code>

<code>                </code><code>import</code> <code>sys</code>

<code>                </code><code>sys.exit(</code><code>255</code><code>)</code>

<code>#update_item()</code>

    后续的批量生成image和生成screen都可以通过zbx 的API来完成,这里就不再列举了  

    ok,最后看两张zabbix生成的靓图吧

<a href="http://s5.51cto.com/wyfs02/M02/80/00/wKiom1cz7y3gx8H_AAFbYDcLV3Q395.png" target="_blank"></a>

<a href="http://s1.51cto.com/wyfs02/M01/80/00/wKiom1cz77qSrYKWAAGSoXMhnv4994.png" target="_blank"></a>

     本文转自kai404 51CTO博客,原文链接:http://blog.51cto.com/kaifly/1772377,如需转载请自行联系原作者