侧边栏壁纸
  • 累计撰写 125 篇文章
  • 累计创建 13 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

【ORACLE】在plsql中通过几条简单的命令生成运维可视化图表html页面

DarkAthena
2021-12-02 / 0 评论 / 0 点赞 / 1368 阅读 / 5860 字

前言

其实本来不想写这篇的,因为这对于前端的入门开发者再简单不过了,只是因为最近看到一位DBA老哥为了生成图表各种折腾,又联想起我原来所在公司的DBA经常找我请教一些自动化流程如何用sql或者plsql实现,实在是忍不住了。

业务报表或者运维报表的自动生成,在一些公司应该是基本操作,开发语言用java的、php的、python的,五花八门,甚至还有直接bat或者shell写静态html的。至于优秀的可视化报表图表平台,更是数不胜数了。只要找个开发问问,没准他几分钟内就帮你搞定了,甚至还可以自动发邮件、企业微信、钉钉等。

找不到开发人员?自己也不会其他开发语言?没关系,HTML总会吧?在数据库里用字符串拼出一个html页面不难吧?

直接上代码

--生成测试数据
create table TEST_AREA_CHART2
(
  sample_time VARCHAR2(8),
  metric_name VARCHAR2(23),
  value       NUMBER
);


insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('12:00:00', 'Instance Foreground CPU', 1);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('12:00:00', 'Instance Background CPU', 4);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('12:00:00', 'Non-Database Host CPU', 7);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('12:00:00', 'Load Average', 10);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('11:00:00', 'Instance Foreground CPU', 2);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('11:00:00', 'Instance Background CPU', 5);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('11:00:00', 'Non-Database Host CPU', 8);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('11:00:00', 'Load Average', 11);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('10:00:00', 'Instance Foreground CPU', 3);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('10:00:00', 'Instance Background CPU', 6);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('10:00:00', 'Non-Database Host CPU', 9);

insert into test_area_chart2 (SAMPLE_TIME, METRIC_NAME, VALUE)
values ('10:00:00', 'Load Average', 12);

commit;

--创建一个HTML生成函数
create function test_area_chart_func return clob is 
  l_clob   clob;
  l_legend varchar2(32000);
  l_xAxis  varchar2(32000);
  l_series varchar2(32000);
begin
  l_clob := q'{
<!DOCTYPE html>
<html style="height: 100%">
<head><meta charset="utf-8"></head>
<body style="height: 100%; margin: 0">
<div id="container" style="height: 100%"></div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts@5.2.2/dist/echarts.min.js"></script>
<script type="text/javascript">
var dom = document.getElementById("container");
var myChart = echarts.init(dom);
var app = {};
var option;
option = {title: {text: 'Stacked Area Chart'},
tooltip: {
trigger: 'axis',
axisPointer: {type: 'cross',label: {backgroundColor: '#6a7985'}}},
legend: {data: [##legend##]},
toolbox: {feature: {saveAsImage: {}}},
grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},
xAxis: [{type: 'category',boundaryGap: false,data: [##xAxis##]}],
yAxis: [{type: 'value'}],
series: [##series##]
};
if (option && typeof option === 'object') {
myChart.setOption(option);
}
</script>
</body>
</html>}';
  select listagg(distinct '''' || a.sample_time || '''', ',') within GROUP(order by sample_time) g
    into l_xAxis
    from test_area_chart2 a;
  select listagg(distinct '''' || a.METRIC_NAME || '''', ',')
    into l_legend
    from test_area_chart2 a;

  select listagg(a)
    into l_series
    from (select q'{ {name: '}' || METRIC_NAME ||
                   q'{',type: 'line',stack: 'Total',areaStyle: {},data: [}' ||
                 listagg(value, ',') within GROUP(order by sample_time) || q'{]} ,}' a
            from test_area_chart2
           where metric_name <> 'Load Average'
           group by METRIC_NAME
          union all
          select q'{ {name: '}' || METRIC_NAME ||
                   q'{',type: 'line',stack: 'Total',data: [}' ||
                 listagg(value, ',') within GROUP(order by sample_time) || q'{]} }'
            from test_area_chart2
           where metric_name = 'Load Average'
           group by METRIC_NAME);

  l_clob := replace(l_clob, '##legend##', l_legend);
  l_clob := replace(l_clob, '##xAxis##', l_xAxis);
  l_clob := replace(l_clob, '##series##', l_series);
  return l_clob;
end;
/

--获取函数返回的html页面
select test_area_chart_func from dual;

页面效果

https://www.darkathena.top/test/test_area_chart.html
image.png
实现原理就是调用开源的图表js组件echarts,手动拼个html。

上面这个函数也就随手一写,主要是验证其可行性,没有针对特殊场景做兼容开发。如果功能要更加全面的话,完全可以把各种选项参数化,封装成一个具有完整功能的plsql包。而且在12c以后也不需要使用字符串拼接json了,直接可以用json语法操作,甚至在21c版本还可以用dbms_mle功能调用js直接返回对应的图片。就算不是21c版本,在ORACLE的apex里写写简单的代码也是可以实现的,甚至还能直接做成动态刷新的页面。最后再搞个大屏显得高大上。

最后提个问题

DBA是否应该至少掌握一门除plsql以外的开发语言?

严格来说,我不是DBA,也不是开发岗位,在之前公司主要是做erp软件运维及业务咨询。由于遇到了和Tim Hall老哥类似的原因

You end up spending loads of time doing things that you are crap at, because your “crap” is better than other people’s “good”

我尝试自己开发各种工具来补齐IT部门工作中的短板,当时的确是没有开发人员,只能自己上(吐槽一下,近十万员工的公司连开发都找不到。。。),所以咨询、设计、开发、运维一个人“全栈”了。而实践证明,懂运维的人开发的运维工具,会比不经常运维的开发人员开发出来的工具用起来更顺手。

所以我对这个问题的回答是,DBA们利用空闲时间去多掌握一门对自己工作有帮助的技能,何乐而不为呢?

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin
博主关闭了所有页面的评论