涛子 - 简单就是美

成单纯魁增,永继振国兴,克复宗清政,广开家必升

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  428 随笔 :: 0 文章 :: 19 评论 :: 22万 阅读

document

http://iwantmyreal.name/blog/2012/09/16/visualising-conair-data-with-cubism-dot-js
https://hveem.no/vm-monitoring-using-salt-and-cubism
http://sciviz.info/time-series-visualization-using-cubism-js
http://square.github.io/cubism/

api

https://github.com/square/cubism/wiki

example

<script>
function random(name) {
  var value = 0,
      values = [],
      i = 0,
      last;
  /* 支持cube, graphite内建方法, 也可以使用context.metric()方法构造新的数据源。
     context.metric()有一个request函数参数, 还有一个可选的name参数。start & stop是日期类型,step单位ms。
     callback有2个参数,第1参数用于node.js,第2参数是数值形数组 */
  return context.metric(function(start, stop, step, callback) {
    start = +start, stop = +stop;
    if (isNaN(last)) last = start;
    while (last < stop) {
      last += step;
      value = Math.max(-10, Math.min(10, value + .8 * Math.random() - .4 + .2 * Math.cos(i += .2)));
      values.push(value);
    }
    callback(null, values = values.slice((start - stop) / step));
  }, name);
}

var context = cubism.context()
    .serverDelay(0) // 服务器延时
    .clientDelay(0) // 客户端延时
    .step(1e3)  // 步进1e3(1000ms), cubism的时间单位是ms
    .size(960); // 960 * 1s, 时间轴是16分钟

var foo = random("foo"),
    bar = random("bar");

// example1
d3.select("#example1").call(function(div) {
  div.append("div")
      .attr("class", "axis")
      .call(context.axis().orient("top"));

  div.selectAll(".horizon")
      .data([foo, bar, foo.add(bar), foo.subtract(bar)])
    .enter().append("div")
      .attr("class", "horizon")
      .call(context.horizon().extent([-20, 20]));

  div.append("div")
      .attr("class", "rule")
      .call(context.rule());

});

// example2a
d3.select("#example2a").call(function(div) {
  div.datum(foo);

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(120)
        .mode("mirror")
        .colors(["#bdd7e7","#bae4b3"])
        .title("Area (120px)")
        .extent([-10, 10]));

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(30)
        .mode("mirror")
        .colors(["#bdd7e7","#bae4b3"])
        .title("Area (30px)")
        .extent([-10, 10]));
});

// example2b
d3.select("#example2b").call(function(div) {
  div.datum(foo);

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(120)
        .colors(["#bdd7e7","#bae4b3"])
        .title("Horizon, 1-band (120px)")
        .extent([-10, 10]));

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(60)
        .colors(["#6baed6","#bdd7e7","#bae4b3","#74c476"])
        .title("Horizon, 2-band (60px)")
        .extent([-10, 10]));

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(40)
        .colors(["#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354"])
        .title("Horizon, 3-band (40px)")
        .extent([-10, 10]));

  div.append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(30)
        .colors(["#08519c","#3182bd","#6baed6","#bdd7e7","#bae4b3","#74c476","#31a354","#006d2c"])
        .title("Horizon, 4-band (30px)")
        .extent([-10, 10]));

});

// On mousemove, reposition the chart values to match the rule.
context.on("focus", function(i) {
  d3.selectAll(".value").style("right", i == null ? null : context.size() - i + "px");
});

我的程序

<html>
  <head>
    <title>dashboard</title>
    <script src="{{ url_for('static', filename='js/d3.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/cubism.v1.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/jquery-1.11.3.min.js') }}"></script>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/style.css') }}">  
  </head>
  <body>
      <div id="cubism"></div>
  </body>

<script type="text/javascript">
function analysis(name, cname, bandwidth, interface, threshold, measure) {
  var label = ((measure.split('_')[1] == 'rx') ? 'In' : 'Out') + ' ' +cname;
  var result = context.metric(function(start, stop, step, callback) {
    $.ajax({
      type: 'GET',
      url: '/api',
      data: {
        'name': name, 
        'interface': interface,
        'measure': measure, 
        'start': start.toISOString(),
        'stop': stop.toISOString()
      },
      dataType: 'json',
      success: function(data) {
        callback(null, data);
        //console.log(data);
      },
    });
    }, label);

  return result;
}

var seconds = 60;
var default_colors = ['#08519c', '#3182bd', '#6baed6', '#bdd7e7', '#bae4b3', '#74c476', '#31a354', '#006d2c'];
var custom_colors = ['#ffcc99', '#ff9999', '#ffcc00', '#ff6666'];

//default_colors = custom_colors;

var context = cubism.context()
    .serverDelay(seconds*1000)
    .step(seconds*1000)
    .size(60*16);

var dataset = [];

{% for switch in switches %}
  var info = ['{{ switch.name }}', '{{ switch.cname }}', '{{ switch.bandwidth }}', '{{ switch.interface }}', '{{ switch.threshold }}'];
  var traffic_in = analysis(info[0], info[1], info[2], info[3], info[4], 'snmp_rx'),
      traffic_out = analysis(info[0], info[1], info[2], info[3], info[4], 'snmp_tx');
  dataset.push(traffic_in, traffic_out);
{% endfor %}

d3.select("#cubism").call(function(div) {
    div.append("div")
      .attr("class", "axis")
      .call(context.axis()
        .tickFormat(d3.time.format("%H:%M"))
        .ticks(d3.time.minutes, 60)
        .orient("top"));

    div.selectAll(".horizon")
      .data(dataset)
      .enter().append("div")
      .attr("class", "horizon")
      .call(context.horizon()
        .height(30)
        .colors(default_colors)
        .format(d3.format('.2f')));

  div.append("div")
    .attr("class", "rule")
    .call(context.rule());
});

context.on("focus", function(i) {
  d3.selectAll(".value").style("right", i == null ? null : context.size() - i + "px");
});
</script>
</html>
#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import json
import yaml
from flask import Flask, render_template, request, url_for
from influxdb import InfluxDBClient

app = Flask(__name__)
client = InfluxDBClient(host='10.10.32.109', port=8086, username='root', password='root', database='collectd')

@app.route('/', methods=['GET'])
def index():
    file = 'switch.yaml'
    with open(file) as f:
        switches = yaml.load(f)
    return render_template('dashboard.html', switches=switches)

@app.route('/cubism', methods=['GET'])
def cubism():
    return render_template('cubism.html')

@app.route('/api', methods=['GET'])
def api():
    host, interface, measure, start, stop = \
        request.args['name'], request.args['interface'], request.args['measure'], \
        request.args['start'], request.args['stop'] 
    file = 'dashboard.yaml'

    query = 'select derivative(value)*8/1000/1000 from '+ measure \
        + ' where host=\'' + host + '\' and type_instance=\'' + interface \
        + '\' and time > \'' + start \
        + '\' and time < \'' + stop +'\''
    
    print query
    result = client.query(query)
    return json.dumps([value[1] for value in result.raw['series'][0]['values'] ])

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

# influxdb的sql可能有bug,按时间段取值,结果会丢失第1个值
# curl http://127.0.0.1:5000/api?name=bjtn&measure=traffic_out&start=2015-07-28T08:10:00Z&stop=2015-07-28T08:50:59Z
posted on   北京涛子  阅读(1010)  评论(1编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· AI与.NET技术实操系列(六):基于图像分类模型对图像进行分类
点击右上角即可分享
微信分享提示