“凡是过去,皆为序曲”
— 莎士比亚
前言:本文其实是给公司写的一篇文章,不过因为时间仓促,当时文章并没有关于代码的分析,只是关于数据的展示,不过觉得很有价值,所以再做分享。
了解我的人,当然知道,本宝宝要大家跟我做的第一件事是什么~
首先,大家跟我念,Python大fa好。
本文皆是一家之言,如有偏颇还望指正。
在笔者的看来,如果数据不能可视化话,那么很大程度来说就是在扯淡,当然数据可视化也仅仅是万里长征第一步。数据就像一堆堆的石子,也许不能就这一篇文章带领大家观其全貌,但至少管中窥豹,可见一斑。
那么数据到底长什么样呢?
它可能长这样。
又或者是这样
如果你 Excel 足够牛逼我想你是能够用 excel 做出足够厉害的图的,但也只是足够而已。
在笔者看来数据至少是长这样。
再或者是这样的。
注:上面使用的是 ELK 套件
ELK安装文档,参考: http://youerning.blog.51cto.com/10513771/1726338
但这只是冰山一角,还远远不够,工具谁能用,怎么用是一个层次,在这基础上再次利用则是另一个层次,为了文章篇幅,本文主要着重于后者并将视线锁定在日志数据,其他数据暂不考虑。
日志的数据至少得有三个作用
一:数据应该能说明问题或者现象。
二:数据应该能解决问题。
三:数据应该能预测与预防问题。
第一点很好理解那就是,数据在可视化的过程能够很直观的说明问题或者现象,即使通过最基本的提取过滤,我们能够知道在一段时间内多大的访问量,客户端的设备是什么,响应时间多少,在往下细化,应该是每个 ip 的访问次数,并且访问了什么内容,常访问什么内容,在知道响应时间的前提上,了解哪个访问链接耗时最长等等,以及一些可能职责之外的事,具体细节请自行脑洞。
下面是简单的全球访问 IP 热点图:
注:不要问我为什么不用 ELK 自带的热点图,两个字,任性 ~
第二点,既然日志能说明问题当然能解决问题,日志文件除了最基本的 info 记录,当然还有 debug 信息,通过 debug 信息我们知道程序运行到什么地方抛出了这个 bug ,为什么抛出这个 bug ,为了第一时间响应,我们还得快速定位到抛出 bug 的主机。
通过简单的查询我们可以快速定位到 404 状态发生的主机,及其发生时间,以及客户端的使用设备为什么,以及在访问什么的时候抛出 404 。
第三点,问题在一定程度上并不可怕,可怕的是不能及时处理以及反复出现却束手无策,所以怎样有效的利用数据的基础上再配合可靠并实时监控报警机制就显得至关重要了。而关于预测,可以通过的一定的算法数据都量化,然后评估以及模拟。
谈完了基础,我们着重谈谈日志数据的再次利用。
也主要分为三个部分:
一:简单统计,无论通过 rrdtool 或者 Excel ,或者 Python ,只要有数据,通过预选及数据清洗,就能得到自己想要的数据,在拥有数据的情况下,可视化也就显得自然而然了。
二:统计细化,数据的可视化可能只是数据分析的一部分,因为可视化只能展示很简单的结果,并不能听见数据内心中呐喊的声音,所以一定程度的统计技术以及编程基础相当重要,庆幸的是 Python 有足够的支持库。
三:统计分析,这一方面可能较于大多数人并无用处,并且并不关心,所以在此略过。
一:简单统计
单日的 Top IP , Top URL , Top City 开始吧。
Top IP
Top URL
Top 城市
由上面三个图,我们就能直观知道我们当日最常访问的 IP , URL ,以及城市,单个 IP 太频繁并次数过多我们需要注意, URL 可以帮助我们评估,而城市可以让我们知道服务的受众分布情况,而最简单的一个作用可能就是 CDN 加速了,其他方面请大家自行脑洞,这里不做展开。
二:统计细化
我们在上面的基础上再次细化,比如每个城市中的终端设备使用情况,如下图
当然也可以反过来看
三:统计分析
我们简单看看用户终端设备,安卓与苹果的相关系数。
基本走势图分析
以及各终端相关关系,如下
再或者
相关关系。
无论是从走势或者相关系数,当日安卓与苹果存在一定的的相关性。
在第三部分的附图中,可能大多数人除了走势图,大都看不懂,在这里也不会过多的讲解各个参数以及所对应的关系,因为讲解这些内容的时间可能比这一篇文章还会长,虽然这并算不上大数据,但是还是想借用《大数据时代》里的一句话,作为本文的结尾。“大数据告诉我们“是什么”而不是“为什么”。在大数据时代,我们不必知道现象背后的原因,我们只要让数据自己发声。”
注:因为是取的其中一天的数据,在误差存在的同时数据处理过程中也存在也有很多的不规范,但这篇文章主要是为了给大家一些关于数据的认识。
好吧,上面就是传说中的PPT了,就算你不看文字内容,但是你也大概能知道通过数据可视化,我们能够将数据的展现形式做到上面程度,而下面的内容只要就是关于其中一部分可视化的代码讲解。
因为本文的数据是基于Elasticsearch存储的,所以先决条件,你得有存在Elasticsearch里的数据内容,如果你对Pandas有所了解,你可能看看代码也就知道怎么回事了
# -*- coding: utf-8 -*- #============================================================================== # 用于生成Top IP,Top URL,历史 Top IP,Top URL #============================================================================== import pandas as pd from pandas import DataFrame import matplotlib.pyplot as plt import numpy as np import seaborn as sns from elasticsearch import Elasticsearch import arrow ##es api es = Elasticsearch(["http://IP:9200/"]) ##时间设定 #time_now = arrow.now().format("X") + "000" index_today = "logstash-" + arrow.now().format("YYYY.MM.DD") index_all = "logstash-*" #time_yesterday = arrow.now().replace(days=-1).format("X") + "000" #time_year = arrow.now().replace(years=-1).format("X") + "000" ##查询字段 q_url="xxx_url" q_ip="xxxx_ip" ##查询语句设定函数 def top_search(query_str): rets = """{ "size":0, "query":{ "filtered":{ "filter":{ "bool":{ "must":[ { "term":{"type":"xxxxx_access"}} ] } }, "query": { "query_string": { "query": "!xxxxx", "analyze_wildcard": true } } } }, "aggs":{ "%s":{ "terms":{"field":"%s", "size":15} } } }""" %(query_str,query_str + ".raw") return rets ##执行查询 today_top_ip = es.search(index=index_today,body=top_search(q_ip)) today_top_url = es.search(index=index_today,body=top_search(q_url)) year_top_ip = es.search(index=index_all,body=top_search(q_ip)) year_top_url = es.search(index=index_all,body=top_search(q_url)) df_today_ip = DataFrame(today_top_ip["aggregations"][q_ip]["buckets"]) df_today_url = DataFrame(today_top_url["aggregations"][q_url]["buckets"]) df_all_ip = DataFrame(year_top_ip["aggregations"][q_ip]["buckets"]) df_all_url = DataFrame(year_top_url["aggregations"][q_url]["buckets"]) p1 = sns.factorplot(x="key",y="doc_count",data=df_today_ip, kind="bar",palette="summer") p1.set_xticklabels(rotation=90) p1.set_titles("Today Top 15 IP") p1.savefig("topip_today.png",dpi=100) p3 = sns.factorplot(x="key",y="doc_count",data=df_all_ip, kind="bar",palette="summer") p3.set_xticklabels(rotation=90) p3.set_titles("Top 15 IP") p3.savefig("topip.png",dpi=100)
通过上面的代码,我们能够生成当日的Top 15 IP以及历史Top 15 IP。
值得注意的是,你是能够单纯通过Kibana过滤出这些数据的,并且也很好看,但是为什么用Python呢,因为通过Kibana能够数据可视化,不过对于数据的再利用就不那么理想了,比如生成报表或者一些更高级的可视化定制,这里主要是为了给大家一个通过Python调用Elasticsearch APi的基本认识。
下面主要挑几个重要的部分讲解。
首先安装依赖库:
pip install elasticsearch
至于pandas之类的科学分析库安装请参考: http://youerning.blog.51cto.com/10513771/1711008
然后基本调用。
from elasticsearch import Elasticsearch import arrow ##es api es = Elasticsearch(["http://IP:9200/"])
查询语句参考官方:https://www.elastic.co/guide/en/elasticsearch/reference/1.7/search.html
doc = """{"size":0, "query":{ "filtered":{ "filter":{ "bool":{ "must":[ { "term":{"type":"xxxxx_access"}} ] } }, "query": { "query_string": { "query": "!xxxxx", "analyze_wildcard": true } } } }, "aggs":{ "ip":{ "terms":{"field":"xxx_ip", "size":15} } } }"""
上面的语句的意思分别是返回查询结果0 =>size = 0
然后查询条件type为“xxxx_access”的数据,并查询非”xxxxx”的内容,即过滤有xxxx的字符串。
然后就是我们主要用到的aggs,aggs代表聚合,因为Elasticsearch的其中一个强大之处,就是关于数据的处理,我们有过aggs,聚合条件为xxx_ip,所以返回的结果是统计过的结果,比如这个IP一共多少次,而这里的我们设置size=15,即返回15条聚合过的数据。
然后我们执行查询:
In [19]: es.search(index=index_today,body=top_search(q_ip))
查询结果如上
总结:数据的使用多种多样,只要你脑洞够大 ~~~
后记:其实运维工程师手里拥有大量资源,但是无论上级或者运维工程师本人却不予重视,一方面是是因为编程的一定门槛,再者就是画地为牢,不过像我这样的运维工程师,应该可能也不太像个传统的运维工程师了吧,毕竟最本质的职责是对于系统的维护,以及故障处理等,在本文的数据再利用的三个方面,我想大多数同行觉得第一层利用就远远足够了,不过随着时代的发展,数据爆发式的增长的今天,我们真的能对自己手上的大量资源,不闻不问么。