{"action":"created","comment":{"url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/comments/76369543","id":76369543,"diff_hunk":"@@ -0,0 +1,349 @@\n+// Copyright 2014 The Prometheus Authors\n+// Copyright 2016 PingCAP, Inc.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+use std::convert::From;\n+use std::sync::{Arc, RwLock};\n+use std::collections::HashMap;\n+\n+use protobuf::RepeatedField;\n+use proto;\n+use desc::Desc;\n+use errors::{Result, Error};\n+use value::make_label_pairs;\n+use vec::{MetricVec, MetricVecBuilder};\n+use metrics::{Collector, Metric, Opts};\n+\n+pub const DEFAULT_BUCKETS: &'static [f64; 11] = &[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0,\n+                                                  2.5, 5.0, 10.0];\n+\n+// `BUCKET_LABEL` is used for the label that defines the upper bound of a\n+// bucket of a histogram (\"le\" -> \"less or equal\").\n+pub const BUCKET_LABEL: &'static str = \"le\";\n+\n+#[inline]\n+fn check_bucket_lable(label: &str) -> Result<()> {\n+    if label == BUCKET_LABEL {\n+        return Err(Error::Msg(\"`le` is not allowed as label name in histograms\".to_owned()));\n+    }\n+\n+    Ok(())\n+}\n+\n+/// `HistogramOpts` bundles the options for creating a Histogram metric. It is\n+/// mandatory to set Name and Help to a non-empty string. All other fields are\n+/// optional and can safely be left at their zero value.\n+pub struct HistogramOpts {\n+    pub common_opts: Opts,\n+\n+    // buckets defines the buckets into which observations are counted. Each\n+    // element in the slice is the upper inclusive bound of a bucket. The\n+    // values must be sorted in strictly increasing order. There is no need\n+    // to add a highest bucket with +Inf bound, it will be added\n+    // implicitly. The default value is DefBuckets.\n+    pub buckets: Vec<f64>,\n+}\n+\n+impl HistogramOpts {\n+    pub fn new<S: Into<String>>(name: S, help: S) -> HistogramOpts {\n+        HistogramOpts {\n+            common_opts: Opts::new(name, help),\n+            buckets: Vec::from(DEFAULT_BUCKETS as &'static [f64]),\n+        }\n+    }\n+\n+    pub fn namespace<S: Into<String>>(mut self, namesapce: S) -> Self {\n+        self.common_opts.namespace = namesapce.into();\n+        self\n+    }\n+\n+    pub fn sub_system<S: Into<String>>(mut self, sub_system: S) -> Self {\n+        self.common_opts.sub_system = sub_system.into();\n+        self\n+    }\n+\n+    pub fn const_labels(mut self, labels: HashMap<String, String>) -> Self {\n+        self.common_opts = self.common_opts.const_labels(labels);\n+        self\n+    }\n+\n+    pub fn const_label<S: Into<String>>(mut self, name: S, value: S) -> Self {\n+        self.common_opts = self.common_opts.const_label(name, value);\n+        self\n+    }\n+\n+    pub fn fq_name(&self) -> String {\n+        self.common_opts.fq_name()\n+    }\n+\n+    pub fn buckets(mut self, buckets: Vec<f64>) -> Result<Self> {\n+        // TODO: check buckets order.\n+        self.buckets = buckets;\n+        Ok(self)\n+    }\n+}\n+\n+#[derive(Debug)]\n+struct HistogramCore {\n+    sum: f64,\n+    count: u64,\n+\n+    upper_bounds: Vec<f64>,\n+    counts: Vec<u64>,\n+}\n+\n+impl HistogramCore {\n+    fn new() -> HistogramCore {\n+        HistogramCore::with_buckets(vec![]).unwrap()\n+    }\n+\n+    fn with_buckets(mut buckets: Vec<f64>) -> Result<HistogramCore> {\n+        if buckets.is_empty() {\n+            buckets = Vec::from(DEFAULT_BUCKETS as &'static [f64]);\n+        }\n+\n+        Ok(HistogramCore {\n+            sum: 0.0,\n+            count: 0,\n+            counts: vec![0; buckets.len()],\n+            upper_bounds: buckets,\n+        })\n+    }\n+\n+    fn observe(&mut self, v: f64) {\n+        // Try find the bucket.\n+        let mut iter = self.upper_bounds.iter().enumerate().filter(|&(_, f)| v <= *f);\n+        if let Some((i, _)) = iter.next() {\n+            self.counts[i] += 1;\n+        }\n+\n+        self.count += 1;\n+        self.sum += v;\n+    }\n+\n+    fn proto_histogram(&self) -> proto::Histogram {\n+        let mut h = proto::Histogram::new();\n+        h.set_sample_sum(self.sum);\n+        h.set_sample_count(self.count);\n+\n+        let mut count = 0;\n+        let mut buckets = Vec::with_capacity(self.upper_bounds.len());\n+        for (i, upper_bound) in self.upper_bounds.iter().enumerate() {\n+            count += self.counts[i];\n+            let mut b = proto::Bucket::new();\n+            b.set_cumulative_count(count);\n+            b.set_upper_bound(*upper_bound);\n+            buckets.push(b);\n+        }\n+        h.set_bucket(RepeatedField::from_vec(buckets));\n+\n+        h\n+    }\n+}\n+\n+// A `Histogram` counts individual observations from an event or sample stream in\n+// configurable buckets. Similar to a summary, it also provides a sum of\n+// observations and an observation count.\n+//\n+// On the Prometheus server, quantiles can be calculated from a Histogram using\n+// the histogram_quantile function in the query language.\n+//\n+// Note that Histograms, in contrast to Summaries, can be aggregated with the\n+// Prometheus query language (see the documentation for detailed\n+// procedures). However, Histograms require the user to pre-define suitable\n+// buckets, and they are in general less accurate. The Observe method of a\n+// Histogram has a very low performance overhead in comparison with the Observe\n+// method of a Summary.\n+//\n+// To create Histogram instances, use NewHistogram.\n+#[derive(Clone)]\n+pub struct Histogram {\n+    desc: Desc,\n+    label_pairs: Vec<proto::LabelPair>,\n+\n+    core: Arc<RwLock<HistogramCore>>,\n+}\n+\n+impl Histogram {\n+    pub fn with_opts(opts: HistogramOpts) -> Result<Histogram> {\n+        let desc = try!(Desc::new(opts.fq_name(),\n+                                  opts.common_opts.help.clone(),\n+                                  vec![],\n+                                  opts.common_opts.const_labels.clone()));\n+\n+        Histogram::with_desc(desc, &[])\n+    }\n+\n+    fn with_desc(desc: Desc, label_values: &[&str]) -> Result<Histogram> {\n+        for name in &desc.variable_labels {\n+            try!(check_bucket_lable(&name));\n+        }\n+        for pair in &desc.const_label_pairs {\n+            try!(check_bucket_lable(pair.get_name()));\n+        }\n+\n+        let pairs = make_label_pairs(&desc, label_values);\n+        let core = HistogramCore::new();\n+\n+        Ok(Histogram {\n+            desc: desc,\n+            label_pairs: pairs,\n+\n+            core: Arc::new(RwLock::new(core)),\n+        })\n+    }\n+}\n+\n+impl Histogram {\n+    pub fn observe(&self, v: f64) {\n+        self.core.write().unwrap().observe(v)\n+    }\n+}\n+\n+\n+impl Metric for Histogram {\n+    fn metric(&self) -> proto::Metric {\n+\n+        let mut m = proto::Metric::new();\n+\n+        m.set_label(RepeatedField::from_vec(self.label_pairs.clone()));\n+\n+        let core = self.core.read().unwrap();\n+        let h = core.proto_histogram();\n+        m.set_histogram(h);\n+\n+        m\n+    }\n+}\n+\n+impl Collector for Histogram {\n+    fn desc(&self) -> &Desc {\n+        &self.desc\n+    }\n+\n+    fn collect(&self) -> proto::MetricFamily {\n+        let mut m = proto::MetricFamily::new();\n+        m.set_name(self.desc.fq_name.clone());\n+        m.set_help(self.desc.help.clone());\n+        m.set_field_type(proto::MetricType::HISTOGRAM);\n+        m.set_metric(RepeatedField::from_vec(vec![self.metric()]));\n+        m\n+    }\n+}\n+\n+#[derive(Clone)]\n+pub struct HistogramVecBuilder {}\n+\n+impl MetricVecBuilder for HistogramVecBuilder {\n+    type Output = Histogram;\n+\n+    fn build(&self, desc: &Desc, vals: &[&str]) -> Result<Histogram> {\n+        Histogram::with_desc(desc.clone(), vals)\n+    }\n+}\n+\n+// `HistogramVec` is a Collector that bundles a set of Histograms that all share the\n+// same Desc, but have different values for their variable labels. This is used\n+// if you want to count the same thing partitioned by various dimensions\n+// (e.g. HTTP request latencies, partitioned by status code and method). Create\n+// instances with NewHistogramVec.\n+pub type HistogramVec = MetricVec<HistogramVecBuilder>;\n+\n+impl HistogramVec {\n+    pub fn new(opts: HistogramOpts, label_names: &[&str]) -> Result<HistogramVec> {\n+        let variable_names = label_names.iter().map(|s| (*s).to_owned()).collect();\n+        let desc = try!(Desc::new(opts.fq_name(),\n+                                  opts.common_opts.help,\n+                                  variable_names,\n+                                  opts.common_opts.const_labels));\n+        let metric_vec =\n+            MetricVec::create(desc, proto::MetricType::HISTOGRAM, HistogramVecBuilder {});\n+\n+        Ok(metric_vec as HistogramVec)\n+    }\n+}\n+\n+/// `linear_buckets` creates 'count' buckets, each 'width' wide, where the lowest\n+/// bucket has an upper bound of 'start'. The final +Inf bucket is not counted\n+/// and not included in the returned slice. The returned slice is meant to be\n+/// used for the Buckets field of `HistogramOpts`.\n+///\n+/// The function returns an error if 'count' is zero or negative.\n+pub fn linear_buckets(start: f64, width: f64, count: usize) -> Result<Vec<f64>> {\n+    if count < 1 {\n+        return Err(Error::Msg(\"LinearBuckets needs a positive count\".to_owned()));\n+    }\n+\n+    let mut next = start;\n+    let mut buckets = Vec::with_capacity(count);\n+    for _ in 0..count {\n+        buckets.push(next);\n+        next += width;\n+    }\n+\n+    Ok(buckets)\n+}\n+\n+/// `exponential_buckets` creates 'count' buckets, where the lowest bucket has an\n+/// upper bound of 'start' and each following bucket's upper bound is 'factor'\n+/// times the previous bucket's upper bound. The final +Inf bucket is not counted\n+/// and not included in the returned slice. The returned slice is meant to be\n+/// used for the Buckets field of `HistogramOpts`.\n+///\n+/// The function returns an error if 'count' is 0 or negative, if 'start' is 0\n+/// or negative, or if 'factor' is less than or equal 1.\n+pub fn exponential_buckets(start: f64, factor: f64, count: usize) -> Result<Vec<f64>> {\n+    if count < 1 {\n+        return Err(Error::Msg(\"exponential_buckets needs a positive count\".to_owned()));\n+    }\n+    if start <= 0.0 {\n+        return Err(Error::Msg(\"exponential_buckets needs a positive start value\".to_owned()));\n+    }\n+    if factor <= 1.0 {\n+        return Err(Error::Msg(\"exponential_buckets needs a factor greater than 1\".to_owned()));","path":"src/histogram.rs","position":329,"original_position":313,"commit_id":"7557a4e3fc58f13e96745cf8c703bde831df405b","original_commit_id":"dbff722cba01f114e4c14d6235b93d9bc03bb052","user":{"login":"siddontang","id":1080370,"avatar_url":"https://avatars.githubusercontent.com/u/1080370?v=3","gravatar_id":"","url":"https://api.github.com/users/siddontang","html_url":"https://github.com/siddontang","followers_url":"https://api.github.com/users/siddontang/followers","following_url":"https://api.github.com/users/siddontang/following{/other_user}","gists_url":"https://api.github.com/users/siddontang/gists{/gist_id}","starred_url":"https://api.github.com/users/siddontang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/siddontang/subscriptions","organizations_url":"https://api.github.com/users/siddontang/orgs","repos_url":"https://api.github.com/users/siddontang/repos","events_url":"https://api.github.com/users/siddontang/events{/privacy}","received_events_url":"https://api.github.com/users/siddontang/received_events","type":"User","site_admin":false},"body":"ditto","created_at":"2016-08-26T06:26:31Z","updated_at":"2016-08-26T06:26:31Z","html_url":"https://github.com/pingcap/rust-prometheus/pull/20#discussion_r76369543","pull_request_url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20","_links":{"self":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/comments/76369543"},"html":{"href":"https://github.com/pingcap/rust-prometheus/pull/20#discussion_r76369543"},"pull_request":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20"}}},"pull_request":{"url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20","id":82822121,"html_url":"https://github.com/pingcap/rust-prometheus/pull/20","diff_url":"https://github.com/pingcap/rust-prometheus/pull/20.diff","patch_url":"https://github.com/pingcap/rust-prometheus/pull/20.patch","issue_url":"https://api.github.com/repos/pingcap/rust-prometheus/issues/20","number":20,"state":"open","locked":false,"title":"Add histogram","user":{"login":"overvenus","id":2150711,"avatar_url":"https://avatars.githubusercontent.com/u/2150711?v=3","gravatar_id":"","url":"https://api.github.com/users/overvenus","html_url":"https://github.com/overvenus","followers_url":"https://api.github.com/users/overvenus/followers","following_url":"https://api.github.com/users/overvenus/following{/other_user}","gists_url":"https://api.github.com/users/overvenus/gists{/gist_id}","starred_url":"https://api.github.com/users/overvenus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/overvenus/subscriptions","organizations_url":"https://api.github.com/users/overvenus/orgs","repos_url":"https://api.github.com/users/overvenus/repos","events_url":"https://api.github.com/users/overvenus/events{/privacy}","received_events_url":"https://api.github.com/users/overvenus/received_events","type":"User","site_admin":false},"body":"Resolved #4 \r\n\r\nExperimental support for histogram.\r\n\r\nPTAL @siddontang @disksing @BusyJay","created_at":"2016-08-26T02:12:08Z","updated_at":"2016-08-26T06:26:31Z","closed_at":null,"merged_at":null,"merge_commit_sha":"89b502ba8061ddb7df7bd16d1ed813a843e65731","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20/commits","review_comments_url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20/comments","review_comment_url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pingcap/rust-prometheus/issues/20/comments","statuses_url":"https://api.github.com/repos/pingcap/rust-prometheus/statuses/7557a4e3fc58f13e96745cf8c703bde831df405b","head":{"label":"overvenus:histogram","ref":"histogram","sha":"7557a4e3fc58f13e96745cf8c703bde831df405b","user":{"login":"overvenus","id":2150711,"avatar_url":"https://avatars.githubusercontent.com/u/2150711?v=3","gravatar_id":"","url":"https://api.github.com/users/overvenus","html_url":"https://github.com/overvenus","followers_url":"https://api.github.com/users/overvenus/followers","following_url":"https://api.github.com/users/overvenus/following{/other_user}","gists_url":"https://api.github.com/users/overvenus/gists{/gist_id}","starred_url":"https://api.github.com/users/overvenus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/overvenus/subscriptions","organizations_url":"https://api.github.com/users/overvenus/orgs","repos_url":"https://api.github.com/users/overvenus/repos","events_url":"https://api.github.com/users/overvenus/events{/privacy}","received_events_url":"https://api.github.com/users/overvenus/received_events","type":"User","site_admin":false},"repo":{"id":66003047,"name":"rust-prometheus","full_name":"overvenus/rust-prometheus","owner":{"login":"overvenus","id":2150711,"avatar_url":"https://avatars.githubusercontent.com/u/2150711?v=3","gravatar_id":"","url":"https://api.github.com/users/overvenus","html_url":"https://github.com/overvenus","followers_url":"https://api.github.com/users/overvenus/followers","following_url":"https://api.github.com/users/overvenus/following{/other_user}","gists_url":"https://api.github.com/users/overvenus/gists{/gist_id}","starred_url":"https://api.github.com/users/overvenus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/overvenus/subscriptions","organizations_url":"https://api.github.com/users/overvenus/orgs","repos_url":"https://api.github.com/users/overvenus/repos","events_url":"https://api.github.com/users/overvenus/events{/privacy}","received_events_url":"https://api.github.com/users/overvenus/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/overvenus/rust-prometheus","description":"Prometheus instrumentation library for Rust applications","fork":true,"url":"https://api.github.com/repos/overvenus/rust-prometheus","forks_url":"https://api.github.com/repos/overvenus/rust-prometheus/forks","keys_url":"https://api.github.com/repos/overvenus/rust-prometheus/keys{/key_id}","collaborators_url":"https://api.github.com/repos/overvenus/rust-prometheus/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/overvenus/rust-prometheus/teams","hooks_url":"https://api.github.com/repos/overvenus/rust-prometheus/hooks","issue_events_url":"https://api.github.com/repos/overvenus/rust-prometheus/issues/events{/number}","events_url":"https://api.github.com/repos/overvenus/rust-prometheus/events","assignees_url":"https://api.github.com/repos/overvenus/rust-prometheus/assignees{/user}","branches_url":"https://api.github.com/repos/overvenus/rust-prometheus/branches{/branch}","tags_url":"https://api.github.com/repos/overvenus/rust-prometheus/tags","blobs_url":"https://api.github.com/repos/overvenus/rust-prometheus/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/overvenus/rust-prometheus/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/overvenus/rust-prometheus/git/refs{/sha}","trees_url":"https://api.github.com/repos/overvenus/rust-prometheus/git/trees{/sha}","statuses_url":"https://api.github.com/repos/overvenus/rust-prometheus/statuses/{sha}","languages_url":"https://api.github.com/repos/overvenus/rust-prometheus/languages","stargazers_url":"https://api.github.com/repos/overvenus/rust-prometheus/stargazers","contributors_url":"https://api.github.com/repos/overvenus/rust-prometheus/contributors","subscribers_url":"https://api.github.com/repos/overvenus/rust-prometheus/subscribers","subscription_url":"https://api.github.com/repos/overvenus/rust-prometheus/subscription","commits_url":"https://api.github.com/repos/overvenus/rust-prometheus/commits{/sha}","git_commits_url":"https://api.github.com/repos/overvenus/rust-prometheus/git/commits{/sha}","comments_url":"https://api.github.com/repos/overvenus/rust-prometheus/comments{/number}","issue_comment_url":"https://api.github.com/repos/overvenus/rust-prometheus/issues/comments{/number}","contents_url":"https://api.github.com/repos/overvenus/rust-prometheus/contents/{+path}","compare_url":"https://api.github.com/repos/overvenus/rust-prometheus/compare/{base}...{head}","merges_url":"https://api.github.com/repos/overvenus/rust-prometheus/merges","archive_url":"https://api.github.com/repos/overvenus/rust-prometheus/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/overvenus/rust-prometheus/downloads","issues_url":"https://api.github.com/repos/overvenus/rust-prometheus/issues{/number}","pulls_url":"https://api.github.com/repos/overvenus/rust-prometheus/pulls{/number}","milestones_url":"https://api.github.com/repos/overvenus/rust-prometheus/milestones{/number}","notifications_url":"https://api.github.com/repos/overvenus/rust-prometheus/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/overvenus/rust-prometheus/labels{/name}","releases_url":"https://api.github.com/repos/overvenus/rust-prometheus/releases{/id}","deployments_url":"https://api.github.com/repos/overvenus/rust-prometheus/deployments","created_at":"2016-08-18T14:17:28Z","updated_at":"2016-08-18T14:17:30Z","pushed_at":"2016-08-26T06:13:38Z","git_url":"git://github.com/overvenus/rust-prometheus.git","ssh_url":"git@github.com:overvenus/rust-prometheus.git","clone_url":"https://github.com/overvenus/rust-prometheus.git","svn_url":"https://github.com/overvenus/rust-prometheus","homepage":null,"size":112,"stargazers_count":0,"watchers_count":0,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"pingcap:master","ref":"master","sha":"426eda7b3cfb354db9171951647edbff7e6d89a2","user":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"repo":{"id":65430363,"name":"rust-prometheus","full_name":"pingcap/rust-prometheus","owner":{"login":"pingcap","id":11855343,"avatar_url":"https://avatars.githubusercontent.com/u/11855343?v=3","gravatar_id":"","url":"https://api.github.com/users/pingcap","html_url":"https://github.com/pingcap","followers_url":"https://api.github.com/users/pingcap/followers","following_url":"https://api.github.com/users/pingcap/following{/other_user}","gists_url":"https://api.github.com/users/pingcap/gists{/gist_id}","starred_url":"https://api.github.com/users/pingcap/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pingcap/subscriptions","organizations_url":"https://api.github.com/users/pingcap/orgs","repos_url":"https://api.github.com/users/pingcap/repos","events_url":"https://api.github.com/users/pingcap/events{/privacy}","received_events_url":"https://api.github.com/users/pingcap/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/pingcap/rust-prometheus","description":"Prometheus instrumentation library for Rust applications","fork":false,"url":"https://api.github.com/repos/pingcap/rust-prometheus","forks_url":"https://api.github.com/repos/pingcap/rust-prometheus/forks","keys_url":"https://api.github.com/repos/pingcap/rust-prometheus/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pingcap/rust-prometheus/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pingcap/rust-prometheus/teams","hooks_url":"https://api.github.com/repos/pingcap/rust-prometheus/hooks","issue_events_url":"https://api.github.com/repos/pingcap/rust-prometheus/issues/events{/number}","events_url":"https://api.github.com/repos/pingcap/rust-prometheus/events","assignees_url":"https://api.github.com/repos/pingcap/rust-prometheus/assignees{/user}","branches_url":"https://api.github.com/repos/pingcap/rust-prometheus/branches{/branch}","tags_url":"https://api.github.com/repos/pingcap/rust-prometheus/tags","blobs_url":"https://api.github.com/repos/pingcap/rust-prometheus/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pingcap/rust-prometheus/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pingcap/rust-prometheus/git/refs{/sha}","trees_url":"https://api.github.com/repos/pingcap/rust-prometheus/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pingcap/rust-prometheus/statuses/{sha}","languages_url":"https://api.github.com/repos/pingcap/rust-prometheus/languages","stargazers_url":"https://api.github.com/repos/pingcap/rust-prometheus/stargazers","contributors_url":"https://api.github.com/repos/pingcap/rust-prometheus/contributors","subscribers_url":"https://api.github.com/repos/pingcap/rust-prometheus/subscribers","subscription_url":"https://api.github.com/repos/pingcap/rust-prometheus/subscription","commits_url":"https://api.github.com/repos/pingcap/rust-prometheus/commits{/sha}","git_commits_url":"https://api.github.com/repos/pingcap/rust-prometheus/git/commits{/sha}","comments_url":"https://api.github.com/repos/pingcap/rust-prometheus/comments{/number}","issue_comment_url":"https://api.github.com/repos/pingcap/rust-prometheus/issues/comments{/number}","contents_url":"https://api.github.com/repos/pingcap/rust-prometheus/contents/{+path}","compare_url":"https://api.github.com/repos/pingcap/rust-prometheus/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pingcap/rust-prometheus/merges","archive_url":"https://api.github.com/repos/pingcap/rust-prometheus/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pingcap/rust-prometheus/downloads","issues_url":"https://api.github.com/repos/pingcap/rust-prometheus/issues{/number}","pulls_url":"https://api.github.com/repos/pingcap/rust-prometheus/pulls{/number}","milestones_url":"https://api.github.com/repos/pingcap/rust-prometheus/milestones{/number}","notifications_url":"https://api.github.com/repos/pingcap/rust-prometheus/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pingcap/rust-prometheus/labels{/name}","releases_url":"https://api.github.com/repos/pingcap/rust-prometheus/releases{/id}","deployments_url":"https://api.github.com/repos/pingcap/rust-prometheus/deployments","created_at":"2016-08-11T02:06:25Z","updated_at":"2016-08-22T01:38:33Z","pushed_at":"2016-08-26T06:13:38Z","git_url":"git://github.com/pingcap/rust-prometheus.git","ssh_url":"git@github.com:pingcap/rust-prometheus.git","clone_url":"https://github.com/pingcap/rust-prometheus.git","svn_url":"https://github.com/pingcap/rust-prometheus","homepage":null,"size":132,"stargazers_count":5,"watchers_count":5,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":14,"forks":1,"open_issues":14,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20"},"html":{"href":"https://github.com/pingcap/rust-prometheus/pull/20"},"issue":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/issues/20"},"comments":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/issues/20/comments"},"review_comments":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20/comments"},"review_comment":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/pulls/20/commits"},"statuses":{"href":"https://api.github.com/repos/pingcap/rust-prometheus/statuses/7557a4e3fc58f13e96745cf8c703bde831df405b"}}}}
{"actor":{"display_login":"siddontang"}}