├── .dockerignore
├── .editorconfig
├── .gitignore
├── .travis.yml
├── Cargo.toml
├── Dockerfile
├── LICENSE
├── README.md
├── debug.sh
├── docker
├── Dockerfile.final
├── build.sh
└── push.sh
├── kernel_tuning.txt
├── src
├── bin
│ ├── carbon.rs
│ ├── graphite.rs
│ └── whisper.rs
├── carbon
│ ├── cache_writer.rs
│ ├── config.rs
│ ├── handlers
│ │ ├── mod.rs
│ │ ├── tcp.rs
│ │ └── udp.rs
│ └── mod.rs
├── graphite
│ ├── cache_holder.rs
│ ├── config.rs
│ ├── error.rs
│ ├── expander.rs
│ ├── handlers
│ │ ├── metrics_find.rs
│ │ ├── mod.rs
│ │ └── render.rs
│ ├── middleware
│ │ ├── mod.rs
│ │ └── path_fixer.rs
│ ├── mod.rs
│ └── server.rs
└── lib.rs
└── test
└── scripts
└── tcp_multipoint.sh
/.dockerignore:
--------------------------------------------------------------------------------
1 | target
2 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | end_of_line = lf
9 | insert_final_newline = true
10 |
11 | [*.rs]
12 | indent_style = space
13 | indent_size = 4
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | Cargo.lock
3 | test
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: rust
2 | rust: nightly
3 | sudo: false
4 | env:
5 | global:
6 | secure: II3sCfqoqziRQtsuEmS7C/nUS7BMMktJAbXSMEoO2jz7JUA3MoYk2vBqWTP0MQj6Sasbitp6a1mH1YCoF8AG5aQIzlUiD1AWgoP0wWcqEvIywZHoqoD0yejOrt4l/LZueTFbu7ugOtSnXIf7qoGzwsN/sLXTUSS94QahXW7UWew=
7 | after_success: |
8 | cargo doc \
9 | && echo '' > target/doc/index.html && \
10 | sudo pip install ghp-import && \
11 | ghp-import -n target/doc && \
12 | git push -qf https://${GH_TOKEN}@github.com/tureus/graphite-rust.git gh-pages
13 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "graphite"
3 | version = "0.2.3"
4 | authors = ["Xavier Lange "]
5 | description = "A fast, pure rust graphite implementation. Includes whisper, carbon, and graphite."
6 | license = "MIT"
7 | homepage = "https://www.github.com/tureus/graphite-rust"
8 | repository = "https://github.com/tureus/graphite-rust.git"
9 |
10 | [lib]
11 | name="graphite"
12 | path="src/lib.rs"
13 |
14 | # [[bin]]
15 | # name="whisper"
16 |
17 | [[bin]]
18 | name="carbon"
19 |
20 | ## [[bin]]
21 | ## name="graphite"
22 | ## [[graphite.dependencies]] # not valid code!
23 | ## iron = "*"
24 | ## # router = "*"
25 | ## urlencoded = "*"
26 | ## glob = "*"
27 | ## # iron-test = "*"
28 | ## persistent = "*" # Not a great name for a HTTP middle lib... there's already a Haskell lib for doing real data persistence with the same name.
29 | ## router = "*"
30 |
31 | ## Out of date deps?
32 | # num = "*"
33 |
34 | [dependencies]
35 | byteorder = "*"
36 | gcc = "*"
37 | time = "*"
38 | log = "*"
39 | env_logger = "*"
40 | docopt = "0.6.64"
41 | regex = "*"
42 | libc = "*"
43 | rustc-serialize = "*"
44 | whisper = "*"
45 |
46 | # [dependencies.router]
47 | # git = "https://github.com/iron/router.git"
48 |
49 | # The documentation profile, used for `cargo doc`
50 | [profile.doc]
51 | opt-level = 0
52 | debug = true
53 | rpath = false
54 | lto = false
55 | debug-assertions = true
56 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM andrewd/rust-musl
2 |
3 | RUN curl -sSL https://get.docker.io/builds/Linux/x86_64/docker-1.2.0 -o /tmp/docker && \
4 | echo "540459bc5d9f1cac17fe8654891814314db15e77 /tmp/docker" | sha1sum -c - && \
5 | mv /tmp/docker /usr/local/bin/docker && \
6 | chmod +x /usr/local/bin/docker
7 |
8 | ADD . /graphite-rust
9 | WORKDIR /graphite-rust
10 | RUN cargo build --release --target x86_64-unknown-linux-musl
11 |
12 | WORKDIR /graphite-rust/target/x86_64-unknown-linux-musl/release
13 |
14 | ADD docker/Dockerfile.final /graphite-rust/target/x86_64-unknown-linux-musl/release/Dockerfile
15 |
16 | CMD docker build -t xrlx/graphite .
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Xavier Lange, Vincent Grato
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | The graphite ecosystem in one easy-to-install package.
2 |
3 | [](https://travis-ci.org/tureus/graphite-rust)
4 |
5 | [](https://imagelayers.io/?images=xrlx/graphite:latest 'Get your own badge on imagelayers.io')
6 |
7 | ## Docker
8 |
9 | By far the easiest experience for getting up and running
10 |
11 | docker pull xrlx/graphite
12 | mkdir data
13 | docker run -v ./data:/data xrlx/graphite
14 |
15 | ## Docker in Production
16 |
17 | How I run `graphite-rust` with `graphite-web` in production:
18 |
19 | $ cat run_graphite.sh
20 | docker run -e "RUST_LOG=warning" --name graphite -d -p 2003:2003/udp -p 2003:2003 -v /var/data/graphite:/data xrlx/graphite
21 | $ cat run_graphite_web.sh
22 | docker run -d -it --name graphite-web -v /var/data/graphite:/opt/graphite/storage/whisper -p 80:80 banno/graphite-web
23 | $ sudo sysctl -w vm.dirty_background_ratio=30 vm.dirty_ratio=60 vm.dirty_expire_centisecs=1080000 vm.dirty_writeback_centisecs=1080000
24 |
25 | ## Building
26 |
27 | Note: you'll need a nightly rust build to build this
28 |
29 | $ git clone git@github.com:tureus/graphite-rust.git
30 | $ cd graphite-rust
31 | $ cargo build --release
32 | $ RUST_LOG=debug ./target/debug/carbon
33 |
34 | ## Tasks
35 |
36 | - [X] Read headers
37 | - [X] Read single point
38 | - [X] Write to single archive
39 | - [X] Write through all archives with downsampling
40 | - [X] Create files
41 | - [X] Read many points
42 | - [ ] Advisory lock files
43 | - [x] `mmap` files (PROFILING)
44 | - [ ] Use `cfg()` guards to provide conditional checks for sysctl settings
45 | - [X] UDP daemon
46 | - [X] TCP daemon
47 | - [ ] Custom schema support when creating new WSPs
48 | - [ ] Pickle daemon
49 | - [ ] HTTP frontend
50 | - [ ] Make logging useful for ops
51 | - [ ] Validate .wsp when opening (archives need to cleanly multiply, etc)
52 |
53 | ## Documentation
54 |
55 | [http://tureus.github.io/graphite-rust](http://tureus.github.io/graphite-rust)
56 |
57 | ## Reference
58 |
59 | Documentation for the whisper file format is slim/nil. Clone the official repo and take a look at `whisper.py`
60 |
61 | $ git clone git@github.com:graphite-project/whisper.git
62 |
63 | ## Talking to Carbon
64 |
65 | On OSX you need to specify IPv4:
66 |
67 | echo -e "local.random.diceroll 4 `date +%s`" | nc -4u -w0 localhost 2003
68 |
69 | On linux:
70 |
71 | echo "local.random.diceroll 4 `date +%s`" | nc -u -w 1 localhost 2003
72 |
73 | Memory stats:
74 |
75 | yum install -y sysstat
76 | toolbox sar -B 1
77 |
--------------------------------------------------------------------------------
/debug.sh:
--------------------------------------------------------------------------------
1 | set -e
2 | set -o pipefail
3 |
4 | export TS=`date +%s`
5 | echo TS is $TS
6 |
7 | # pushd ../whisper && python ../whisper/setup.py install > /dev/null && popd
8 |
9 | # export FNAME="1-5-5-5-10-5"
10 | # export ARCHIVE="1:5 5:5 10:5"
11 |
12 | # export FNAME="1s-6h-1h-1d-24h-20y"
13 | # export ARCHIVE="1s:6h 1h:1d 24h:20y"
14 |
15 | export FNAME="1s-24h-1h-30d-24h-30y"
16 | export ARCHIVE="1s:24h 1h:30d 24h:30y"
17 |
18 | rm test/fixtures/$FNAME.wsp.{python,rust}
19 | whisper-create.py test/fixtures/$FNAME.wsp.python $ARCHIVE
20 | whisper-create.py test/fixtures/$FNAME.wsp.rust $ARCHIVE
21 |
22 | echo "PYTHON TIME"
23 | time {
24 | for i in `seq 1 100000`;
25 | do
26 | whisper-update.py test/fixtures/$FNAME.wsp.python $TS:10
27 | done
28 | }
29 |
30 | echo "RUST TIME"
31 | time {
32 | for i in `seq 1 100000`;
33 | do
34 | RUST_LOG=warning target/release/whisper update test/fixtures/$FNAME.wsp.rust $TS 10
35 | done
36 | }
37 |
38 | diff test/fixtures/$FNAME.wsp.*
39 |
40 | if [[ $? -eq 0 ]]; then
41 | echo "whisper files match"
42 | fi
43 |
--------------------------------------------------------------------------------
/docker/Dockerfile.final:
--------------------------------------------------------------------------------
1 | FROM busybox
2 |
3 | ADD carbon /usr/bin/carbon
4 |
5 | ENV RUST_LOG debug
6 |
7 | VOLUME /data
8 | EXPOSE 2003
9 | EXPOSE 2003/udp
10 |
11 | ENTRYPOINT ["/usr/bin/carbon", "--storage-path", "/data"]
12 |
--------------------------------------------------------------------------------
/docker/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -xe
3 |
4 | docker build -t xrlx/graphite_build .
5 | # run the build env CMD for copying deb and installing to minimal image
6 | docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -ti xrlx/graphite_build
7 |
--------------------------------------------------------------------------------
/docker/push.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -xe
3 |
4 | docker push xrlx/graphite
5 |
--------------------------------------------------------------------------------
/kernel_tuning.txt:
--------------------------------------------------------------------------------
1 | # https://www.kernel.org/doc/Documentation/sysctl/vm.txt
2 | # http://jmoiron.net/
3 |
4 | # DEFAULTS
5 | vm.dirty_background_bytes = 0
6 | vm.dirty_background_ratio = 10
7 | vm.dirty_expire_centisecs = 3000
8 | vm.dirty_bytes = 0
9 | vm.dirty_ratio = 20
10 | vm.dirty_writeback_centisecs = 500
11 | vm.dirtytime_expire_seconds = 43200
12 |
13 | # FIRST TRY
14 | sysctl -w vm.dirty_background_ratio=30 vm.dirty_ratio=60 vm.dirty_expire_centisecs=18000 vm.dirty_writeback_centisecs=3000
15 |
16 | # SECOND TRY (smoothing out sync by disabling writeback thread (3000 -> 0))
17 | sysctl -w vm.dirty_background_ratio=30 vm.dirty_ratio=60 vm.dirty_expire_centisecs=18000 vm.dirty_writeback_centisecs=0
18 |
19 | # THIRD TRY (fixed a default schema bug which had artificially small number of dirty pages, kernel died in mysterious way and had iops storm. time to reel it back and run the dirty_writeback every once in a while)
20 | # Wake up every 3 hours to flush data
21 | sysctl -w vm.dirty_background_ratio=30 vm.dirty_ratio=60 vm.dirty_expire_centisecs=1080000 vm.dirty_writeback_centisecs=1080000
22 |
23 | sysctl -w vm.dirty_background_ratio=30 vm.dirty_ratio=60 vm.dirty_expire_centisecs=1080000 vm.dirty_writeback_centisecs=1080000
24 |
--------------------------------------------------------------------------------
/src/bin/carbon.rs:
--------------------------------------------------------------------------------
1 | #![feature(unmarked_api)]
2 |
3 | extern crate graphite;
4 | extern crate whisper;
5 |
6 | #[macro_use]
7 | extern crate log;
8 | extern crate env_logger;
9 | extern crate rustc_serialize;
10 | extern crate docopt;
11 | extern crate time;
12 |
13 | use graphite::carbon;
14 | use whisper::{ WhisperCache, Schema };
15 |
16 | use std::path::Path;
17 |
18 | use docopt::Docopt;
19 | static USAGE: &'static str = "
20 | Carbon is the network service for writing data to disk
21 |
22 | Usage:
23 | carbon [--port PORT] [--bind HOST] [--chan DEPTH] [--storage-path STORAGEPATH] [--cache-size CACHESIZE]
24 | carbon --help
25 |
26 | Options:
27 | -h --help show this screen
28 | --bind HOST host to bind to [default: 0.0.0.0:2003]
29 | --chan DEPTH how many carbon messages can be in-flight [default: 1000]
30 | --storage-path STORAGEPATH where to find the whisper file [default: /tmp]
31 | --cache-size CACHESIZE max number of open files to keep in memory [default: 60000]
32 | ";
33 |
34 | #[derive(RustcDecodable, Debug)]
35 | struct Args {
36 | flag_bind: String,
37 | flag_chan: usize,
38 | flag_storage_path: String,
39 | flag_cache_size: usize
40 | }
41 |
42 | pub fn main(){
43 | env_logger::init().unwrap();
44 | let args: Args = Docopt::new(USAGE)
45 | .and_then(|d| d.decode())
46 | .unwrap_or_else(|e| e.exit());
47 |
48 | let bind_spec = unsafe {
49 | args.flag_bind.slice_unchecked(0, args.flag_bind.len())
50 | };
51 |
52 | let config = carbon::Config{
53 | bind_spec: bind_spec,
54 | chan_depth: args.flag_chan,
55 | base_path: Path::new(&args.flag_storage_path),
56 | cache_size: args.flag_cache_size
57 | };
58 |
59 | info!("preparing whisper cache...");
60 | let default_specs = vec!["5s:1y".to_string()];
61 | let schema = Schema::new_from_retention_specs(default_specs);
62 | let cache = WhisperCache::new(&config.base_path.to_owned(), config.cache_size, schema);
63 |
64 | let (tx,_) = carbon::cache_writer::spawn(cache, &config);
65 |
66 | let udp_server = carbon::udp::run_server(tx.clone(), &config).unwrap();
67 | let tcp_server = carbon::tcp::run_server(tx, &config).unwrap();
68 |
69 | udp_server.join().unwrap();
70 | tcp_server.join().unwrap();
71 | }
72 |
--------------------------------------------------------------------------------
/src/bin/graphite.rs:
--------------------------------------------------------------------------------
1 | extern crate graphite;
2 |
3 | #[macro_use]
4 | extern crate log;
5 | extern crate env_logger;
6 | extern crate rustc_serialize;
7 | extern crate docopt;
8 | extern crate time;
9 |
10 | use std::path::Path;
11 |
12 | use docopt::Docopt;
13 | static USAGE: &'static str = "
14 | Graphite is the HTTP REST API for querying data from the database
15 |
16 | Usage:
17 | graphite server
18 | graphite expand [--storage-path STORAGEPATH]
19 | Options:
20 |
21 | --bind HOST host to bind to [default: 0.0.0.0:8080]
22 | --storage-path STORAGEPATH where to find the whisper file [default: /tmp]
23 | ";
24 |
25 | use self::graphite::graphite::{ Config, server, expander };
26 | use self::graphite::whisper::Cache;
27 |
28 | #[derive(RustcDecodable, Debug)]
29 | struct Args {
30 | cmd_server: bool,
31 | cmd_expand: bool,
32 |
33 | arg_pattern: String,
34 |
35 | flag_bind: String,
36 | flag_storage_path: String
37 | }
38 |
39 | pub fn main(){
40 | env_logger::init().unwrap();
41 | let args: Args = Docopt::new(USAGE)
42 | .and_then(|d| d.decode())
43 | .unwrap_or_else(|e| e.exit());
44 |
45 | let bind_spec : &str = unsafe {
46 | args.flag_bind.slice_unchecked(0, args.flag_bind.len())
47 | };
48 |
49 | let config = Config{
50 | bind_spec: bind_spec,
51 | base_path: Path::new(&args.flag_storage_path)
52 | };
53 |
54 | if args.cmd_server {
55 | let cache = Cache::new(config.base_path);
56 | server::run(config, cache);
57 | } else if args.cmd_expand {
58 | let cache = Cache::new(config.base_path);
59 | expander::expand(&args.arg_pattern, &cache);
60 | } else {
61 | println!("command not specified");
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/bin/whisper.rs:
--------------------------------------------------------------------------------
1 | extern crate graphite;
2 |
3 | #[macro_use]
4 | extern crate log;
5 | extern crate env_logger;
6 | extern crate rustc_serialize;
7 | extern crate docopt;
8 | extern crate time;
9 |
10 | use docopt::Docopt;
11 | use graphite::whisper::{ WhisperFile, RefCellWhisperFile, Point };
12 | use graphite::whisper::schema::Schema;
13 |
14 | use std::path::Path;
15 |
16 | static USAGE: &'static str = "
17 | Whisper is the fast file manipulator
18 |
19 | Usage:
20 | whisper info
21 | whisper dump
22 | whisper update
23 | whisper mark
24 | whisper thrash
25 | whisper create ...
26 |
27 | Options:
28 | --xff
29 | --aggregation_method
30 | ";
31 |
32 | #[derive(RustcDecodable, Debug)]
33 | struct Args {
34 | cmd_info: bool,
35 | cmd_dump: bool,
36 | cmd_update: bool,
37 | cmd_mark: bool,
38 | cmd_thrash: bool,
39 | cmd_create: bool,
40 |
41 | arg_file: String,
42 | arg_timestamp: String,
43 | arg_value: String,
44 | arg_times: String,
45 |
46 | arg_timespec: Vec
47 | }
48 |
49 |
50 | pub fn main(){
51 | env_logger::init().unwrap();
52 | let args: Args = Docopt::new(USAGE)
53 | .and_then(|d| d.decode())
54 | .unwrap_or_else(|e| e.exit());
55 |
56 | let arg_file = args.arg_file.clone();
57 | let path_str : &str = unsafe {
58 | arg_file.slice_unchecked(0, args.arg_file.len())
59 | };
60 | let path = Path::new(path_str);
61 |
62 |
63 | let current_time = time::get_time().sec as u64;
64 |
65 | if args.cmd_info {
66 | cmd_info(path);
67 | } else if args.cmd_dump {
68 | cmd_dump(path);
69 | } else if args.cmd_update {
70 | cmd_update(args, path, current_time);
71 | } else if args.cmd_mark {
72 | cmd_mark(args, path, current_time);
73 | } else if args.cmd_thrash {
74 | cmd_thrash(args, path, current_time);
75 | } else if args.cmd_create {
76 | cmd_create(args, path);
77 | } else {
78 | println!("Must specify command.");
79 | }
80 | }
81 |
82 | fn cmd_info(path: &Path) {
83 | let file_open = RefCellWhisperFile::open(path);
84 | match file_open {
85 | Ok(whisper_file) => println!("{}", whisper_file),
86 | Err(why) => {
87 | println!("could create whisper file: {:?}", why)
88 | }
89 | }
90 | }
91 |
92 | fn cmd_dump(path: &Path) {
93 | let file_open = RefCellWhisperFile::open(path);
94 | match file_open {
95 | Ok(whisper_file) => println!("{:?}", whisper_file),
96 | Err(why) => {
97 | println!("could create whisper file: {:?}", why)
98 | }
99 | }
100 | }
101 |
102 | fn cmd_update(args: Args, path: &Path, current_time: u64) {
103 | let mut file = RefCellWhisperFile::open(path).unwrap();
104 | let point = Point{
105 | timestamp: args.arg_timestamp.parse::().unwrap(),
106 | value: args.arg_value.parse::().unwrap()
107 | };
108 | debug!("Updating TS: {} with value: {}", point.timestamp, point.value);
109 |
110 | file.write(current_time, point);
111 | }
112 |
113 | fn cmd_mark(args: Args, path: &Path, current_time: u64) {
114 | let mut file = RefCellWhisperFile::open(path).unwrap();
115 | let point = Point{
116 | timestamp: current_time,
117 | value: args.arg_value.parse::().unwrap()
118 | };
119 |
120 | file.write(current_time, point);
121 | }
122 |
123 | fn cmd_thrash(args: Args, path: &Path, current_time: u64) {
124 | let times = args.arg_times.parse::().unwrap();
125 | let mut file = RefCellWhisperFile::open(path).unwrap();
126 | for index in 1..times {
127 | let point = Point{
128 | timestamp: current_time+index,
129 | value: args.arg_value.parse::().unwrap()
130 | };
131 |
132 | file.write(current_time+index, point);
133 | }
134 | }
135 |
136 | fn cmd_create(args: Args, path: &Path) {
137 | let schema = Schema::new_from_retention_specs(args.arg_timespec);
138 | let new_result = RefCellWhisperFile::new(path, schema);
139 | match new_result {
140 | Ok(whisper_file) => println!("Success! {}", whisper_file),
141 | Err(why) => println!("Failed: {:?}", why)
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/src/carbon/cache_writer.rs:
--------------------------------------------------------------------------------
1 | use whisper::{ WhisperCache };
2 |
3 | use std::thread::{ self, JoinHandle };
4 | // extern crate time;
5 | use std::sync::mpsc::{ sync_channel, SyncSender };
6 |
7 | use super::Config;
8 | use super::handlers::Action;
9 |
10 | pub fn spawn(cache: WhisperCache, config: &Config) -> (SyncSender, JoinHandle<()>) {
11 | let (tx, rx) = sync_channel(config.chan_depth);
12 |
13 | info!("spawning file writer...");
14 | let mut cache = cache; // gotta alias the value as mut!
15 |
16 | let writer = thread::spawn(move || {
17 | loop {
18 | let recv = rx.recv();
19 | // let current_time = time::get_time().sec as u64;
20 |
21 | match recv {
22 | Ok(Action::Write(named_point)) => {
23 | let write_res = cache.write( named_point );
24 |
25 | match write_res {
26 | Ok(()) => (),
27 | Err(reason) => debug!("err: {:?}", reason)
28 | }
29 | },
30 | Err(_) => {
31 | debug!("shutting down writer thread");
32 | return ()
33 | }
34 | }
35 | }
36 | });
37 |
38 | (tx,writer)
39 | }
40 |
--------------------------------------------------------------------------------
/src/carbon/config.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 |
3 | pub struct Config<'a> {
4 | pub bind_spec: &'a str,
5 | pub chan_depth: usize,
6 | pub base_path: &'a Path,
7 | pub cache_size: usize
8 | }
9 |
--------------------------------------------------------------------------------
/src/carbon/handlers/mod.rs:
--------------------------------------------------------------------------------
1 | use whisper::NamedPoint;
2 |
3 | pub mod udp;
4 | pub mod tcp;
5 |
6 | // Room to add functionality such as
7 | // - USR1 signal print state of cache to STDOUT
8 | // - USR2 signal flush state of cache to DISK
9 | pub enum Action {
10 | Write(NamedPoint)
11 | }
12 |
--------------------------------------------------------------------------------
/src/carbon/handlers/tcp.rs:
--------------------------------------------------------------------------------
1 | use whisper::{ NamedPoint };
2 |
3 | use std::net::{ TcpListener, TcpStream };
4 | use std::io::{ Error, BufReader, BufRead };
5 | extern crate time;
6 |
7 | use std::sync::mpsc::{ sync_channel, SyncSender };
8 | use std::thread::{ self, JoinHandle };
9 |
10 | use super::super::Config;
11 | use super::Action;
12 |
13 | pub fn run_server(tx: SyncSender, config: &Config) -> Result>,Error> {
14 | info!("TCP server binding to `{}`", config.bind_spec);
15 | let listener = try!( TcpListener::bind(config.bind_spec) );
16 |
17 | let listener_tx = tx.clone();
18 | let accept_thread = thread::spawn(move ||{
19 | let listener_tx = listener_tx;
20 |
21 | debug!("waiting for incoming streams");
22 | for listen_result in listener.incoming() {
23 | let tcp_stream = try!(listen_result);
24 | let thread_tx = listener_tx.clone();
25 | debug!("handling new stream");
26 | thread::spawn(move || {
27 | do_server(thread_tx, tcp_stream);
28 | });
29 | };
30 |
31 | drop(listener);
32 |
33 | Ok(())
34 | });
35 |
36 | debug!("cool, done booting TCP server");
37 |
38 | Ok(accept_thread)
39 | }
40 |
41 | fn do_server(tx: SyncSender, tcp_stream: TcpStream) {
42 | let mut line_buf = String::new();
43 | let mut reader = BufReader::new(tcp_stream);
44 |
45 | loop {
46 | match reader.read_line(&mut line_buf) {
47 | Ok(bytes_read) => {
48 | if bytes_read == 0 {
49 | debug!("connection was closed");
50 | break;
51 | }
52 |
53 | debug!("tcp listener read {} bytes", bytes_read);
54 | let parsed_line = NamedPoint::parse_line(&(line_buf.trim_right())[..]);
55 | match parsed_line {
56 | Ok(np) => tx.send(Action::Write(np)).unwrap(),
57 | Err(err) => {
58 | error!("could not parse incoming data: {:?}", err);
59 | break;
60 | }
61 | }
62 |
63 | line_buf.clear();
64 | },
65 | Err(err) => {
66 | info!("shutting down tcp listener: {:?}", err);
67 | break
68 | }
69 | };
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/carbon/handlers/udp.rs:
--------------------------------------------------------------------------------
1 | use whisper::{ NamedPoint };
2 |
3 | use std::thread::{ self, JoinHandle };
4 | use std::net::UdpSocket;
5 | use std::io::Error;
6 | use std::sync::mpsc::{ SyncSender };
7 |
8 | use super::super::Config;
9 | use super::Action;
10 |
11 | pub fn run_server<'a>(tx: SyncSender, config: &Config) -> Result,Error> {
12 | info!("UDP server binding to `{}`", config.bind_spec);
13 | let mut buf_box = create_buffer();
14 | let socket = try!( UdpSocket::bind(config.bind_spec) );
15 |
16 | let join_handle = thread::spawn(move ||{
17 | loop {
18 | let (bytes_read,_) = {
19 | // debug!("waiting on recv from socket");
20 |
21 | match socket.recv_from( &mut buf_box[..] ) {
22 | Ok(res) => {
23 | res
24 | },
25 | Err(err) => {
26 | error!("error reading from socket: {:?}", err);
27 | continue;
28 | }
29 | }
30 | };
31 |
32 | debug!("parsing point...");
33 |
34 | match NamedPoint::from_datagram(&buf_box[0..bytes_read]) {
35 | Ok(named_points) => {
36 | // Dies if the receiver is closed
37 | debug!("putting message on tx");
38 | for named_point in named_points {
39 | tx.send(Action::Write(named_point)).unwrap();
40 | }
41 | },
42 | Err(err) => {
43 | debug!("wtf mate: {:?}", err);
44 | }
45 | };
46 | }
47 | });
48 | Ok(join_handle)
49 | }
50 |
51 | fn create_buffer() -> Box<[u8]> {
52 | let buf : [u8; 8*1024] = [0; 8*1024];
53 | Box::new( buf )
54 | }
55 |
--------------------------------------------------------------------------------
/src/carbon/mod.rs:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | All the necessary code for listening on network interfaces
4 | for
5 |
6 | */
7 |
8 | mod handlers;
9 | pub mod cache_writer;
10 | mod config;
11 |
12 | pub use self::handlers::{ tcp, udp };
13 | pub use self::config::Config;
14 |
--------------------------------------------------------------------------------
/src/graphite/cache_holder.rs:
--------------------------------------------------------------------------------
1 | use iron;
2 | use super::super::whisper::Cache;
3 |
4 | // This is some weird voodoo so I can use persistent
5 | // apparently I have to give a vtable which is used to resolve the
6 | // type of the stored value so it can be recast "safely"
7 | // but it adds one more level of indirection. Caveat emptor folks.
8 | pub struct CacheHolder;
9 | impl iron::typemap::Key for CacheHolder {
10 | // TODO: my brain hurts. what does this mean?
11 | type Value = Cache;
12 | }
--------------------------------------------------------------------------------
/src/graphite/config.rs:
--------------------------------------------------------------------------------
1 | // Just a re-export of the carbon config
2 |
3 | use std::path::Path;
4 |
5 | pub struct Config<'a> {
6 | pub bind_spec: &'a str,
7 | pub base_path: &'a Path
8 | }
9 |
--------------------------------------------------------------------------------
/src/graphite/error.rs:
--------------------------------------------------------------------------------
1 | use std::error::Error;
2 | use std::fmt::{self, Debug};
3 |
4 | #[derive(Debug)]
5 | pub struct StringError(pub String);
6 |
7 | impl fmt::Display for StringError {
8 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9 | Debug::fmt(self, f)
10 | }
11 | }
12 |
13 | impl Error for StringError {
14 | fn description(&self) -> &str { &*self.0 }
15 | }
16 |
--------------------------------------------------------------------------------
/src/graphite/expander.rs:
--------------------------------------------------------------------------------
1 | use glob::glob;
2 | use super::super::whisper::cache::Cache;
3 | use std::path::{ Path, PathBuf };
4 | use std::fs::{ PathExt, read_dir };
5 | // use std::collections::BTreeMap;
6 | // use rustc_serialize::json::{self, ToJson, Json};
7 |
8 | #[derive(Debug)]
9 | pub enum QueryResultNode {
10 | WspNode(PathBuf, PathBuf),
11 | // path to dir, has children,
12 | DirNode(PathBuf, PathBuf, bool, )
13 | }
14 |
15 | const EXPANDABLE : i8 = 1;
16 | const NOT_EXPANDABLE : i8 = 2;
17 |
18 | fn text_and_file_name<'a>(cache_root: &'a Path, path: &'a Path) -> (&'a str,String) {
19 | let mut text = path.file_name().unwrap().to_str().unwrap();
20 | text = &text[0..text.len()-4];
21 |
22 | let cache_root_str : &str = &cache_root.to_str().unwrap();
23 | let path_str : &str = &path.to_str().unwrap();
24 |
25 | // Subtract the common cache path bits. And trim off the .wsp while we're at it.
26 | // One of the most reckless code path in here! 8-)
27 | let without_root : &str = &path_str[ cache_root_str.len()+1 .. path_str.len()-4 ];
28 | let mut metric_name = without_root.to_string();
29 | metric_name = metric_name.replace("/",".");
30 |
31 | return (text, metric_name)
32 | }
33 |
34 | fn text_and_folder_name<'a>(cache_root: &'a Path, path: &'a Path) -> (&'a str,String) {
35 | let text = path.file_name().unwrap().to_str().unwrap();
36 |
37 | let cache_root_str : &str = &cache_root.to_str().unwrap();
38 | let path_str : &str = &path.to_str().unwrap();
39 |
40 | // Subtract the common cache path bits. And trim off the .wsp while we're at it.
41 | // One of the most reckless code path in here! 8-)
42 | let without_root : &str = &path_str[ cache_root_str.len()+1 .. path_str.len() ];
43 | let mut metric_name = without_root.to_string();
44 | metric_name = metric_name.replace("/",".");
45 |
46 | return (text, metric_name)
47 | }
48 |
49 |
50 | impl QueryResultNode {
51 | fn to_json(&self) -> String {
52 | match *self {
53 | QueryResultNode::WspNode(ref cache_root, ref path) => {
54 | let pair = text_and_file_name(cache_root, path);
55 |
56 | format!(r#"{{"leaf": {leaf}, "context": {{}}, "text": "{text}", "expandable": {expandable}, "id": "{id}", "allowChildren": {allow_children}}}"#,
57 | allow_children=0, expandable=0, leaf=0,
58 | text=pair.0, id=pair.1)
59 | },
60 | QueryResultNode::DirNode(ref cache_root, ref path, ref has_children) => {
61 | let pair = text_and_folder_name(cache_root, path);
62 |
63 | format!(r#"{{"leaf": {leaf}, "context": {{}}, "text": "{text}", "expandable": {expandable}, "id": "{id}", "allowChildren": {allow_children}}}"#,
64 | allow_children=0, expandable= if *has_children { EXPANDABLE } else { NOT_EXPANDABLE } , leaf=0,
65 | text=pair.0, id=pair.1)
66 | }
67 | }
68 | }
69 | }
70 |
71 | // A file-system only operation which can detect
72 | // whisper files
73 | pub fn expand(query: &String, cache: &Cache) -> Vec {
74 | let glob_pattern = dots_to_full_path_glob(query, cache);
75 |
76 | debug!("expanding {}", glob_pattern);
77 |
78 | let mut retval = vec![];
79 | let search = glob(&glob_pattern).unwrap();
80 |
81 | for search_result in search {
82 | match search_result {
83 | Ok(path_buf) => {
84 | debug!("expansion match: {:?}", path_buf);
85 | let is_dir = {
86 | let path = path_buf.as_path();
87 | path.is_dir()
88 | };
89 |
90 | let has_children = if is_dir {
91 | read_dir( &path_buf ).unwrap().any(|f| {
92 | let metadata = f.unwrap().metadata().unwrap();
93 | metadata.is_dir() || metadata.is_file()
94 | })
95 | } else {
96 | false
97 | };
98 |
99 | if is_dir {
100 | retval.push( QueryResultNode::DirNode( cache.base_path.clone(), path_buf, has_children).to_json() )
101 | } else {
102 | retval.push( QueryResultNode::WspNode( cache.base_path.clone(), path_buf).to_json() )
103 | }
104 | },
105 | Err(e) => {
106 | info!("error in search: {:?}", e)
107 | }
108 | }
109 | }
110 |
111 | debug!("retval len: {}", retval.len());
112 |
113 | return retval
114 | }
115 |
116 | // TODO: is it really this much work?
117 | // TODO: what about security concerns for traversing the file system? Can you craft a query such that ".." shows up? (Don't think so)
118 | fn dots_to_full_path_glob(query: &String, cache: &Cache) -> String {
119 | let replaced = query.replace(".","/");
120 |
121 | let qualified_path = cache.base_path.join(replaced);
122 | let path : &Path = qualified_path.as_path();
123 | let str_rep = path.to_str().unwrap();
124 | let string_rep = str_rep.to_string();
125 | // string_rep.push_str(".wsp");
126 |
127 | return string_rep;
128 | }
129 |
130 | #[cfg(test)]
131 | mod tests {
132 | use std::path::Path;
133 | use super::super::super::whisper::cache::Cache;
134 | use super::QueryResultNode;
135 |
136 | #[test]
137 | fn has_full_path(){
138 | let cache = Cache::new(Path::new("/tmp"));
139 | let input = "what.*.ever".to_string();
140 | let expected = "/tmp/what/*/ever";
141 |
142 | let full_glob = super::dots_to_full_path_glob(&input, &cache);
143 |
144 | assert_eq!(full_glob, expected)
145 | }
146 |
147 | // Not trying that hard but a simple sanity check
148 | #[test]
149 | fn wont_go_up_directory(){
150 | let cache = Cache::new(Path::new("/tmp"));
151 | let input = "what.*.ever/../".to_string();
152 | let expected = "/tmp/what/*/ever////";
153 |
154 | let full_glob = super::dots_to_full_path_glob(&input, &cache);
155 |
156 | assert_eq!(full_glob, expected)
157 | }
158 |
159 | #[test]
160 | fn wsp_node_json(){
161 | let root = Path::new("/tmp/thing").to_path_buf();
162 | let deep = Path::new("/tmp/thing/is/cool/bear.wsp").to_path_buf();
163 | let wsp_node = QueryResultNode::WspNode( root, deep );
164 | let expected = "{\"leaf\": 0, \"context\": {}, \"text\": \"bear\", \"expandable\": 0, \"id\": \"is.cool.bear\", \"allowChildren\": 0}";
165 | assert_eq!( wsp_node.to_json(), expected.to_string() )
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/graphite/handlers/metrics_find.rs:
--------------------------------------------------------------------------------
1 | use super::super::super::whisper::Cache;
2 |
3 | use super::super::expander::expand;
4 | use super::super::cache_holder::CacheHolder;
5 | use super::super::error::StringError;
6 |
7 | use iron::prelude::*;
8 | use iron;
9 | use urlencoded::UrlEncodedQuery;
10 |
11 | use persistent::State;
12 | use std::sync::{ Arc, RwLock };
13 | use std::ops::DerefMut;
14 |
15 | pub fn metrics_find(req: &mut Request) -> IronResult {
16 | let locked_cache : Arc< RwLock > = req.get::>().unwrap();
17 | let mut cache_writer = locked_cache.write().unwrap();
18 | let mut cache = cache_writer.deref_mut();
19 |
20 | // Extract the decoded data as hashmap, using the UrlEncodedQuery plugin.
21 | match req.get_ref::() {
22 | Ok(ref hashmap) => {
23 | match hashmap.get("query") {
24 | Some(query) => {
25 | if query.len() == 1 {
26 | let ref first_query = query[0];
27 | let http_body = do_find_metrics(first_query, &mut cache);
28 | let mut http_res = Response::with((iron::status::Ok, http_body));
29 |
30 | let jsony_ctype = iron::headers::ContentType(
31 | iron::mime::Mime(
32 | iron::mime::TopLevel::Application,
33 | iron::mime::SubLevel::Json,
34 | vec![(iron::mime::Attr::Charset, iron::mime::Value::Utf8)]
35 | )
36 | );
37 | http_res.headers.set::(jsony_ctype);
38 | Ok(http_res)
39 | } else {
40 | error!("must provide only 1 query string");
41 | Err(IronError::new(StringError("Must provide only one query".to_string()), iron::status::BadRequest))
42 | }
43 | },
44 | None => {
45 | error!("no query was provided");
46 | Err(IronError::new(StringError("Must provide query".to_string()), iron::status::BadRequest))
47 | }
48 | }
49 | },
50 | Err(_) => {
51 | error!("unknown error");
52 | Err(IronError::new(StringError("Error whoaaa".to_string()), iron::status::BadRequest))
53 | }
54 | }
55 | }
56 |
57 | fn do_find_metrics(query: &String, cache: &mut Cache) -> String {
58 | let hits = expand(query, cache);
59 | format!("[{}]", hits.join(","))
60 | }
--------------------------------------------------------------------------------
/src/graphite/handlers/mod.rs:
--------------------------------------------------------------------------------
1 | mod metrics_find;
2 | mod render;
3 |
4 | pub use self::render::render;
5 | pub use self::metrics_find::metrics_find;
--------------------------------------------------------------------------------
/src/graphite/handlers/render.rs:
--------------------------------------------------------------------------------
1 | use iron::prelude::*;
2 | use iron;
3 | use urlencoded::UrlEncodedQuery;
4 |
5 | use std::io::Read;
6 |
7 | // [{
8 | // "target": "entries",
9 | // "datapoints": [
10 | // [1.0, 1311836008],
11 | // [2.0, 1311836009],
12 | // [3.0, 1311836010],
13 | // [5.0, 1311836011],
14 | // [6.0, 1311836012]
15 | // ]
16 | // }]
17 | pub fn render(req: &mut Request) -> IronResult {
18 | let mut buf : Vec = Vec::new();
19 | let bytes_read = req.body.read_to_end(&mut buf);
20 | println!("body ({bytes_read:?}: {:#?}", buf, bytes_read=bytes_read);
21 |
22 | match req.get_ref::() {
23 | Ok(ref hashmap) => println!("Parsed GET request query string:\n {:?}", hashmap),
24 | Err(ref e) => println!("err {:?}", e)
25 | };
26 |
27 | Ok( Response::with( (iron::status::Ok, "hey".to_string() ) ) )
28 | }
29 |
30 | // target=hey.select%20metric&from=-6h&until=now&format=json&maxDataPoints=1425
31 | // fn do_render() {
32 |
33 | // }
--------------------------------------------------------------------------------
/src/graphite/middleware/mod.rs:
--------------------------------------------------------------------------------
1 | mod path_fixer;
2 |
3 | pub use self::path_fixer::PathFixer;
4 |
--------------------------------------------------------------------------------
/src/graphite/middleware/path_fixer.rs:
--------------------------------------------------------------------------------
1 | use iron::prelude::*;
2 | use iron;
3 |
4 | pub struct PathFixer;
5 |
6 | impl iron::middleware::BeforeMiddleware for PathFixer {
7 | fn before(&self, req: &mut Request) -> IronResult<()> {
8 | let ref mut path = req.url.path;
9 | if path.last().unwrap().len() == 0 {
10 | path.pop();
11 | }
12 |
13 | Ok(())
14 | }
15 |
16 | // fn catch(&self, _: &mut Request, err: IronError) -> IronResult<()> {
17 | // Err(err)
18 | // }
19 | }
--------------------------------------------------------------------------------
/src/graphite/mod.rs:
--------------------------------------------------------------------------------
1 | extern crate iron;
2 | extern crate router;
3 | extern crate urlencoded;
4 | extern crate glob;
5 | extern crate persistent;
6 | // extern crate bodyparser;
7 |
8 | mod config;
9 | pub mod server;
10 | mod error;
11 | pub mod expander;
12 | mod middleware;
13 | mod handlers;
14 | mod cache_holder;
15 |
16 | pub use self::config::Config;
17 |
18 | // Query root namespace
19 | // curl 'http://10.69.8.54/graphite-web/metrics/find/?query=*' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' -H 'Cache-Control: no-cache' --compressed
20 | // [{"leaf": 0, "context": {}, "text": "carbon", "expandable": 1, "id": "carbon", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "cisco", "expandable": 1, "id": "cisco", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "collectd", "expandable": 1, "id": "collectd", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "es_xle", "expandable": 1, "id": "es_xle", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "logstash", "expandable": 1, "id": "logstash", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "misc", "expandable": 1, "id": "misc", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "stats", "expandable": 1, "id": "stats", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "stats_counts", "expandable": 1, "id": "stats_counts", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "statsd", "expandable": 1, "id": "statsd", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "uwsgi", "expandable": 1, "id": "uwsgi", "allowChildren": 1}]
21 |
22 | // Query a sub namespace
23 | // curl 'http://10.69.8.54/graphite-web/metrics/find/?query=carbon' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' -H 'Cache-Control: no-cache' --compressed
24 |
25 | // Query a sub namespace with wildcard
26 | // curl 'http://10.69.8.54/graphite-web/metrics/find/?query=collectd.xle.*' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' -H 'Cache-Control: no-cache' --compressed
27 | // [{"leaf": 0, "context": {}, "text": "xle-broker-01", "expandable": 1, "id": "collectd.xle.xle-broker-01", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-broker-02", "expandable": 1, "id": "collectd.xle.xle-broker-02", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-broker-03", "expandable": 1, "id": "collectd.xle.xle-broker-03", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-06", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-06", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-07", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-07", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-08", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-08", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-09", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-09", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-10", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-10", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-13", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-13", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-14", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-14", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-15", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-15", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-16", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-16", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-17", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-17", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-18", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-18", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-19", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-19", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-elasticsearch-20", "expandable": 1, "id": "collectd.xle.xle-elasticsearch-20", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-01", "expandable": 1, "id": "collectd.xle.xle-forwarder-01", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-02", "expandable": 1, "id": "collectd.xle.xle-forwarder-02", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-03", "expandable": 1, "id": "collectd.xle.xle-forwarder-03", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-04", "expandable": 1, "id": "collectd.xle.xle-forwarder-04", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-05", "expandable": 1, "id": "collectd.xle.xle-forwarder-05", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-06", "expandable": 1, "id": "collectd.xle.xle-forwarder-06", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-07", "expandable": 1, "id": "collectd.xle.xle-forwarder-07", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-08", "expandable": 1, "id": "collectd.xle.xle-forwarder-08", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-forwarder-102", "expandable": 1, "id": "collectd.xle.xle-forwarder-102", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-frontend-01", "expandable": 1, "id": "collectd.xle.xle-frontend-01", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-frontend-02-temp", "expandable": 1, "id": "collectd.xle.xle-frontend-02-temp", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-sensor-01vcasensorp01_hq_corp_viasat_com", "expandable": 1, "id": "collectd.xle.xle-sensor-01vcasensorp01_hq_corp_viasat_com", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-stats-01", "expandable": 1, "id": "collectd.xle.xle-stats-01", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-syslog-archiver-01", "expandable": 1, "id": "collectd.xle.xle-syslog-archiver-01", "allowChildren": 1}, {"leaf": 0, "context": {}, "text": "xle-syslog-forwarder-01vcasyslogp02_hq_corp_viasat_com", "expandable": 1, "id": "collectd.xle.xle-syslog-forwarder-01vcasyslogp02_hq_corp_viasat_com", "allowChildren": 1}]
28 |
29 | // Query a mixed namespace with wildcard
30 | // curl 'http://10.69.8.54/graphite-web/render' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' --data 'target=collectd.xle.xle-elasticsearch-20.*.*.*&from=-5min&until=now&format=json&maxDataPoints=362' --compressed
31 | // [{"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_merged.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_merged.write", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_octets.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_octets.write", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_ops.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_ops.write", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_time.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-sr0.disk_time.write", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_merged.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_merged.write", "datapoints": [[0.05, 1437548400], [0.099998, 1437548460], [0.033334, 1437548520], [0.033334, 1437548580], [0.033333, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_octets.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_octets.write", "datapoints": [[1365.344167, 1437548400], [1843.164623, 1437548460], [1160.55345, 1437548520], [1160.532349, 1437548580], [1160.517175, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_ops.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_ops.write", "datapoints": [[0.150001, 1437548400], [0.183328, 1437548460], [0.11667, 1437548520], [0.116667, 1437548580], [0.116666, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_time.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda.disk_time.write", "datapoints": [[2.21667, 1437548400], [1.083311, 1437548460], [2.283368, 1437548520], [1.150014, 1437548580], [1.716652, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_merged.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_merged.write", "datapoints": [[0.05, 1437548400], [0.099998, 1437548460], [0.033334, 1437548520], [0.033334, 1437548580], [0.033333, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_octets.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_octets.write", "datapoints": [[1365.335251, 1437548400], [1843.162884, 1437548460], [1160.548773, 1437548520], [1160.54616, 1437548580], [1160.527822, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_ops.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_ops.write", "datapoints": [[0.15, 1437548400], [0.18333, 1437548460], [0.116668, 1437548520], [0.116668, 1437548580], [0.116666, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_time.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vda1.disk_time.write", "datapoints": [[2.21667, 1437548400], [1.083312, 1437548460], [2.283362, 1437548520], [1.150014, 1437548580], [1.716659, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_merged.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_merged.write", "datapoints": [[22.766694, 1437548400], [40.449326, 1437548460], [26.200252, 1437548520], [21.083653, 1437548580], [23.133223, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_octets.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_octets.write", "datapoints": [[931090.118875, 1437548400], [1433847.928078, 1437548460], [1266018.975983, 1437548520], [893145.302494, 1437548580], [960575.70446, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_ops.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_ops.write", "datapoints": [[7.516675, 1437548400], [19.016339, 1437548460], [9.983438, 1437548520], [7.233437, 1437548580], [8.716625, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_time.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb.disk_time.write", "datapoints": [[7.150008, 1437548400], [4.949916, 1437548460], [11.633449, 1437548520], [6.683433, 1437548580], [5.999972, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_merged.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_merged.write", "datapoints": [[22.766691, 1437548400], [40.449393, 1437548460], [26.200222, 1437548520], [21.083678, 1437548580], [23.133223, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_octets.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_octets.write", "datapoints": [[931090.115522, 1437548400], [1433850.034798, 1437548460], [1266017.149898, 1437548520], [893146.625558, 1437548580], [960575.707561, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_ops.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_ops.write", "datapoints": [[7.416674, 1437548400], [15.216429, 1437548460], [9.450085, 1437548520], [7.050111, 1437548580], [8.44996, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_time.read", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.disk-vdb1.disk_time.write", "datapoints": [[7.233341, 1437548400], [6.016575, 1437548460], [12.250107, 1437548520], [6.816776, 1437548580], [6.166637, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_errors.rx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_errors.tx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_octets.rx", "datapoints": [[206384.034396, 1437548400], [181786.848038, 1437548460], [187141.228723, 1437548520], [185586.058428, 1437548580], [188129.387048, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_octets.tx", "datapoints": [[73172.681439, 1437548400], [58449.103321, 1437548460], [58215.881876, 1437548520], [60515.573755, 1437548580], [58241.422936, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_packets.rx", "datapoints": [[289.384544, 1437548400], [262.561301, 1437548460], [273.485892, 1437548520], [267.752853, 1437548580], [268.297009, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-eth0.if_packets.tx", "datapoints": [[258.984417, 1437548400], [235.561853, 1437548460], [237.902226, 1437548520], [238.552542, 1437548580], [237.13069, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_errors.rx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_errors.tx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_octets.rx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_octets.tx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_packets.rx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.interface-lo.if_packets.tx", "datapoints": [[0.0, 1437548400], [0.0, 1437548460], [0.0, 1437548520], [0.0, 1437548580], [0.0, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.load.load.longterm", "datapoints": [[0.35, 1437548400], [0.35, 1437548460], [0.35, 1437548520], [0.34, 1437548580], [0.35, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.load.load.midterm", "datapoints": [[0.26, 1437548400], [0.31, 1437548460], [0.31, 1437548520], [0.3, 1437548580], [0.34, 1437548640]]}, {"target": "collectd.xle.xle-elasticsearch-20.load.load.shortterm", "datapoints": [[0.18, 1437548400], [0.42, 1437548460], [0.38, 1437548520], [0.23, 1437548580], [0.43, 1437548640]]}]
32 |
33 | // Query one metric
34 | // curl 'http://10.69.8.54/graphite-web/metrics/find/?query=carbon.agents.xle-stats-01-a.cache.*' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Accept: application/json, text/plain, */*' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' -H 'Cache-Control: no-cache' --compressed
35 |
36 | // Render a single query
37 | // curl 'http://10.69.8.54/graphite-web/render' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' --data 'target=carbon.agents.xle-stats-01-a.cache.size&from=-6h&until=now&format=json&maxDataPoints=611' --compressed
38 |
39 | // Render two queries
40 | // curl 'http://10.69.8.54/graphite-web/render' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' --data 'target=carbon.agents.xle-stats-01-a.cache.size&target=carbon.agents.xle-stats-01-a.cache.queues&from=-6h&until=now&format=json&maxDataPoints=611' --compressed
41 | // [{"target": "carbon.agents.xle-stats-01-a.cache.size", "datapoints": [[0.0, 1437321720], [76.0, 1437321780], [7.0, 1437321840], [0.0, 1437321900], [76.0, 1437321960], [7.0, 1437322020], [77.0, 1437322080], [12045.0, 1437322140], [77.0, 1437322200], [7.0, 1437322260], [0.0, 1437322320], [77.0, 1437322380], [76.0, 1437322440], [78.0, 1437322500], [0.0, 1437322560], [4.0, 1437322620], [76.0, 1437322680], [78.0, 1437322740], [59.0, 1437322800], [0.0, 1437322860], [0.0, 1437322920], [0.0, 1437322980], [0.0, 1437323040], [7.0, 1437323100], [91.0, 1437323160], [7.0, 1437323220], [91.0, 1437323280], [2214.0, 1437323340], [1270.0, 1437323400], [0.0, 1437323460], [92.0, 1437323520], [91.0, 1437323580], [73.0, 1437323640], [530.0, 1437323700], [14.0, 1437323760], [953.0, 1437323820], [1153.0, 1437323880], [0.0, 1437323940], [0.0, 1437324000], [669.0, 1437324060], [959.0, 1437324120], [523.0, 1437324180], [75.0, 1437324240], [856.0, 1437324300], [496.0, 1437324360], [75.0, 1437324420], [0.0, 1437324480], [7.0, 1437324540], [77.0, 1437324600], [59.0, 1437324660], [77.0, 1437324720], [77.0, 1437324780], [0.0, 1437324840], [77.0, 1437324900], [0.0, 1437324960], [0.0, 1437325020], [0.0, 1437325080], [60.0, 1437325140], [79.0, 1437325200], [75.0, 1437325260], [75.0, 1437325320], [0.0, 1437325380], [74.0, 1437325440], [0.0, 1437325500], [0.0, 1437325560], [76.0, 1437325620], [0.0, 1437325680], [7.0, 1437325740], [59.0, 1437325800], [4.0, 1437325860], [0.0, 1437325920], [7.0, 1437325980], [0.0, 1437326040], [7.0, 1437326100], [76.0, 1437326160], [0.0, 1437326220], [0.0, 1437326280], [76.0, 1437326340], [77.0, 1437326400], [59.0, 1437326460], [0.0, 1437326520], [78.0, 1437326580], [75.0, 1437326640], [0.0, 1437326700], [7.0, 1437326760], [77.0, 1437326820], [0.0, 1437326880], [0.0, 1437326940], [0.0, 1437327000], [61.0, 1437327060], [63.0, 1437327120], [79.0, 1437327180], [52.0, 1437327240], [7.0, 1437327300], [7.0, 1437327360], [75.0, 1437327420], [74.0, 1437327480], [0.0, 1437327540], [76.0, 1437327600], [75.0, 1437327660], [58.0, 1437327720], [77.0, 1437327780], [75.0, 1437327840], [75.0, 1437327900], [0.0, 1437327960], [77.0, 1437328020], [213.0, 1437328080], [0.0, 1437328140], [0.0, 1437328200], [490.0, 1437328260], [0.0, 1437328320], [2733.0, 1437328380], [0.0, 1437328440], [1719.0, 1437328500], [0.0, 1437328560], [7.0, 1437328620], [7.0, 1437328680], [60.0, 1437328740], [77.0, 1437328800], [1711.0, 1437328860], [2735.0, 1437328920], [2734.0, 1437328980], [76.0, 1437329040], [2715.0, 1437329100], [1326.0, 1437329160], [2734.0, 1437329220], [2484.0, 1437329280], [2735.0, 1437329340], [2665.0, 1437329400], [0.0, 1437329460], [0.0, 1437329520], [75.0, 1437329580], [77.0, 1437329640], [0.0, 1437329700], [59.0, 1437329760], [2000.0, 1437329820], [0.0, 1437329880], [75.0, 1437329940], [0.0, 1437330000], [7.0, 1437330060], [77.0, 1437330120], [4.0, 1437330180], [0.0, 1437330240], [0.0, 1437330300], [0.0, 1437330360], [76.0, 1437330420], [77.0, 1437330480], [77.0, 1437330540], [75.0, 1437330600], [7.0, 1437330660], [76.0, 1437330720], [76.0, 1437330780], [0.0, 1437330840], [77.0, 1437330900], [59.0, 1437330960], [7.0, 1437331020], [0.0, 1437331080], [0.0, 1437331140], [7.0, 1437331200], [58.0, 1437331260], [7.0, 1437331320], [78.0, 1437331380], [0.0, 1437331440], [0.0, 1437331500], [0.0, 1437331560], [0.0, 1437331620], [75.0, 1437331680], [0.0, 1437331740], [59.0, 1437331800], [0.0, 1437331860], [77.0, 1437331920], [76.0, 1437331980], [7.0, 1437332040], [0.0, 1437332100], [77.0, 1437332160], [0.0, 1437332220], [77.0, 1437332280], [0.0, 1437332340], [7.0, 1437332400], [76.0, 1437332460], [0.0, 1437332520], [75.0, 1437332580], [0.0, 1437332640], [90.0, 1437332700], [91.0, 1437332760], [91.0, 1437332820], [91.0, 1437332880], [74.0, 1437332940], [21.0, 1437333000], [0.0, 1437333060], [74.0, 1437333120], [92.0, 1437333180], [14.0, 1437333240], [14.0, 1437333300], [61.0, 1437333360], [7.0, 1437333420], [7.0, 1437333480], [0.0, 1437333540], [76.0, 1437333600], [75.0, 1437333660], [61.0, 1437333720], [7.0, 1437333780], [0.0, 1437333840], [0.0, 1437333900], [0.0, 1437333960], [77.0, 1437334020], [7.0, 1437334080], [0.0, 1437334140], [76.0, 1437334200], [75.0, 1437334260], [7.0, 1437334320], [60.0, 1437334380], [0.0, 1437334440], [76.0, 1437334500], [76.0, 1437334560], [77.0, 1437334620], [0.0, 1437334680], [0.0, 1437334740], [0.0, 1437334800], [77.0, 1437334860], [75.0, 1437334920], [0.0, 1437334980], [60.0, 1437335040], [75.0, 1437335100], [0.0, 1437335160], [77.0, 1437335220], [77.0, 1437335280], [58.0, 1437335340], [75.0, 1437335400], [7.0, 1437335460], [77.0, 1437335520], [7.0, 1437335580], [0.0, 1437335640], [76.0, 1437335700], [77.0, 1437335760], [75.0, 1437335820], [0.0, 1437335880], [7.0, 1437335940], [0.0, 1437336000], [76.0, 1437336060], [77.0, 1437336120], [76.0, 1437336180], [61.0, 1437336240], [78.0, 1437336300], [0.0, 1437336360], [75.0, 1437336420], [77.0, 1437336480], [76.0, 1437336540], [0.0, 1437336600], [75.0, 1437336660], [78.0, 1437336720], [77.0, 1437336780], [0.0, 1437336840], [7.0, 1437336900], [0.0, 1437336960], [76.0, 1437337020], [75.0, 1437337080], [7.0, 1437337140], [59.0, 1437337200], [0.0, 1437337260], [78.0, 1437337320], [4.0, 1437337380], [0.0, 1437337440], [0.0, 1437337500], [77.0, 1437337560], [77.0, 1437337620], [7.0, 1437337680], [60.0, 1437337740], [76.0, 1437337800], [0.0, 1437337860], [75.0, 1437337920], [18.0, 1437337980], [59.0, 1437338040], [7.0, 1437338100], [7.0, 1437338160], [77.0, 1437338220], [0.0, 1437338280], [0.0, 1437338340], [19.0, 1437338400], [0.0, 1437338460], [78.0, 1437338520], [77.0, 1437338580], [7.0, 1437338640], [77.0, 1437338700], [0.0, 1437338760], [0.0, 1437338820], [0.0, 1437338880], [0.0, 1437338940], [0.0, 1437339000], [75.0, 1437339060], [77.0, 1437339120], [75.0, 1437339180], [0.0, 1437339240], [7.0, 1437339300], [0.0, 1437339360], [77.0, 1437339420], [60.0, 1437339480], [3.0, 1437339540], [0.0, 1437339600], [7.0, 1437339660], [0.0, 1437339720], [0.0, 1437339780], [77.0, 1437339840], [0.0, 1437339900], [77.0, 1437339960], [7.0, 1437340020], [57.0, 1437340080], [0.0, 1437340140], [7.0, 1437340200], [77.0, 1437340260], [0.0, 1437340320], [60.0, 1437340380], [76.0, 1437340440], [7.0, 1437340500], [0.0, 1437340560], [0.0, 1437340620], [78.0, 1437340680], [77.0, 1437340740], [0.0, 1437340800], [60.0, 1437340860], [75.0, 1437340920], [75.0, 1437340980], [76.0, 1437341040], [77.0, 1437341100], [0.0, 1437341160], [58.0, 1437341220], [0.0, 1437341280], [78.0, 1437341340], [76.0, 1437341400], [7.0, 1437341460], [61.0, 1437341520], [7.0, 1437341580], [0.0, 1437341640], [76.0, 1437341700], [75.0, 1437341760], [59.0, 1437341820], [7.0, 1437341880], [76.0, 1437341940], [76.0, 1437342000], [76.0, 1437342060], [89.0, 1437342120], [72.0, 1437342180], [78.0, 1437342240], [7.0, 1437342300], [92.0, 1437342360], [7.0, 1437342420], [21.0, 1437342480], [93.0, 1437342540], [11050.0, 1437342600], [21.0, 1437342660], [14.0, 1437342720], [14.0, 1437342780], [80.0, 1437342840], [0.0, 1437342900], [0.0, 1437342960], [77.0, 1437343020], [76.0, 1437343080], [76.0, 1437343140], [0.0, 1437343200], [null, 1437343260]]}, {"target": "carbon.agents.xle-stats-01-a.cache.queues", "datapoints": [[0.0, 1437321720], [64.0, 1437321780], [7.0, 1437321840], [0.0, 1437321900], [73.0, 1437321960], [7.0, 1437322020], [73.0, 1437322080], [11842.0, 1437322140], [72.0, 1437322200], [7.0, 1437322260], [0.0, 1437322320], [67.0, 1437322380], [69.0, 1437322440], [73.0, 1437322500], [0.0, 1437322560], [4.0, 1437322620], [70.0, 1437322680], [71.0, 1437322740], [55.0, 1437322800], [0.0, 1437322860], [0.0, 1437322920], [0.0, 1437322980], [0.0, 1437323040], [7.0, 1437323100], [85.0, 1437323160], [7.0, 1437323220], [87.0, 1437323280], [2203.0, 1437323340], [1267.0, 1437323400], [0.0, 1437323460], [87.0, 1437323520], [85.0, 1437323580], [73.0, 1437323640], [516.0, 1437323700], [14.0, 1437323760], [949.0, 1437323820], [1138.0, 1437323880], [0.0, 1437323940], [0.0, 1437324000], [665.0, 1437324060], [933.0, 1437324120], [521.0, 1437324180], [73.0, 1437324240], [851.0, 1437324300], [494.0, 1437324360], [73.0, 1437324420], [0.0, 1437324480], [7.0, 1437324540], [73.0, 1437324600], [57.0, 1437324660], [61.0, 1437324720], [73.0, 1437324780], [0.0, 1437324840], [72.0, 1437324900], [0.0, 1437324960], [0.0, 1437325020], [0.0, 1437325080], [60.0, 1437325140], [71.0, 1437325200], [71.0, 1437325260], [65.0, 1437325320], [0.0, 1437325380], [69.0, 1437325440], [0.0, 1437325500], [0.0, 1437325560], [65.0, 1437325620], [0.0, 1437325680], [7.0, 1437325740], [59.0, 1437325800], [4.0, 1437325860], [0.0, 1437325920], [7.0, 1437325980], [0.0, 1437326040], [7.0, 1437326100], [73.0, 1437326160], [0.0, 1437326220], [0.0, 1437326280], [65.0, 1437326340], [69.0, 1437326400], [55.0, 1437326460], [0.0, 1437326520], [64.0, 1437326580], [66.0, 1437326640], [0.0, 1437326700], [7.0, 1437326760], [71.0, 1437326820], [0.0, 1437326880], [0.0, 1437326940], [0.0, 1437327000], [61.0, 1437327060], [56.0, 1437327120], [69.0, 1437327180], [52.0, 1437327240], [7.0, 1437327300], [7.0, 1437327360], [73.0, 1437327420], [63.0, 1437327480], [0.0, 1437327540], [73.0, 1437327600], [73.0, 1437327660], [56.0, 1437327720], [73.0, 1437327780], [70.0, 1437327840], [72.0, 1437327900], [0.0, 1437327960], [73.0, 1437328020], [211.0, 1437328080], [0.0, 1437328140], [0.0, 1437328200], [485.0, 1437328260], [0.0, 1437328320], [2731.0, 1437328380], [0.0, 1437328440], [1719.0, 1437328500], [0.0, 1437328560], [7.0, 1437328620], [7.0, 1437328680], [57.0, 1437328740], [65.0, 1437328800], [1711.0, 1437328860], [2731.0, 1437328920], [2731.0, 1437328980], [73.0, 1437329040], [2713.0, 1437329100], [1326.0, 1437329160], [2720.0, 1437329220], [2484.0, 1437329280], [2729.0, 1437329340], [2665.0, 1437329400], [0.0, 1437329460], [0.0, 1437329520], [73.0, 1437329580], [73.0, 1437329640], [0.0, 1437329700], [57.0, 1437329760], [2000.0, 1437329820], [0.0, 1437329880], [70.0, 1437329940], [0.0, 1437330000], [7.0, 1437330060], [73.0, 1437330120], [4.0, 1437330180], [0.0, 1437330240], [0.0, 1437330300], [0.0, 1437330360], [67.0, 1437330420], [73.0, 1437330480], [69.0, 1437330540], [71.0, 1437330600], [7.0, 1437330660], [73.0, 1437330720], [65.0, 1437330780], [0.0, 1437330840], [73.0, 1437330900], [59.0, 1437330960], [7.0, 1437331020], [0.0, 1437331080], [0.0, 1437331140], [7.0, 1437331200], [55.0, 1437331260], [7.0, 1437331320], [72.0, 1437331380], [0.0, 1437331440], [0.0, 1437331500], [0.0, 1437331560], [0.0, 1437331620], [65.0, 1437331680], [0.0, 1437331740], [55.0, 1437331800], [0.0, 1437331860], [63.0, 1437331920], [66.0, 1437331980], [7.0, 1437332040], [0.0, 1437332100], [67.0, 1437332160], [0.0, 1437332220], [70.0, 1437332280], [0.0, 1437332340], [7.0, 1437332400], [65.0, 1437332460], [0.0, 1437332520], [69.0, 1437332580], [0.0, 1437332640], [73.0, 1437332700], [85.0, 1437332760], [81.0, 1437332820], [85.0, 1437332880], [74.0, 1437332940], [21.0, 1437333000], [0.0, 1437333060], [74.0, 1437333120], [83.0, 1437333180], [14.0, 1437333240], [14.0, 1437333300], [59.0, 1437333360], [7.0, 1437333420], [7.0, 1437333480], [0.0, 1437333540], [66.0, 1437333600], [73.0, 1437333660], [61.0, 1437333720], [7.0, 1437333780], [0.0, 1437333840], [0.0, 1437333900], [0.0, 1437333960], [71.0, 1437334020], [7.0, 1437334080], [0.0, 1437334140], [64.0, 1437334200], [69.0, 1437334260], [7.0, 1437334320], [60.0, 1437334380], [0.0, 1437334440], [71.0, 1437334500], [64.0, 1437334560], [71.0, 1437334620], [0.0, 1437334680], [0.0, 1437334740], [0.0, 1437334800], [73.0, 1437334860], [73.0, 1437334920], [0.0, 1437334980], [60.0, 1437335040], [73.0, 1437335100], [0.0, 1437335160], [68.0, 1437335220], [72.0, 1437335280], [57.0, 1437335340], [69.0, 1437335400], [7.0, 1437335460], [69.0, 1437335520], [7.0, 1437335580], [0.0, 1437335640], [61.0, 1437335700], [73.0, 1437335760], [73.0, 1437335820], [0.0, 1437335880], [7.0, 1437335940], [0.0, 1437336000], [67.0, 1437336060], [65.0, 1437336120], [73.0, 1437336180], [61.0, 1437336240], [72.0, 1437336300], [0.0, 1437336360], [71.0, 1437336420], [69.0, 1437336480], [73.0, 1437336540], [0.0, 1437336600], [73.0, 1437336660], [64.0, 1437336720], [73.0, 1437336780], [0.0, 1437336840], [7.0, 1437336900], [0.0, 1437336960], [65.0, 1437337020], [71.0, 1437337080], [7.0, 1437337140], [59.0, 1437337200], [0.0, 1437337260], [71.0, 1437337320], [4.0, 1437337380], [0.0, 1437337440], [0.0, 1437337500], [67.0, 1437337560], [71.0, 1437337620], [7.0, 1437337680], [59.0, 1437337740], [73.0, 1437337800], [0.0, 1437337860], [71.0, 1437337920], [18.0, 1437337980], [59.0, 1437338040], [7.0, 1437338100], [7.0, 1437338160], [69.0, 1437338220], [0.0, 1437338280], [0.0, 1437338340], [19.0, 1437338400], [0.0, 1437338460], [71.0, 1437338520], [71.0, 1437338580], [7.0, 1437338640], [63.0, 1437338700], [0.0, 1437338760], [0.0, 1437338820], [0.0, 1437338880], [0.0, 1437338940], [0.0, 1437339000], [73.0, 1437339060], [73.0, 1437339120], [69.0, 1437339180], [0.0, 1437339240], [7.0, 1437339300], [0.0, 1437339360], [73.0, 1437339420], [60.0, 1437339480], [3.0, 1437339540], [0.0, 1437339600], [7.0, 1437339660], [0.0, 1437339720], [0.0, 1437339780], [59.0, 1437339840], [0.0, 1437339900], [73.0, 1437339960], [7.0, 1437340020], [57.0, 1437340080], [0.0, 1437340140], [7.0, 1437340200], [73.0, 1437340260], [0.0, 1437340320], [60.0, 1437340380], [72.0, 1437340440], [7.0, 1437340500], [0.0, 1437340560], [0.0, 1437340620], [73.0, 1437340680], [69.0, 1437340740], [0.0, 1437340800], [60.0, 1437340860], [73.0, 1437340920], [73.0, 1437340980], [73.0, 1437341040], [73.0, 1437341100], [0.0, 1437341160], [58.0, 1437341220], [0.0, 1437341280], [64.0, 1437341340], [73.0, 1437341400], [7.0, 1437341460], [61.0, 1437341520], [7.0, 1437341580], [0.0, 1437341640], [71.0, 1437341700], [71.0, 1437341760], [57.0, 1437341820], [7.0, 1437341880], [63.0, 1437341940], [68.0, 1437342000], [71.0, 1437342060], [85.0, 1437342120], [72.0, 1437342180], [62.0, 1437342240], [7.0, 1437342300], [87.0, 1437342360], [7.0, 1437342420], [21.0, 1437342480], [77.0, 1437342540], [10757.0, 1437342600], [21.0, 1437342660], [14.0, 1437342720], [14.0, 1437342780], [69.0, 1437342840], [0.0, 1437342900], [0.0, 1437342960], [61.0, 1437343020], [73.0, 1437343080], [72.0, 1437343140], [0.0, 1437343200], [null, 1437343260]]}]
42 |
43 | // Render a single query with a wild card
44 | // curl 'http://10.69.8.54/graphite-web/render' -H 'Pragma: no-cache' -H 'Origin: http://10.69.8.55' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json, text/plain, */*' -H 'Cache-Control: no-cache' -H 'Referer: http://10.69.8.55/grafana/' -H 'Connection: keep-alive' --data 'target=carbon.agents.*.cache.size&from=-6h&until=now&format=json&maxDataPoints=611' --compressed
45 | // [{"target": "carbon.agents.xle-stats-01-a.cache.size", "datapoints": [[76.0, 1437321780], [7.0, 1437321840], [0.0, 1437321900], [76.0, 1437321960], [7.0, 1437322020], [77.0, 1437322080], [12045.0, 1437322140], [77.0, 1437322200], [7.0, 1437322260], [0.0, 1437322320], [77.0, 1437322380], [76.0, 1437322440], [78.0, 1437322500], [0.0, 1437322560], [4.0, 1437322620], [76.0, 1437322680], [78.0, 1437322740], [59.0, 1437322800], [0.0, 1437322860], [0.0, 1437322920], [0.0, 1437322980], [0.0, 1437323040], [7.0, 1437323100], [91.0, 1437323160], [7.0, 1437323220], [91.0, 1437323280], [2214.0, 1437323340], [1270.0, 1437323400], [0.0, 1437323460], [92.0, 1437323520], [91.0, 1437323580], [73.0, 1437323640], [530.0, 1437323700], [14.0, 1437323760], [953.0, 1437323820], [1153.0, 1437323880], [0.0, 1437323940], [0.0, 1437324000], [669.0, 1437324060], [959.0, 1437324120], [523.0, 1437324180], [75.0, 1437324240], [856.0, 1437324300], [496.0, 1437324360], [75.0, 1437324420], [0.0, 1437324480], [7.0, 1437324540], [77.0, 1437324600], [59.0, 1437324660], [77.0, 1437324720], [77.0, 1437324780], [0.0, 1437324840], [77.0, 1437324900], [0.0, 1437324960], [0.0, 1437325020], [0.0, 1437325080], [60.0, 1437325140], [79.0, 1437325200], [75.0, 1437325260], [75.0, 1437325320], [0.0, 1437325380], [74.0, 1437325440], [0.0, 1437325500], [0.0, 1437325560], [76.0, 1437325620], [0.0, 1437325680], [7.0, 1437325740], [59.0, 1437325800], [4.0, 1437325860], [0.0, 1437325920], [7.0, 1437325980], [0.0, 1437326040], [7.0, 1437326100], [76.0, 1437326160], [0.0, 1437326220], [0.0, 1437326280], [76.0, 1437326340], [77.0, 1437326400], [59.0, 1437326460], [0.0, 1437326520], [78.0, 1437326580], [75.0, 1437326640], [0.0, 1437326700], [7.0, 1437326760], [77.0, 1437326820], [0.0, 1437326880], [0.0, 1437326940], [0.0, 1437327000], [61.0, 1437327060], [63.0, 1437327120], [79.0, 1437327180], [52.0, 1437327240], [7.0, 1437327300], [7.0, 1437327360], [75.0, 1437327420], [74.0, 1437327480], [0.0, 1437327540], [76.0, 1437327600], [75.0, 1437327660], [58.0, 1437327720], [77.0, 1437327780], [75.0, 1437327840], [75.0, 1437327900], [0.0, 1437327960], [77.0, 1437328020], [213.0, 1437328080], [0.0, 1437328140], [0.0, 1437328200], [490.0, 1437328260], [0.0, 1437328320], [2733.0, 1437328380], [0.0, 1437328440], [1719.0, 1437328500], [0.0, 1437328560], [7.0, 1437328620], [7.0, 1437328680], [60.0, 1437328740], [77.0, 1437328800], [1711.0, 1437328860], [2735.0, 1437328920], [2734.0, 1437328980], [76.0, 1437329040], [2715.0, 1437329100], [1326.0, 1437329160], [2734.0, 1437329220], [2484.0, 1437329280], [2735.0, 1437329340], [2665.0, 1437329400], [0.0, 1437329460], [0.0, 1437329520], [75.0, 1437329580], [77.0, 1437329640], [0.0, 1437329700], [59.0, 1437329760], [2000.0, 1437329820], [0.0, 1437329880], [75.0, 1437329940], [0.0, 1437330000], [7.0, 1437330060], [77.0, 1437330120], [4.0, 1437330180], [0.0, 1437330240], [0.0, 1437330300], [0.0, 1437330360], [76.0, 1437330420], [77.0, 1437330480], [77.0, 1437330540], [75.0, 1437330600], [7.0, 1437330660], [76.0, 1437330720], [76.0, 1437330780], [0.0, 1437330840], [77.0, 1437330900], [59.0, 1437330960], [7.0, 1437331020], [0.0, 1437331080], [0.0, 1437331140], [7.0, 1437331200], [58.0, 1437331260], [7.0, 1437331320], [78.0, 1437331380], [0.0, 1437331440], [0.0, 1437331500], [0.0, 1437331560], [0.0, 1437331620], [75.0, 1437331680], [0.0, 1437331740], [59.0, 1437331800], [0.0, 1437331860], [77.0, 1437331920], [76.0, 1437331980], [7.0, 1437332040], [0.0, 1437332100], [77.0, 1437332160], [0.0, 1437332220], [77.0, 1437332280], [0.0, 1437332340], [7.0, 1437332400], [76.0, 1437332460], [0.0, 1437332520], [75.0, 1437332580], [0.0, 1437332640], [90.0, 1437332700], [91.0, 1437332760], [91.0, 1437332820], [91.0, 1437332880], [74.0, 1437332940], [21.0, 1437333000], [0.0, 1437333060], [74.0, 1437333120], [92.0, 1437333180], [14.0, 1437333240], [14.0, 1437333300], [61.0, 1437333360], [7.0, 1437333420], [7.0, 1437333480], [0.0, 1437333540], [76.0, 1437333600], [75.0, 1437333660], [61.0, 1437333720], [7.0, 1437333780], [0.0, 1437333840], [0.0, 1437333900], [0.0, 1437333960], [77.0, 1437334020], [7.0, 1437334080], [0.0, 1437334140], [76.0, 1437334200], [75.0, 1437334260], [7.0, 1437334320], [60.0, 1437334380], [0.0, 1437334440], [76.0, 1437334500], [76.0, 1437334560], [77.0, 1437334620], [0.0, 1437334680], [0.0, 1437334740], [0.0, 1437334800], [77.0, 1437334860], [75.0, 1437334920], [0.0, 1437334980], [60.0, 1437335040], [75.0, 1437335100], [0.0, 1437335160], [77.0, 1437335220], [77.0, 1437335280], [58.0, 1437335340], [75.0, 1437335400], [7.0, 1437335460], [77.0, 1437335520], [7.0, 1437335580], [0.0, 1437335640], [76.0, 1437335700], [77.0, 1437335760], [75.0, 1437335820], [0.0, 1437335880], [7.0, 1437335940], [0.0, 1437336000], [76.0, 1437336060], [77.0, 1437336120], [76.0, 1437336180], [61.0, 1437336240], [78.0, 1437336300], [0.0, 1437336360], [75.0, 1437336420], [77.0, 1437336480], [76.0, 1437336540], [0.0, 1437336600], [75.0, 1437336660], [78.0, 1437336720], [77.0, 1437336780], [0.0, 1437336840], [7.0, 1437336900], [0.0, 1437336960], [76.0, 1437337020], [75.0, 1437337080], [7.0, 1437337140], [59.0, 1437337200], [0.0, 1437337260], [78.0, 1437337320], [4.0, 1437337380], [0.0, 1437337440], [0.0, 1437337500], [77.0, 1437337560], [77.0, 1437337620], [7.0, 1437337680], [60.0, 1437337740], [76.0, 1437337800], [0.0, 1437337860], [75.0, 1437337920], [18.0, 1437337980], [59.0, 1437338040], [7.0, 1437338100], [7.0, 1437338160], [77.0, 1437338220], [0.0, 1437338280], [0.0, 1437338340], [19.0, 1437338400], [0.0, 1437338460], [78.0, 1437338520], [77.0, 1437338580], [7.0, 1437338640], [77.0, 1437338700], [0.0, 1437338760], [0.0, 1437338820], [0.0, 1437338880], [0.0, 1437338940], [0.0, 1437339000], [75.0, 1437339060], [77.0, 1437339120], [75.0, 1437339180], [0.0, 1437339240], [7.0, 1437339300], [0.0, 1437339360], [77.0, 1437339420], [60.0, 1437339480], [3.0, 1437339540], [0.0, 1437339600], [7.0, 1437339660], [0.0, 1437339720], [0.0, 1437339780], [77.0, 1437339840], [0.0, 1437339900], [77.0, 1437339960], [7.0, 1437340020], [57.0, 1437340080], [0.0, 1437340140], [7.0, 1437340200], [77.0, 1437340260], [0.0, 1437340320], [60.0, 1437340380], [76.0, 1437340440], [7.0, 1437340500], [0.0, 1437340560], [0.0, 1437340620], [78.0, 1437340680], [77.0, 1437340740], [0.0, 1437340800], [60.0, 1437340860], [75.0, 1437340920], [75.0, 1437340980], [76.0, 1437341040], [77.0, 1437341100], [0.0, 1437341160], [58.0, 1437341220], [0.0, 1437341280], [78.0, 1437341340], [76.0, 1437341400], [7.0, 1437341460], [61.0, 1437341520], [7.0, 1437341580], [0.0, 1437341640], [76.0, 1437341700], [75.0, 1437341760], [59.0, 1437341820], [7.0, 1437341880], [76.0, 1437341940], [76.0, 1437342000], [76.0, 1437342060], [89.0, 1437342120], [72.0, 1437342180], [78.0, 1437342240], [7.0, 1437342300], [92.0, 1437342360], [7.0, 1437342420], [21.0, 1437342480], [93.0, 1437342540], [11050.0, 1437342600], [21.0, 1437342660], [14.0, 1437342720], [14.0, 1437342780], [80.0, 1437342840], [0.0, 1437342900], [0.0, 1437342960], [77.0, 1437343020], [76.0, 1437343080], [76.0, 1437343140], [0.0, 1437343200], [61.0, 1437343260], [null, 1437343320]]}]
46 |
47 |
--------------------------------------------------------------------------------
/src/graphite/server.rs:
--------------------------------------------------------------------------------
1 | use super::config::Config;
2 | use super::middleware::PathFixer;
3 |
4 | use iron::prelude::*;
5 | use persistent::State;
6 |
7 | use router::Router;
8 |
9 | use super::super::whisper::Cache;
10 | use super::handlers;
11 | use super::cache_holder::CacheHolder;
12 |
13 | pub fn run(config: Config, cache: Cache) {
14 | let mut router = Router::new();
15 | router.get("/metrics/find", handlers::metrics_find);
16 | router.post("/render", handlers::render);
17 |
18 | let mut chain = Chain::new(router);
19 | chain.link_before(PathFixer);
20 | chain.link( State::::both(cache) );
21 |
22 | Iron::new(chain).http(config.bind_spec).unwrap();
23 | }
24 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | /*!
2 |
3 | # graphite-rust
4 |
5 | Herein lies a humble reimplementation of the graphite metrics system -- a time series database system,
6 | with HTTP frontend and management tools.
7 | It strikes a reasonable balance between features you need, easy management, and a rich ecosystem of tools which can talk to graphite.
8 |
9 | `graphite-rust` aims to maintain total compatibility in both features and file formats.
10 | The big selling point should be the ease of installation: it's just one
11 | binary. It may be higher performance but that's not the main goal.
12 |
13 | This work falls under the name `graphite` but in reality the package has distinct components you may want to understand:
14 |
15 | * [`whisper`](whisper/index.html) - all the heavy lifting for parsing and writing to whisper database files
16 | * `carbon` - the network daemon which mediates access to whisper files
17 | * `graphite` - the HTTP REST server which handles queries. It has a minimal HTML
18 | application for creating dashboard but I'll be skipping that. For dashboard you'll want [`grafana`](http://grafana.org/).
19 |
20 | Status of the codes:
21 |
22 | * `whisper`
23 | * *DOES* open and parse header/metadata/archive info
24 | * *IN PROGRESS* take a metric value and provide a WriteOp
25 | * *NOT STARTED* write `vec![WriteOp]` to file
26 | * `carbon`
27 | * *DOESN'T DO ANYTHING*
28 | * `graphite`
29 | * *DOESN'T EXIST*
30 |
31 | ## Also, this is brand-new code. In the true rust spirit it does not guarantee the safety of your kittens.
32 |
33 | */
34 |
35 | #![crate_name = "graphite"]
36 | #![feature(trace_macros)]
37 |
38 | #![feature(test)]
39 | extern crate test;
40 |
41 | extern crate time;
42 | extern crate byteorder;
43 |
44 | #[macro_use]
45 | extern crate log;
46 | extern crate env_logger;
47 |
48 | extern crate regex;
49 |
50 | extern crate whisper;
51 |
52 | pub mod carbon;
53 | // TODO: scuttled until I want to fix all the iron related issues
54 | // pub mod graphite;
55 |
--------------------------------------------------------------------------------
/test/scripts/tcp_multipoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | set -xe
3 |
4 | BODY=$( cat <