丹露 datav数据大屏经验总结

11/21/2017 11:31:46 AM

第一版

丹露成都网络技术有限公司

运维部:周龙波

11/27/2017 2:04:32 PM

第二版

新增 pv/uv 折线图 访问来源 地图 的内网IP过滤功能以及使用新的时间段函数

12/6/2017 3:11:55 PM

第三版

更新如下bug

  1. 解决控制台报错问题:Error: attribute transform: Expected number, "translate(NaN,49.5)"
  2. 添加饼图显示来源网络运营商
  3. 解决PV/UV的折线图 y轴 显示小数问题

先来张目前的效果图,勿喷,我也才开始学习,欢迎大家多多交流:_


运维大屏项目


1. 需求背景

1.多一种途径展示线上运维状况;
2.为运维驱动开发埋下伏笔;
3.对运维自己也是一种自我工作驱动;
4.最最重要的是提升运维逼格,瞬间赶上别人几百万的大屏。。。。。

2. 功能介绍

1. 展示线上所有服务器的资源使用,为后期的资源规划提供依据指导;
2. 对当前压力大的服务器进行针对资源使用报告;
3. 对当前用户的访问地域、访问量做友好展示;
4. 提供自带监控报警展示;
5. 对线上服务所受攻击进行友好展示;
5. 提供线上访问状态码展示;
6. 其他类:当前时间/天气/油价/不宜写代码等展示

3.技术选型介绍

1. 其实主要是为啥很多展示方式,就认准了datav呢?我们现在还有tig(telegraf + influxdb + grafana)的监控展示,也有部分elk(elasticsearch + logstash + kibana)部分展示;入口不同一,维护成本太高了;
2. datav介绍:[DATAV介绍](https://help.aliyun.com/document_detail/30360.html)
3. 为啥选datav:**其实最简单的理由是没多少资源投入,能快速收获成果**

4.datav技术调研

1. datav组件需求功能匹配调研
    1. 访问来源需    地图展示
    2. PV/UV    折线图展示
    3. 访问状态    饼图展示
    4. 资源总消耗情况    数字展示
    5. top5资源使用展示    滚动列表展示
    6. 告警展示    轮播列表
    7. 其他类型    文本展示
2. 数据源类型选择
    1. PV/UV/访问来源地理位置/http访问状态    nginx日志获取
    2. 自建告警信息展示    通过持久化的数据库抽取展示
    3. 资源使用总消耗    通过阿里pop api 接口获取
    4. 自定义文本展示    文本组件
3. 数据源使用配置
    1. 使用数据源之前必须要有访问资源的账号,除了数据库之外,其他的都可以通过ram(访问控制管理服务控制只读权限),方法:略;
    2. RDS等数据库需要建立只读账号,方法:略;
    3. RDS链接信息大概包含:连接地址,端口,登陆账号,登陆密码,实例ID,地域(如果是VPC专网,会有VPC相关的信息,比如VPCid等;建议都通过VPC专网,增强安全性);
    4. 非RDS 连接包含 地域(endpoint),一对AK(AK ID和AK Secret,ram里面分配,建议datav使用的账号都授权只读);
4. 回调ID使用
    1. 回调ID是不同组件间交互的通道,个人理解类似于socket/pipeline等,达到联动的目的;
    2. 用法思路为一个组件申明我提供一个功能,回调ID是A,另一个组件B如果需要使用A的功能,就在B传参变量里指定A即可;
    3. 例子:两个时间轴组件分别每秒产生当前时间戳A和一周前的时间戳B,C云监控组件可以通过starttime 和endtime 对应A/B时间戳 找到过去一周服务器的资源使用情况;
5. 过滤器编写
    1. 过滤器为对当前获取的数据作进一步的加工,比如过滤不必要的字段,转换格式或者产生新的值;
    2. 例子:我从数据库里获取到自定义报警的监控情况,但是时间戳格式和显示的不一样,我需要通过过滤器修改格式;还有就是产生新值,比如当前时间戳;
6. 页面展示调整
    1. 这一步就看你自己的审美了,可以调整组件编排,也可以对组件内容字体等编辑,更可以对整体背景做修饰;一句话,看自己的审美。。。。。

5. datav 需求实现步骤

1. 创建数据源
    1. 如果配置sls(日志服务)的地址时记得加 "http://" 前缀;如:![_](https://yqfile.alicdn.com/78c2e7c2f1205969b891e.png)

    2. 添加RDS配置时主要考虑是否通过vpc专网连接以及添加RDS白名单,目前的datav内网白名单为 "100.104.81.0/24";示例图:![RDS_](https://yqfile.alicdn.com/e360be653b607d0a100bc5da116698335c5f0aed.png)

    3. 配置pop api 数据源时需要注意APIversion值,这个值需要看你使用的接口定义的版本;我这边用的默认都是"2017-03-01";示例图:![pop_api_](https://yqfile.alicdn.com/e7335af7231953948419b09a62ca92a6b61cd4dc.png)

2. 添加组件,调整样式:
    1. 对于会开发的大拿,肯定较熟悉echarts,datav也集成了部分echarts,对于喜欢酷炫的样式的人有福了;
    2. 没特殊要求或者美术功底的话,就默认值我觉得挺好;
3. 添加数据源以及参数注意事项
    1. 数据源选择得根据你的数据原来是在哪儿,通过哪种途径获取来判断,比如我的访问来源地图组件,是通过nginx分析得来的,那我地图的数据源就选择简单日志服务SLS;如果你的数据都存储在RDS数据库,那你就选择数据库;选择pop api 的时候,你还得选择你要调用的接口名称以及返回结果路径,比如我要调用云监控里的QueryMetricList获取监控信息,并直接获取datapoints里的有用数据,我填写的内容为:![pop_api](https://yqfile.alicdn.com/f250df3a7a82204cf66d1e700e0539bd473b267c.png)

    2. 字段映射 为 当前组件所使用字段与你获取的字段不一样而做的,类似于C预言的指针或者shell 里面的软连接;比如我数据库里查出的数据是 username 和password,而组件需要的是name 和 pass,那就需要在name 后面的自定义映射填 username,pass后面填写password,如果填写正确,后面的状态会变成 匹配成功;![_](https://yqfile.alicdn.com/8f38bd36287b513ab10bcc36bc5e5dc498fbbf40.png)

    3. 查询参数 就得看你自己接口得规定了,比如pop api,你得根据你这个接口定义看需要传哪些参数,然后以json传入;如果里面有其他组件的回调ID,你就得把值换成 ":回调ID名";我的sls 查询from 参数为 "from": ":twoDayAgo_unix" ;
4. 添加过滤器
    1. 当你的查询结果不符合当前组件的静态数据格式时,就需要过滤器来处理;我使用最多的是时间格式转换(unix)和产生,数据排序和取部分值,其实js 那么强大,你想做啥都行,但不建议写很重的js,因为当前页面有很多组件很多数据需要处理,节省点资源使用对你整体的响应是有好处的;
    2. 关于我的js内容,我直接贴在文末;

6. 案列教训

1. sls [geoip]访问来源地域展示
    1. 理想中的数据流处理方式为: nginx --> logtail --> sls -->datav(基本地图组件);而我目前的流程是: nginx --> filebeat --> logstash --> sls --> datav(基本地图组件);
    2. 为啥没用阿里云的sls logtail直接收集日志?而且他们的logtail 是针对优化过的。
        1. 答案是 datav的地图基础组件的点热力图 的数据是需要经纬度的,而我nginx日志里面是没有经纬度的;
        2. 当时考虑经纬度可以本地程序翻译,也可以datav调用第三方api翻译;结果datav同一组件只能有一个数据源,而且只能请求同一个接口;好吧就我本地翻译;
    3. 我本地原有就是elk 那一套,只是不想维护,就借用 logstash 来做;在logstash 的配置文件里的filter里添加 geoip{source => "remote_addr"},这样就搞定了;当然如果你的nginx前面有类似阿里云的slb代理,或者客户端本来就通过几级代理过来的,remote_addr 是不会有真实客户端的IP的,所以你需要取http_x_forwarded_for里的值,而且是第一个字段;当然,如果你的nginx直接对外,你还得判断http_x_forwarded_for是否为空;
    4. 到目前为止,你已经可以在阿里云的sls 里面查询到日志了日志显示和日志索引如图;![_](https://yqfile.alicdn.com/3498fa02c0e4ebcaba94b94a61c4d4b6fbcec8b2.png)

_

    5. 根据经纬度获取访问量的 sls sql 为:"  *|select json_extract(replace(geoip,'=>',':'),'$.location') as location ,count(*) as num group by  1  limit 10000  ";细心的同学会发现我的geoip 根本就不是标准的json格式,所以我用了replace 函数把 "=>" 换成 ":",然后根据 sql 的 json查询方式 group by 经纬度组合;sql 的写法可以看:[https://help.aliyun.com/document_detail/53608.html?spm=5176.100239.blogcont204548.20.a3nA4a](https://help.aliyun.com/document_detail/53608.html?spm=5176.100239.blogcont204548.20.a3nA4a);如果sls 的 查询窗口查询不出数据,在datav 也肯定展示不出来的;
    6. 在datav里面选择基本地图组件,点热力层数据源选择sls,填写查询参数![datav_sls_](https://yqfile.alicdn.com/13dd6bd9ff20516d8cd80ef1602e101dd0e8a42f.png)
    7. 此时,数据已经可以查出来了,但是查询出来的值是"经纬度,访问量",不是我们要的 经度/维度/访问量,这儿就需要借助过滤器把经纬度分割成经度和维度;经纬度过滤器关键脚本为:![_](https://yqfile.alicdn.com/cc7ba4230487610f6e400c9f58753d4bd894bd7a.png)

2. PV/UV 展示
    1. PV/UV我是用折线图展示的,具体操作 同 地图基础组件类似,只是查询的sql和过滤器变了;sql变了是因为我查询的内容都变了,添加过滤器是因为查询出来的和静态数据里的标准时间格式有冲突,所以需要处理一下;
    2. 其实大家看我之前给的全屏图就能发现,折线图下面的时间没显示到时和分,这是我数据来源时间跨度想长一点,如果只展示一天的,就在折线图的样式X轴里把时间显示格式换一下就行;如图:![X_](https://yqfile.alicdn.com/4715ed9b2cd030898fb830999b7bbe86ae5df660.png)

7. 后续优化

1. 报错优化
    1. 目前虽然我的每个组件都能按照预想的显示内容,但是按下F12 就能看到一堆堆的报错,这需要留资源进行处理;
    2. 在使用了回调ID后,在调试界面就会报错,比如我 PV的from起始报错:{"errorCode":"ParameterInvalid","errorMessage":"from : NaN pair is invalid"},这是阿里云datav没获取到from的值的原因,希望阿里的同学优化下;
2. 访问速度优化
    1. 每次调试的时候,电脑都会很卡,浏览器会把CPU和MEM吃得很高,每次调试一段时间就得把整个浏览器关闭来释放资源;
    2. 预览的时候如果不是静态数据展示大部分组件得数据展示会非常慢,有些甚至6/7秒钟才有;但是单个数据源得访问却非常快,不明觉厉;
3. 数据展示内容增加
    1. 线上阿里云自带告警展示:需要把阿里云自带的告警内容给展示出来并自己加工标注是否已处理以及什么时候处理;
    2. VPN/网络拓扑等访问速率展示:因为目前使用了华东和华北双中心,都是VPN站到站打通办公网和阿里云的,之前就出现过VPN不稳定导致环境访问和内部工具出现问题,我们需要一个近似实时的访问速率展示;其实就是想从网络层面展示服务器间的网络状态;
    3. 安全类容展示:目前公司接入了较多的阿里云安全类产品,尤其是云盾里的态势感知/安骑士等,我们想把攻击的量变化/攻击类型/攻击来源/不安全资产占比等通过饼图/折线图来展示,但是目前没相关接口可以直接提供,希望阿里的童鞋早点把云盾做到pop api里;

8.使用心得

  • 组件使用了回调ID后,在编辑页面不能把使用回调的异常给过滤;
  • 不能删除已保存的过滤器;
  • 不能多画布共享变量;
  • 安全的 API 还没开放;
  • 云监控不能获取 ECS监控的别名;
  • 添加数据库作为数据源的时候一定要记得白名单,一定要测试连接;
  • nginx日志中文有编码问题,导致部分数据解析不到;
  • 尽量在一个干净的大屏里面调试一个组件,摸索透了再添加到你整体的大屏里;避免排错的时候相互影响;
  • 理论上针对不同场景和业务会有不同的大屏,而你显示的显示屏幕较少的话,可以采取浏览器tab轮播的策略;阿里童鞋有提供教程:https://yq.aliyun.com/articles/209767?spm=5176.100244.teamhomeleft.19.IvOGDK

9. 查询参数及过滤器脚本

统计PV-折线图

适用于从sls 获取 nginx日志,统计PV;
查询参数:
(第一版查询:不过滤nginx的日志是否有内网调用)
`{

"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "pv",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*|select from_unixtime( __time__- __time__% 8640) as t, count(1) as pv  group by __time__- __time__% 8640 order by t limit 60",
"line": 100,
"offset": 0
  }`

(第二版查询:过滤nginx的日志中内网调用的流量并更改更标准的时间段函数)

`  {
"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "pv",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*|select date_trunc('hour',__time__) as t, count(1) as pv,ip_to_domain(remote_addr) as a group by  a,t having ip_to_domain(remote_addr)='internet' order by t limit 60",
"line": 100,
"offset": 0

}`
过滤器:

`data.sort(function(a,b){

var s = a.Average
var t = b.Average
if(s if(s>t) return -1;
})
var temp = [];
data.forEach(function(item){
temp.push({

instanceId :item.instanceId,
Maximum : item.Maximum,
Minimum : item.Minimum,
Average : item.Average

})
})
return temp.slice(0,5); `

统计UV-折线图

适用于从sls 获取 nginx日志,统计UV;
查询参数:
(第一版查询:不过滤nginx的日志是否有内网调用)
`{

"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": ":",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*|select from_unixtime( __time__- __time__% 8640) as t,approx_distinct(remote_addr) as uv group by __time__- __time__% 8640 order by t limit 60",
"line": 100,
"offset": 0

}`
(第二版查询:过滤nginx的日志中内网调用的流量并更改更标准的时间段函数)

`   {
"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": ":",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*|select date_trunc('hour',__time__) as t,approx_distinct(remote_addr) as uv,ip_to_domain(remote_addr) as a group by t,a having ip_to_domain(remote_addr)='internet' order by t limit 60",
"line": 100,
"offset": 0

}`
过滤器:

`var uvTemp = []

var formatDateTime = function (mydate) {

var y = mydate.getFullYear();  
var m = mydate.getMonth() + 1;  
m = m < 10 ? ('0' + m) : m;  
var d = mydate.getDate();  
d = d < 10 ? ('0' + d) : d;  
var h = mydate.getHours(); 
h = h < 10 ? ('0' + h) : h; 
var minute = mydate.getMinutes();  
minute = minute < 10 ? ('0' + minute) : minute;  
var second = mydate.getSeconds();
second = second < 10 ? ('0' + second) : second; 
return y + '/' + m + '/' + d+' '+h + ":"+minute+":"+second

// return y + '/' + m + '/' + d+' '+h + ":"+minute
};
for(var key in data){
var item = data[key]
uvTemp.push({

x:formatDateTime(new Date(item.t) ),
y:item.uv,
s:1

})
}
return uvTemp;`

http状态分布-饼图

适用于从sls 获取 nginx日志,统计http 请求状态;
查询参数:
` {

"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*| select status, count(1) as pv group by status order by pv desc  limit 5",
"line": 100,
"offset": 0

}`
映射名:

`type:status,value:pv`

过滤器(需要转换查询里面的PV为int类型):

`return Object.keys(data).map((key) => {

let d= data[key];
d["pv"] = parseInt(d["pv"]);
return d;
})`

访问来源运营商分布-饼图

适用于从sls 获取 nginx日志,统计访问来源运营商的比例;
查询参数:

`    {
"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "net_type",
"from": ":oneDayAgo_unix",
"to": ":now_unix",
"query": "*|select ip_to_provider(remote_addr) as net_type,count(*) as num group by 1 order by num desc",
"line": 100,
"offset": 0

}`

过滤器:

`return Object.keys(data).map((key) => {

let d= data[key];
d["type"] = d["net_type"];
d["value"] = parseInt(d["num"]);
return d;
}
)`

访问来源展示-地图

适用于从sls 获取 nginx日志,统计访问来源以及每个来源的请求量;
查询参数:
(第一版查询:不过滤nginx的日志是否有内网调用)

`{
"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "",
"from": ":twoDayAgo_unix",
"to": ":now_unix",
"query": "*|select json_extract(replace(geoip,'=>',':'),'$.location') as location ,count(*) as num group by  1  limit 10000",
"line": 100,
"offset": 0

}`
(第二版查询:过滤nginx的日志中内网调用的流量)

`{
"projectName": "hd-danlu",
"logStoreName": "nginx",
"topic": "",
"from": ":twoDayAgo_unix",
"to": ":now_unix",
"query": "*|select json_extract(replace(geoip,'=>',':'),'$.location') as location ,count(*) as num where ip_to_domain(remote_addr) ='internet'  group by  1  limit 10000",
"line": 100,
"offset": 0

}`
过滤器:

`var temp = [];

for(var key in data){

var item = data[key]
var location = JSON.parse(item.location) 
if(location && location[0] && location[1]){
    temp.push({
      lng : location[0],
      lat : location[1],
      value : item.num
  })

}}
return temp;`

计算资源总消耗-数字翻牌器

适用于通过pop api 获取云监控的信息,统计整体资源使用;
查询参数:

`{

"Period": 300,
"StartTime": ":oneDayAgo",
"EndTime": ":now",
"Metric": "ecs_CPUUtilization ",
"Project": "acs_cms_resource "
}`
接口名称:QueryMetricList
返回结果路劲:Datapoints

过滤器:

`var temp = 0;

var temp_num = 0;
data.forEach(function(item){
temp += item.Value;
temp_num += 1;
})
temp = temp / temp_num;
temp = String(temp).substr(0,7)
return [{"temp":temp}]
//return [{"temp":temp,"temp_num":temp_num}]
`

10.后期更新内容

问题1:解决控制台报错问题:Error: attribute transform: Expected number, "translate(NaN,49.5)"
答:这块问题为回掉ID里源时间轴输出数据类型问题,因为之前时间轴抛出来的是字符串,但是在时间轴的样式-事件节点-种类里是默认的时间类型,本身组件格式化本身的过滤器输出时就报错了;把默认时间类型改成类目型即OK!

问题2:解决PV/UV的折线图 y轴 显示小数问题
答:折线图里面的js会自动对数据做自动分段统计,显示内容由js浮点类型控制就会出现小数,解决这个问题就需要在显示前添加一个format;在折线图的样式-显示格式里把之前的默认值宣称整数即可;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值