Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support text format #12

Merged
merged 17 commits into from
Aug 23, 2016
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target
Cargo.lock
bin
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ dev = ["clippy"]
protobuf = "1.0"
quick-error = "0.2"
clippy = {version = "*", optional = true}
fnv = "1.0.3"
fnv = "1.0.3"

[dependencies.hyper]
git = "https://github.com/hyperium/hyper.git"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any need for this to be a git-dependency instead of a versioned crate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes @lucab.
Hope hyper can release 1.0 soon too :-)

Copy link
Member

@BusyJay BusyJay Aug 23, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just used in examples?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now yes.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can put it into dev-dependencies.

11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
all: format build test
all: format build test examples

build:
cargo build --features default
Expand All @@ -14,4 +14,11 @@ format:
cargo fmt -- --write-mode overwrite

clean:
cargo clean
cargo clean

examples:
cargo build --example example_embed
cargo build --example example_hyper
cp target/debug/examples/* bin/

.PHONY: all examples
63 changes: 63 additions & 0 deletions examples/example_embed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate prom;
extern crate hyper;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This crate seems unused.


use std::thread;
use std::time::Duration;

use prom::encoder::{TextEncoder, Encoder};
use prom::{Counter, Opts, Registry};

fn main() {
let opts = Opts::new("test", "test help").const_label("a", "1").const_label("b", "2");
let counter = Counter::with_opts(opts).unwrap();

let r = Registry::new();
r.register(Box::new(counter.clone())).unwrap();

counter.inc();
assert_eq!(counter.get() as u64, 1);
counter.inc_by(42.0).unwrap();
assert_eq!(counter.get() as u64, 43);

let c2 = counter.clone();
thread::spawn(move || {
for _ in 0..10 {
thread::sleep(Duration::from_millis(500));
c2.inc();
}
});

thread::spawn(move || {
for _ in 0..5 {
thread::sleep(Duration::from_secs(1));
counter.inc();
}
});

// Choose your writer and encoder.
let mut buffer = Vec::<u8>::new();
let encoder = TextEncoder::new();
for _ in 0..5 {
let metric_familys = r.gather();
encoder.encode(&metric_familys, &mut buffer).unwrap();

// Output to the standard output.
println!("{}", String::from_utf8(buffer.clone()).unwrap());

buffer.clear();
thread::sleep(Duration::from_secs(1));
}
}
134 changes: 134 additions & 0 deletions examples/example_hyper.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate prom;
extern crate hyper;

use std::thread;
use std::time::Duration;

use hyper::{StatusCode, Decoder, Next, Encoder as HyperEncoder};
use hyper::header::{ContentLength, ContentType};
use hyper::net::HttpStream;
use hyper::server::{Server, Handler, Request, Response};
use hyper::mime::Mime;

use prom::errors::{Error, Result};
use prom::encoder::{Encoder, TextEncoder};
use prom::{Counter, Opts, Registry};

fn main() {
let opts = Opts::new("test", "test help").const_label("a", "1").const_label("b", "2");
let counter = Counter::with_opts(opts).unwrap();

let r = Registry::new();
r.register(Box::new(counter.clone())).unwrap();

counter.inc();
assert_eq!(counter.get() as u64, 1);
counter.inc_by(42.0).unwrap();
assert_eq!(counter.get() as u64, 43);

let c2 = counter.clone();
thread::spawn(move || {
loop {
thread::sleep(Duration::from_millis(300));
c2.inc();
}
});

thread::spawn(move || {
loop {
thread::sleep(Duration::from_millis(1500));
counter.inc();
}
});

let encoder = TextEncoder::new();
// Http server
run("127.0.0.1:9898", &r, &encoder).unwrap();
}

// run runs a http server with a Registry and a Encoder, it blocks current thread.
pub fn run<'a>(addr: &str, reg: &Registry, encoder: &'a Encoder) -> Result<()> {
let reg = reg.clone();

let addr = try!(addr.parse().or_else(|e| Err(Error::Msg(format!("{:?}", e)))));
let server = try!(Server::http(&addr).or_else(|e| Err(Error::Msg(format!("{:?}", e)))));
if let Ok((listener, server)) = server.handle(|_| HttpHandler::new(reg.clone(), encoder)) {
println!("listening {}", listener);

server.run();
}

Err(Error::Msg("http server error".to_owned()))
}

pub struct HttpHandler<'a> {
registry: Registry,
encoder: &'a (Encoder + 'a),
buffer: Vec<u8>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In practice, we should use VecDeque.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is only example, I think ok here.

write_pos: usize,
}

impl<'a> HttpHandler<'a> {
pub fn new(registry: Registry, encoder: &'a Encoder) -> HttpHandler<'a> {
HttpHandler {
registry: registry,
encoder: encoder,
buffer: Vec::new(),
write_pos: 0,
}
}
}

impl<'a> Handler<HttpStream> for HttpHandler<'a> {
fn on_request(&mut self, _: Request<HttpStream>) -> Next {
// TODO: route requests
Next::write()
}

fn on_request_readable(&mut self, _: &mut Decoder<HttpStream>) -> Next {
Next::write()
}

fn on_response(&mut self, res: &mut Response) -> Next {
let metric_familys = self.registry.gather();
if let Ok(written) = self.encoder.encode(&metric_familys, &mut self.buffer) {
res.headers_mut().set(ContentLength(written as u64));
} else {
return Next::remove();
}

self.write_pos = 0;
res.set_status(StatusCode::Ok);
res.headers_mut().set(ContentType((&self.encoder.format_type()).parse::<Mime>().unwrap()));
Next::write()
}

fn on_response_writable(&mut self, encoder: &mut HyperEncoder<HttpStream>) -> Next {
match encoder.try_write(&self.buffer[self.write_pos..]) {
Ok(Some(n)) => {
if (self.write_pos + n) == self.buffer.len() {
Next::end()
} else {
// a partial write
self.write_pos += n;
Next::write()
}
}
Ok(None) => Next::write(),
Err(_) => Next::remove(),
}
}
}
Loading