summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Sun <tony.sun427@gmail.com>2021-03-10 22:03:34 -0800
committerTony Sun <tony.sun427@gmail.com>2021-04-13 11:17:37 -0700
commit4e5df74bf6e6d66bd8efe860d178e0bd23c4e3ed (patch)
tree0e2edb2d5c10c3a1bbe00054563ac852717cd91d
parent2ae47756f9add96080e0e257e6cea31f9f074841 (diff)
downloadcouchdb-4e5df74bf6e6d66bd8efe860d178e0bd23c4e3ed.tar.gz
add configurable http server
We add an option to spawn a new mochiweb_http server to allow for an additional port for scraping which does not require authentication. The default ports are 17986, 27986, 37986 across 3 nodes.
-rwxr-xr-xdev/run7
-rw-r--r--rel/overlay/etc/default.ini5
-rw-r--r--setup_eunit.template1
-rw-r--r--src/couch_prometheus/src/couch_prometheus.app.src2
-rw-r--r--src/couch_prometheus/src/couch_prometheus.hrl3
-rw-r--r--src/couch_prometheus/src/couch_prometheus_http.erl88
-rw-r--r--src/couch_prometheus/src/couch_prometheus_server.erl12
-rw-r--r--src/couch_prometheus/src/couch_prometheus_sup.erl8
8 files changed, 116 insertions, 10 deletions
diff --git a/dev/run b/dev/run
index 46759f4f1..9aa95ca6d 100755
--- a/dev/run
+++ b/dev/run
@@ -287,7 +287,8 @@ def check_boot_script(ctx):
@log("Prepare configuration files")
def setup_configs(ctx):
for idx, node in enumerate(ctx["nodes"]):
- cluster_port, backend_port = get_ports(ctx, idx + ctx["node_number"])
+ cluster_port, backend_port, prometheus_port = get_ports(ctx,
+ idx + ctx["node_number"])
env = {
"prefix": toposixpath(ctx["rootdir"]),
"package_author_name": "The Apache Software Foundation",
@@ -300,6 +301,7 @@ def setup_configs(ctx):
"node_name": "-name %s@127.0.0.1" % node,
"cluster_port": cluster_port,
"backend_port": backend_port,
+ "prometheus_port": prometheus_port,
"uuid": "fake_uuid_for_dev",
"_default": "",
}
@@ -360,7 +362,8 @@ def apply_config_overrides(ctx, content):
def get_ports(ctx, idnode):
assert idnode
if idnode <= 5 and not ctx["auto_ports"]:
- return ((10000 * idnode) + 5984, (10000 * idnode) + 5986)
+ return ((10000 * idnode) + 5984, (10000 * idnode) + 5986,
+ (10000 * idnode) + 7986)
else:
return tuple(get_available_ports(2))
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini
index 25f3cca37..5bdaef389 100644
--- a/rel/overlay/etc/default.ini
+++ b/rel/overlay/etc/default.ini
@@ -905,3 +905,8 @@ compaction = false
; The interval in seconds of how often the expiration check runs.
;cache_expiration_check_sec = 10
+
+[prometheus]
+additional_port = true
+bind_address = 127.0.0.1
+port = {{prometheus_port}} \ No newline at end of file
diff --git a/setup_eunit.template b/setup_eunit.template
index 97bee466c..3625441bd 100644
--- a/setup_eunit.template
+++ b/setup_eunit.template
@@ -2,6 +2,7 @@
{package_author_name, "The Apache Software Foundation"},
{cluster_port, 5984},
{backend_port, 5986},
+ {prometheus_port, 17986},
{node_name, "-name couchdbtest@127.0.0.1"},
{data_dir, "/tmp"},
diff --git a/src/couch_prometheus/src/couch_prometheus.app.src b/src/couch_prometheus/src/couch_prometheus.app.src
index 3080b2908..bf49e59d2 100644
--- a/src/couch_prometheus/src/couch_prometheus.app.src
+++ b/src/couch_prometheus/src/couch_prometheus.app.src
@@ -14,7 +14,7 @@
{description, "Aggregated metrics info for Prometheus consumption"},
{vsn, git},
{registered, []},
- {applications, [kernel, stdlib, folsom, couch_stats]},
+ {applications, [kernel, stdlib, folsom, couch_stats, couch_log]},
{mod, {couch_prometheus_app, []}},
{env, []}
]}.
diff --git a/src/couch_prometheus/src/couch_prometheus.hrl b/src/couch_prometheus/src/couch_prometheus.hrl
index e82fb90cb..383dbfeab 100644
--- a/src/couch_prometheus/src/couch_prometheus.hrl
+++ b/src/couch_prometheus/src/couch_prometheus.hrl
@@ -10,4 +10,5 @@
% License for the specific language governing permissions and limitations under
% the License.
--define(REFRESH_INTERVAL, 60).
+-define(REFRESH_INTERVAL, 5).
+
diff --git a/src/couch_prometheus/src/couch_prometheus_http.erl b/src/couch_prometheus/src/couch_prometheus_http.erl
new file mode 100644
index 000000000..4edb53886
--- /dev/null
+++ b/src/couch_prometheus/src/couch_prometheus_http.erl
@@ -0,0 +1,88 @@
+-module(couch_prometheus_http).
+
+-compile(tuple_calls).
+
+-export([
+ start_link/0,
+ handle_request/1
+]).
+
+-include("couch_prometheus.hrl").
+-include_lib("couch/include/couch_db.hrl").
+
+start_link() ->
+ IP = case config:get("prometheus", "bind_address", "any") of
+ "any" -> any;
+ Else -> Else
+ end,
+ Port = config:get("prometheus", "port"),
+ ok = couch_httpd:validate_bind_address(IP),
+
+ Options = [
+ {name, ?MODULE},
+ {loop, fun ?MODULE:handle_request/1},
+ {ip, IP},
+ {port, Port}
+ ],
+ case mochiweb_http:start(Options) of
+ {ok, Pid} ->
+ {ok, Pid};
+ {error, Reason} ->
+ io:format("Failure to start Mochiweb: ~s~n", [Reason]),
+ {error, Reason}
+ end.
+
+handle_request(MochiReq) ->
+ RawUri = MochiReq:get(raw_path),
+ {"/" ++ Path, _, _} = mochiweb_util:urlsplit_path(RawUri),
+ PathParts = string:tokens(Path, "/"), try
+ case PathParts of
+ ["_node", Node, "_prometheus"] ->
+ send_prometheus(MochiReq, Node);
+ _ ->
+ send_error(MochiReq, 404, <<"not_found">>, <<>>)
+ end
+ catch T:R ->
+ Body = list_to_binary(io_lib:format("~p:~p", [T, R])),
+ send_error(MochiReq, 500, <<"server_error">>, Body)
+ end.
+
+send_prometheus(MochiReq, Node) ->
+ Headers = couch_httpd:server_header() ++ [
+ {<<"Content-Type">>, <<"text/plain">>}
+ ],
+ Body = call_node(Node, couch_prometheus_server, scrape, []),
+ send_resp(MochiReq, 200, Headers, Body).
+
+send_resp(MochiReq, Status, ExtraHeaders, Body) ->
+ Headers = couch_httpd:server_header() ++ ExtraHeaders,
+ MochiReq:respond({Status, Headers, Body}).
+
+send_error(MochiReq, Code, Error, Reason) ->
+ Headers = couch_httpd:server_header() ++ [
+ {<<"Content-Type">>, <<"application/json">>}
+ ],
+ JsonError = {[{<<"error">>, Error},
+ {<<"reason">>, Reason}]},
+ Body = ?JSON_ENCODE(JsonError),
+ MochiReq:respond({Code, Headers, Body}).
+
+call_node("_local", Mod, Fun, Args) ->
+ call_node(node(), Mod, Fun, Args);
+call_node(Node0, Mod, Fun, Args) when is_list(Node0) ->
+ Node1 = try
+ list_to_existing_atom(Node0)
+ catch
+ error:badarg ->
+ NoNode = list_to_binary(Node0),
+ throw({not_found, <<"no such node: ", NoNode/binary>>})
+ end,
+ call_node(Node1, Mod, Fun, Args);
+call_node(Node, Mod, Fun, Args) when is_atom(Node) ->
+ case rpc:call(Node, Mod, Fun, Args) of
+ {badrpc, nodedown} ->
+ Reason = list_to_binary(io_lib:format("~s is down", [Node])),
+ throw({error, {nodedown, Reason}});
+ Else ->
+ Else
+ end.
diff --git a/src/couch_prometheus/src/couch_prometheus_server.erl b/src/couch_prometheus/src/couch_prometheus_server.erl
index a0accba99..753e95351 100644
--- a/src/couch_prometheus/src/couch_prometheus_server.erl
+++ b/src/couch_prometheus/src/couch_prometheus_server.erl
@@ -21,15 +21,17 @@
]).
-export([
+ scrape/0
+]).
+
+-export([
start_link/0,
init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
code_change/3,
- terminate/2,
-
- scrape/0
+ terminate/2
]).
-include("couch_prometheus.hrl").
@@ -51,7 +53,6 @@ scrape() ->
{ok, Metrics} = gen_server:call(?MODULE, scrape),
Metrics.
-
handle_call(scrape, _from, #st{metrics = Metrics}=State) ->
{reply, {ok, Metrics}, State};
handle_call(refresh, _from, #st{refresh=OldRT} = State) ->
@@ -67,7 +68,8 @@ handle_cast(Msg, State) ->
handle_info(refresh, State) ->
Metrics = refresh_metrics(),
- {noreply, State#st{metrics=Metrics}};
+ RT = update_refresh_timer(),
+ {noreply, State#st{metrics=Metrics, refresh=RT}};
handle_info(Msg, State) ->
{stop, {unknown_info, Msg}, State}.
diff --git a/src/couch_prometheus/src/couch_prometheus_sup.erl b/src/couch_prometheus/src/couch_prometheus_sup.erl
index 09ed45f12..8d8c7e078 100644
--- a/src/couch_prometheus/src/couch_prometheus_sup.erl
+++ b/src/couch_prometheus/src/couch_prometheus_sup.erl
@@ -28,6 +28,12 @@ init([]) ->
{ok, {
{one_for_one, 5, 10}, [
?CHILD(couch_prometheus_server, worker)
- ]
+ ] ++ maybe_start_prometheus_http()
}}.
+maybe_start_prometheus_http() ->
+ case config:get("prometheus", "additional_port", "false") of
+ "false" -> [];
+ "true" -> [?CHILD(couch_prometheus_http, worker)];
+ _ -> []
+ end.