From 6858090650c4b69e4f36f9c8a33778799dbfa063 Mon Sep 17 00:00:00 2001 From: abo Date: Mon, 27 Mar 2017 21:47:35 +0800 Subject: [PATCH] sparkline sample: rate visualization --- .gitignore | 3 ++ README.md | 14 ++++++++ cmd/sparkline/.babelrc | 5 +++ cmd/sparkline/main.go | 57 +++++++++++++++++++++++++++++ cmd/sparkline/main.jsx | 61 ++++++++++++++++++++++++++++++++ cmd/sparkline/package.json | 23 ++++++++++++ cmd/sparkline/sparkline.png | Bin 0 -> 15333 bytes cmd/sparkline/tpl/index.html | 60 +++++++++++++++++++++++++++++++ cmd/sparkline/webpack.config.js | 13 +++++++ 9 files changed, 236 insertions(+) create mode 100644 cmd/sparkline/.babelrc create mode 100644 cmd/sparkline/main.go create mode 100644 cmd/sparkline/main.jsx create mode 100644 cmd/sparkline/package.json create mode 100644 cmd/sparkline/sparkline.png create mode 100644 cmd/sparkline/tpl/index.html create mode 100644 cmd/sparkline/webpack.config.js diff --git a/.gitignore b/.gitignore index 3736f90..cea017e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ _testmain.go .vscode/ *.log + +cmd/sparkline/node_modules/ +cmd/sparkline/assets/ diff --git a/README.md b/README.md index 29faf3e..d0147d0 100644 --- a/README.md +++ b/README.md @@ -66,6 +66,20 @@ Documentation - [Wiki](https://github.com/abo/rerate/wiki) +Sample - Sparkline +------------------ + +![](https://github.com/abo/rerate/raw/master/cmd/sparkline/sparkline.png) + +``` + cd cmd/sparkline + npm install webpack -g + npm install + webpack && go run main.go +``` +Open `http://localhost:8080` in Browser, And then move mouse. + + Contributing ------------ WELCOME diff --git a/cmd/sparkline/.babelrc b/cmd/sparkline/.babelrc new file mode 100644 index 0000000..9d31e80 --- /dev/null +++ b/cmd/sparkline/.babelrc @@ -0,0 +1,5 @@ +{ + "presets":[ + "es2015", "react" + ] +} diff --git a/cmd/sparkline/main.go b/cmd/sparkline/main.go new file mode 100644 index 0000000..526b6f0 --- /dev/null +++ b/cmd/sparkline/main.go @@ -0,0 +1,57 @@ +package main + +import ( + "encoding/json" + "net/http" + "time" + + redis "gopkg.in/redis.v5" + + "github.com/abo/rerate" + "github.com/gorilla/mux" +) + +var counter *rerate.Counter + +func init() { + buckets := rerate.NewRedisV5Buckets(redis.NewClient(&redis.Options{ + Addr: "localhost:6379", + Password: "", + DB: 0, + })) + counter = rerate.NewCounter(buckets, "rerate:sparkline", 20*time.Second, 500*time.Millisecond) +} + +func main() { + r := mux.NewRouter() + r.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("assets")))) + r.HandleFunc("/histogram/{key}", histogram) + r.HandleFunc("/inc/{key}", inc) + r.PathPrefix("/").Handler(http.FileServer(http.Dir("tpl"))) + + srv := &http.Server{ + Handler: r, + Addr: ":8080", + WriteTimeout: 15 * time.Second, + ReadTimeout: 15 * time.Second, + } + + srv.ListenAndServe() +} + +func inc(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + counter.Inc(vars["key"]) +} + +func histogram(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + if hist, err := counter.Histogram(vars["key"]); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } else if resp, err := json.Marshal(hist); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } else { + w.Header().Set("Content-Type", "application/json") + w.Write(resp) + } +} diff --git a/cmd/sparkline/main.jsx b/cmd/sparkline/main.jsx new file mode 100644 index 0000000..b99a7bf --- /dev/null +++ b/cmd/sparkline/main.jsx @@ -0,0 +1,61 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import { Sparklines, SparklinesLine, SparklinesBars } from 'react-sparklines'; + +class Rerate extends React.Component { + constructor(props) { + super(props); + this.state = { histogram:[] }; + } + + componentDidMount() { + this.intervalId = setInterval( () => { + fetch("/histogram/"+this.props.counterId) + .then(response => response.json()) + .then(json => this.setState({histogram:json})); + },this.props.interval); + } + + componentWillUnmount() { + clearInterval(this.intervalId); + } + + render() { + const data = this.state.histogram.reverse(); + return (
{React.Children.map(this.props.children, function(child) { + return React.cloneElement(child, { data }); + })}
); + } +} + + +ReactDOM.render( + + + , document.getElementById("sparkline-0") +); +ReactDOM.render( + + + , document.getElementById("sparkline-1") +); +/*ReactDOM.render( + + + , document.getElementById("sparkline-2") +); +ReactDOM.render( + + + , document.getElementById("sparkline-3") +); +ReactDOM.render( + + + , document.getElementById("sparkline-4") +); +ReactDOM.render( + + + , document.getElementById("sparkline-5") + );*/ \ No newline at end of file diff --git a/cmd/sparkline/package.json b/cmd/sparkline/package.json new file mode 100644 index 0000000..f527554 --- /dev/null +++ b/cmd/sparkline/package.json @@ -0,0 +1,23 @@ +{ + "name": "rerate-sparkline", + "version": "1.0.0", + "description": "", + "main": "webpack.config.js", + "dependencies": { + "react": "^15.4.2", + "react-dom": "^15.4.2", + "react-sparklines": "^1.6.0" + }, + "devDependencies": { + "babel-core": "^6.24.0", + "babel-loader": "^6.4.1", + "babel-preset-es2015": "^6.24.0", + "babel-preset-react": "^6.23.0", + "webpack": "^2.3.2" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "abo", + "license": "ISC" +} diff --git a/cmd/sparkline/sparkline.png b/cmd/sparkline/sparkline.png new file mode 100644 index 0000000000000000000000000000000000000000..f843b25d7a8748ecee99bc21c93208940ac182b9 GIT binary patch literal 15333 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 literal 0 HcmV?d00001 diff --git a/cmd/sparkline/tpl/index.html b/cmd/sparkline/tpl/index.html new file mode 100644 index 0000000..a9360fb --- /dev/null +++ b/cmd/sparkline/tpl/index.html @@ -0,0 +1,60 @@ + + + + + + + rerate's sparkline + + + + + + + + + + + + + +
+

Sparkline for rerate

+ + + + + + + + + + + + + + + + + + + + + +
rerate:sparkline:0rerate:sparkline:1rerate:sparkline:arerate:sparkline:brerate:sparkline:crerate:sparkline:d
+
+ + + + \ No newline at end of file diff --git a/cmd/sparkline/webpack.config.js b/cmd/sparkline/webpack.config.js new file mode 100644 index 0000000..0ba8184 --- /dev/null +++ b/cmd/sparkline/webpack.config.js @@ -0,0 +1,13 @@ +const path = require('path'); +module.exports = { + entry: './main.jsx', + output: { + path: path.resolve('assets'), + filename: 'sparkline.js' + }, + module: { + loaders: [ + {test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/} + ] + } +} \ No newline at end of file