{"action":"created","comment":{"url":"https://api.github.com/repos/brpc/brpc/pulls/comments/239101991","pull_request_review_id":181790055,"id":239101991,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzOTEwMTk5MQ==","diff_hunk":"@@ -0,0 +1,181 @@\n+// Copyright (c) 2018 Bilibili, 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+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+// Authors: Jiashun Zhu(zhujiashun@bilibili.com)\n+\n+#include <vector>\n+#include <iomanip>\n+#include <map>\n+#include \"brpc/controller.h\"                // Controller\n+#include \"brpc/server.h\"                    // Server\n+#include \"brpc/closure_guard.h\"             // ClosureGuard\n+#include \"brpc/builtin/prometheus_metrics_service.h\"\n+#include \"brpc/builtin/common.h\"\n+#include \"bvar/bvar.h\"\n+\n+namespace bvar {\n+DECLARE_int32(bvar_latency_p1);\n+DECLARE_int32(bvar_latency_p2);\n+DECLARE_int32(bvar_latency_p3);\n+}\n+\n+namespace brpc {\n+\n+// This is a class that convert bvar result to prometheus output.\n+// Currently the output only includes gauge and summary for two\n+// reasons:\n+// 1) We cannot tell gauge and counter just from name and what's\n+// more counter is just another gauge.\n+// 2) Histogram and summary is equivalent except that histogram\n+// calculates quantiles in the server side.\n+class PrometheusMetricsDumper : public bvar::Dumper {\n+public:\n+    explicit PrometheusMetricsDumper(butil::IOBufBuilder* os,\n+                                     const std::string& server_prefix)\n+        : _os(os)\n+        , _server_prefix(server_prefix) {\n+    }\n+\n+    bool dump(const std::string& name, const butil::StringPiece& desc) override;\n+\n+private:\n+    DISALLOW_COPY_AND_ASSIGN(PrometheusMetricsDumper);\n+\n+    bool DumpLatencyRecorderSuffix(const butil::StringPiece& name,\n+                                   const butil::StringPiece& desc);\n+\n+    // 6 is the number of bvars in LatencyRecorder that indicating percentiles\n+    static const int NPERCENTILES = 6;\n+\n+    struct SummaryItems {\n+        std::string latency_percentiles[NPERCENTILES];\n+        std::string latency_avg;\n+        std::string count;\n+        std::string metric_name;\n+    };\n+    SummaryItems* ProcessLatencyRecorderSuffix(const butil::StringPiece& name,\n+                                               const butil::StringPiece& desc);\n+\n+private:\n+    butil::IOBufBuilder* _os;\n+    const std::string _server_prefix;\n+    std::map<std::string, SummaryItems> _m;\n+};\n+\n+bool PrometheusMetricsDumper::dump(const std::string& name,\n+                                   const butil::StringPiece& desc) {\n+    if (!desc.empty() && desc[0] == '\"') {\n+        // there is no necessary to monitor string in prometheus\n+        return true;\n+    }\n+    if (DumpLatencyRecorderSuffix(name, desc)) {\n+        // Has encountered name with suffix exposed by LatencyRecorder,\n+        // Leave it to DumpLatencyRecorderSuffix to output Summary.\n+        return true;\n+    }\n+    *_os << \"# HELP \" << name << '\\n'\n+         << \"# TYPE \" << name << \" gauge\" << '\\n'\n+         << name << \" \" << desc << '\\n';\n+    return true;\n+}\n+\n+PrometheusMetricsDumper::SummaryItems*\n+PrometheusMetricsDumper::ProcessLatencyRecorderSuffix(const butil::StringPiece& name,\n+                                                      const butil::StringPiece& desc) {\n+    static std::string latency_names[] = {\n+        butil::string_printf(\"_latency_%d\", (int)bvar::FLAGS_bvar_latency_p1),\n+        butil::string_printf(\"_latency_%d\", (int)bvar::FLAGS_bvar_latency_p2),\n+        butil::string_printf(\"_latency_%d\", (int)bvar::FLAGS_bvar_latency_p3),\n+        \"_latency_999\", \"_latency_9999\", \"_max_latency\"\n+    };\n+    CHECK(NPERCENTILES == arraysize(latency_names));\n+    butil::StringPiece metric_name(name);\n+    for (int i = 0; i < NPERCENTILES; ++i) {\n+        if (!metric_name.ends_with(latency_names[i])) {\n+            continue;\n+        }\n+        metric_name.remove_suffix(latency_names[i].size());\n+        SummaryItems* si = &_m[metric_name.as_string()];\n+        si->latency_percentiles[i] = desc.as_string();\n+        if (i == NPERCENTILES - 1) {\n+            // 'max_latency' is the last suffix name that appear in the sorted bvar\n+            // list, which means all related percentiles have been gathered and we are\n+            // ready to output a Summary.\n+            si->metric_name = metric_name.as_string();\n+            return si;\n+        }\n+        return NULL;\n+    }\n+    // Get the average of latency in recent window size\n+    if (metric_name.ends_with(\"_latency\")) {\n+        metric_name.remove_suffix(8);\n+        _m[metric_name.as_string()].latency_avg = desc.as_string();\n+        return NULL;\n+    }\n+    if (metric_name.ends_with(\"_count\")) {\n+        metric_name.remove_suffix(6);\n+        _m[metric_name.as_string()].count = desc.as_string();\n+        return NULL;\n+    }\n+    return NULL;\n+}\n+\n+bool PrometheusMetricsDumper::DumpLatencyRecorderSuffix(const butil::StringPiece& name,\n+                                                        const butil::StringPiece& desc) {\n+    if (!name.starts_with(_server_prefix)) {\n+        return false;\n+    }\n+    SummaryItems* si = NULL;\n+    if ((si = ProcessLatencyRecorderSuffix(name, desc))) {","path":"src/brpc/builtin/prometheus_metrics_service.cpp","position":140,"original_position":140,"commit_id":"b0fdaf4fc3799934ed4f3db15155016e69b89fe6","original_commit_id":"b0fdaf4fc3799934ed4f3db15155016e69b89fe6","user":{"login":"jamesge","id":6566535,"node_id":"MDQ6VXNlcjY1NjY1MzU=","avatar_url":"https://avatars0.githubusercontent.com/u/6566535?v=4","gravatar_id":"","url":"https://api.github.com/users/jamesge","html_url":"https://github.com/jamesge","followers_url":"https://api.github.com/users/jamesge/followers","following_url":"https://api.github.com/users/jamesge/following{/other_user}","gists_url":"https://api.github.com/users/jamesge/gists{/gist_id}","starred_url":"https://api.github.com/users/jamesge/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamesge/subscriptions","organizations_url":"https://api.github.com/users/jamesge/orgs","repos_url":"https://api.github.com/users/jamesge/repos","events_url":"https://api.github.com/users/jamesge/events{/privacy}","received_events_url":"https://api.github.com/users/jamesge/received_events","type":"User","site_admin":false},"body":"把赋值老老实实写在上一行有多任何行数么？","created_at":"2018-12-05T15:06:10Z","updated_at":"2018-12-05T15:07:38Z","html_url":"https://github.com/brpc/brpc/pull/587#discussion_r239101991","pull_request_url":"https://api.github.com/repos/brpc/brpc/pulls/587","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/brpc/brpc/pulls/comments/239101991"},"html":{"href":"https://github.com/brpc/brpc/pull/587#discussion_r239101991"},"pull_request":{"href":"https://api.github.com/repos/brpc/brpc/pulls/587"}}},"pull_request":{"url":"https://api.github.com/repos/brpc/brpc/pulls/587","id":234951679,"node_id":"MDExOlB1bGxSZXF1ZXN0MjM0OTUxNjc5","html_url":"https://github.com/brpc/brpc/pull/587","diff_url":"https://github.com/brpc/brpc/pull/587.diff","patch_url":"https://github.com/brpc/brpc/pull/587.patch","issue_url":"https://api.github.com/repos/brpc/brpc/issues/587","number":587,"state":"open","locked":false,"title":"Support Prometheus output","user":{"login":"zyearn","id":4475779,"node_id":"MDQ6VXNlcjQ0NzU3Nzk=","avatar_url":"https://avatars1.githubusercontent.com/u/4475779?v=4","gravatar_id":"","url":"https://api.github.com/users/zyearn","html_url":"https://github.com/zyearn","followers_url":"https://api.github.com/users/zyearn/followers","following_url":"https://api.github.com/users/zyearn/following{/other_user}","gists_url":"https://api.github.com/users/zyearn/gists{/gist_id}","starred_url":"https://api.github.com/users/zyearn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zyearn/subscriptions","organizations_url":"https://api.github.com/users/zyearn/orgs","repos_url":"https://api.github.com/users/zyearn/repos","events_url":"https://api.github.com/users/zyearn/events{/privacy}","received_events_url":"https://api.github.com/users/zyearn/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-11-30T11:07:40Z","updated_at":"2018-12-05T15:07:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"fddc31e14c7406140eb48ce97842d0ae32063fe6","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/brpc/brpc/pulls/587/commits","review_comments_url":"https://api.github.com/repos/brpc/brpc/pulls/587/comments","review_comment_url":"https://api.github.com/repos/brpc/brpc/pulls/comments{/number}","comments_url":"https://api.github.com/repos/brpc/brpc/issues/587/comments","statuses_url":"https://api.github.com/repos/brpc/brpc/statuses/b0fdaf4fc3799934ed4f3db15155016e69b89fe6","head":{"label":"zyearn:prometheus","ref":"prometheus","sha":"b0fdaf4fc3799934ed4f3db15155016e69b89fe6","user":{"login":"zyearn","id":4475779,"node_id":"MDQ6VXNlcjQ0NzU3Nzk=","avatar_url":"https://avatars1.githubusercontent.com/u/4475779?v=4","gravatar_id":"","url":"https://api.github.com/users/zyearn","html_url":"https://github.com/zyearn","followers_url":"https://api.github.com/users/zyearn/followers","following_url":"https://api.github.com/users/zyearn/following{/other_user}","gists_url":"https://api.github.com/users/zyearn/gists{/gist_id}","starred_url":"https://api.github.com/users/zyearn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zyearn/subscriptions","organizations_url":"https://api.github.com/users/zyearn/orgs","repos_url":"https://api.github.com/users/zyearn/repos","events_url":"https://api.github.com/users/zyearn/events{/privacy}","received_events_url":"https://api.github.com/users/zyearn/received_events","type":"User","site_admin":false},"repo":{"id":124358748,"node_id":"MDEwOlJlcG9zaXRvcnkxMjQzNTg3NDg=","name":"brpc","full_name":"zyearn/brpc","private":false,"owner":{"login":"zyearn","id":4475779,"node_id":"MDQ6VXNlcjQ0NzU3Nzk=","avatar_url":"https://avatars1.githubusercontent.com/u/4475779?v=4","gravatar_id":"","url":"https://api.github.com/users/zyearn","html_url":"https://github.com/zyearn","followers_url":"https://api.github.com/users/zyearn/followers","following_url":"https://api.github.com/users/zyearn/following{/other_user}","gists_url":"https://api.github.com/users/zyearn/gists{/gist_id}","starred_url":"https://api.github.com/users/zyearn/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zyearn/subscriptions","organizations_url":"https://api.github.com/users/zyearn/orgs","repos_url":"https://api.github.com/users/zyearn/repos","events_url":"https://api.github.com/users/zyearn/events{/privacy}","received_events_url":"https://api.github.com/users/zyearn/received_events","type":"User","site_admin":false},"html_url":"https://github.com/zyearn/brpc","description":"Industrial-grade RPC framework used throughout Baidu, with 1,000,000+ instances and thousands kinds of services, called \"baidu-rpc\" inside Baidu.","fork":true,"url":"https://api.github.com/repos/zyearn/brpc","forks_url":"https://api.github.com/repos/zyearn/brpc/forks","keys_url":"https://api.github.com/repos/zyearn/brpc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zyearn/brpc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zyearn/brpc/teams","hooks_url":"https://api.github.com/repos/zyearn/brpc/hooks","issue_events_url":"https://api.github.com/repos/zyearn/brpc/issues/events{/number}","events_url":"https://api.github.com/repos/zyearn/brpc/events","assignees_url":"https://api.github.com/repos/zyearn/brpc/assignees{/user}","branches_url":"https://api.github.com/repos/zyearn/brpc/branches{/branch}","tags_url":"https://api.github.com/repos/zyearn/brpc/tags","blobs_url":"https://api.github.com/repos/zyearn/brpc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zyearn/brpc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zyearn/brpc/git/refs{/sha}","trees_url":"https://api.github.com/repos/zyearn/brpc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zyearn/brpc/statuses/{sha}","languages_url":"https://api.github.com/repos/zyearn/brpc/languages","stargazers_url":"https://api.github.com/repos/zyearn/brpc/stargazers","contributors_url":"https://api.github.com/repos/zyearn/brpc/contributors","subscribers_url":"https://api.github.com/repos/zyearn/brpc/subscribers","subscription_url":"https://api.github.com/repos/zyearn/brpc/subscription","commits_url":"https://api.github.com/repos/zyearn/brpc/commits{/sha}","git_commits_url":"https://api.github.com/repos/zyearn/brpc/git/commits{/sha}","comments_url":"https://api.github.com/repos/zyearn/brpc/comments{/number}","issue_comment_url":"https://api.github.com/repos/zyearn/brpc/issues/comments{/number}","contents_url":"https://api.github.com/repos/zyearn/brpc/contents/{+path}","compare_url":"https://api.github.com/repos/zyearn/brpc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zyearn/brpc/merges","archive_url":"https://api.github.com/repos/zyearn/brpc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zyearn/brpc/downloads","issues_url":"https://api.github.com/repos/zyearn/brpc/issues{/number}","pulls_url":"https://api.github.com/repos/zyearn/brpc/pulls{/number}","milestones_url":"https://api.github.com/repos/zyearn/brpc/milestones{/number}","notifications_url":"https://api.github.com/repos/zyearn/brpc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zyearn/brpc/labels{/name}","releases_url":"https://api.github.com/repos/zyearn/brpc/releases{/id}","deployments_url":"https://api.github.com/repos/zyearn/brpc/deployments","created_at":"2018-03-08T08:11:24Z","updated_at":"2018-09-29T10:18:01Z","pushed_at":"2018-12-05T09:30:24Z","git_url":"git://github.com/zyearn/brpc.git","ssh_url":"git@github.com:zyearn/brpc.git","clone_url":"https://github.com/zyearn/brpc.git","svn_url":"https://github.com/zyearn/brpc","homepage":"","size":26548,"stargazers_count":3,"watchers_count":3,"language":"C++","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":3,"default_branch":"master"}},"base":{"label":"brpc:master","ref":"master","sha":"dde83f0cd3a70c9f8ac737f0831d3b3af10a4de0","user":{"login":"brpc","id":31610676,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNjEwNjc2","avatar_url":"https://avatars2.githubusercontent.com/u/31610676?v=4","gravatar_id":"","url":"https://api.github.com/users/brpc","html_url":"https://github.com/brpc","followers_url":"https://api.github.com/users/brpc/followers","following_url":"https://api.github.com/users/brpc/following{/other_user}","gists_url":"https://api.github.com/users/brpc/gists{/gist_id}","starred_url":"https://api.github.com/users/brpc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brpc/subscriptions","organizations_url":"https://api.github.com/users/brpc/orgs","repos_url":"https://api.github.com/users/brpc/repos","events_url":"https://api.github.com/users/brpc/events{/privacy}","received_events_url":"https://api.github.com/users/brpc/received_events","type":"Organization","site_admin":false},"repo":{"id":102343794,"node_id":"MDEwOlJlcG9zaXRvcnkxMDIzNDM3OTQ=","name":"brpc","full_name":"brpc/brpc","private":false,"owner":{"login":"brpc","id":31610676,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMxNjEwNjc2","avatar_url":"https://avatars2.githubusercontent.com/u/31610676?v=4","gravatar_id":"","url":"https://api.github.com/users/brpc","html_url":"https://github.com/brpc","followers_url":"https://api.github.com/users/brpc/followers","following_url":"https://api.github.com/users/brpc/following{/other_user}","gists_url":"https://api.github.com/users/brpc/gists{/gist_id}","starred_url":"https://api.github.com/users/brpc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/brpc/subscriptions","organizations_url":"https://api.github.com/users/brpc/orgs","repos_url":"https://api.github.com/users/brpc/repos","events_url":"https://api.github.com/users/brpc/events{/privacy}","received_events_url":"https://api.github.com/users/brpc/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/brpc/brpc","description":"Industrial-grade RPC framework used throughout Baidu, with 1,000,000+ instances and thousands kinds of services, called \"baidu-rpc\" inside Baidu.","fork":false,"url":"https://api.github.com/repos/brpc/brpc","forks_url":"https://api.github.com/repos/brpc/brpc/forks","keys_url":"https://api.github.com/repos/brpc/brpc/keys{/key_id}","collaborators_url":"https://api.github.com/repos/brpc/brpc/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/brpc/brpc/teams","hooks_url":"https://api.github.com/repos/brpc/brpc/hooks","issue_events_url":"https://api.github.com/repos/brpc/brpc/issues/events{/number}","events_url":"https://api.github.com/repos/brpc/brpc/events","assignees_url":"https://api.github.com/repos/brpc/brpc/assignees{/user}","branches_url":"https://api.github.com/repos/brpc/brpc/branches{/branch}","tags_url":"https://api.github.com/repos/brpc/brpc/tags","blobs_url":"https://api.github.com/repos/brpc/brpc/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/brpc/brpc/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/brpc/brpc/git/refs{/sha}","trees_url":"https://api.github.com/repos/brpc/brpc/git/trees{/sha}","statuses_url":"https://api.github.com/repos/brpc/brpc/statuses/{sha}","languages_url":"https://api.github.com/repos/brpc/brpc/languages","stargazers_url":"https://api.github.com/repos/brpc/brpc/stargazers","contributors_url":"https://api.github.com/repos/brpc/brpc/contributors","subscribers_url":"https://api.github.com/repos/brpc/brpc/subscribers","subscription_url":"https://api.github.com/repos/brpc/brpc/subscription","commits_url":"https://api.github.com/repos/brpc/brpc/commits{/sha}","git_commits_url":"https://api.github.com/repos/brpc/brpc/git/commits{/sha}","comments_url":"https://api.github.com/repos/brpc/brpc/comments{/number}","issue_comment_url":"https://api.github.com/repos/brpc/brpc/issues/comments{/number}","contents_url":"https://api.github.com/repos/brpc/brpc/contents/{+path}","compare_url":"https://api.github.com/repos/brpc/brpc/compare/{base}...{head}","merges_url":"https://api.github.com/repos/brpc/brpc/merges","archive_url":"https://api.github.com/repos/brpc/brpc/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/brpc/brpc/downloads","issues_url":"https://api.github.com/repos/brpc/brpc/issues{/number}","pulls_url":"https://api.github.com/repos/brpc/brpc/pulls{/number}","milestones_url":"https://api.github.com/repos/brpc/brpc/milestones{/number}","notifications_url":"https://api.github.com/repos/brpc/brpc/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/brpc/brpc/labels{/name}","releases_url":"https://api.github.com/repos/brpc/brpc/releases{/id}","deployments_url":"https://api.github.com/repos/brpc/brpc/deployments","created_at":"2017-09-04T09:28:47Z","updated_at":"2018-12-05T14:42:06Z","pushed_at":"2018-12-05T14:41:59Z","git_url":"git://github.com/brpc/brpc.git","ssh_url":"git@github.com:brpc/brpc.git","clone_url":"https://github.com/brpc/brpc.git","svn_url":"https://github.com/brpc/brpc","homepage":"","size":26446,"stargazers_count":7841,"watchers_count":7841,"language":"C++","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1785,"mirror_url":null,"archived":false,"open_issues_count":63,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":1785,"open_issues":63,"watchers":7841,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/brpc/brpc/pulls/587"},"html":{"href":"https://github.com/brpc/brpc/pull/587"},"issue":{"href":"https://api.github.com/repos/brpc/brpc/issues/587"},"comments":{"href":"https://api.github.com/repos/brpc/brpc/issues/587/comments"},"review_comments":{"href":"https://api.github.com/repos/brpc/brpc/pulls/587/comments"},"review_comment":{"href":"https://api.github.com/repos/brpc/brpc/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/brpc/brpc/pulls/587/commits"},"statuses":{"href":"https://api.github.com/repos/brpc/brpc/statuses/b0fdaf4fc3799934ed4f3db15155016e69b89fe6"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"jamesge"}}