Permalink
Browse files

Ephemeral statistics

  • Loading branch information...
1 parent ef9d677 commit f0393aa118419f5a07704e657be97d6d7e9b62f2 @MasseR committed May 3, 2013
Showing with 132 additions and 0 deletions.
  1. +1 −0 src/minecraft_app.erl
  2. +8 −0 src/minecraft_web.erl
  3. +73 −0 src/statistics_srv.erl
  4. +50 −0 src/statistics_sup.erl
@@ -16,6 +16,7 @@ start(_Type, _StartArgs) ->
minecraft_deps:ensure(),
itemstats_sup:start_link(),
iteminfo_sup:start_link(),
+ statistics_sup:start_link(),
minecraft_sup:start_link().
%% @spec stop(_State) -> ServerRet
@@ -23,26 +23,31 @@ stop() ->
loop(Req, _DocRoot) ->
Path = Req:get(path),
Method = Req:get(method),
+ statistics_srv:record_request(),
mc_response(Method, Path, Req).
mc_response('GET', "/itemstats/get/" ++ Key, Req) ->
+ statistics_srv:read(),
Req:ok({"text/plain", integer_to_list(itemstats_srv:value(Key))});
% This part of the API is supposed to be called by lua which doesn't support put
mc_response('POST', "/itemstats/set/" ++ Key, Req) ->
+ statistics_srv:write(),
Count = list_to_integer(binary_to_list(Req:recv_body())),
case string:tokens(Key, "/") of
[ TurtleId, RealKey ] -> itemstats_srv:set(RealKey, TurtleId, Count);
[ RealKey ] -> itemstats_srv:set(RealKey, Count)
end,
Req:ok({"text/plain", "ok"});
mc_response('POST', "/itemstats/inc/" ++ Key, Req) ->
+ statistics_srv:write(),
Count = list_to_integer(binary_to_list(Req:recv_body())),
case string:tokens(Key, "/") of
[ TurtleId, RealKey ] -> itemstats_srv:increment(RealKey, TurtleId, Count);
[ RealKey ] -> itemstats_srv:increment(RealKey, Count)
end,
Req:ok({"text/plain", "ok"});
mc_response('POST', "/itemstats/dec/" ++ Key, Req) ->
+ statistics_srv:write(),
Count = list_to_integer(binary_to_list(Req:recv_body())),
case string:tokens(Key, "/") of
[ TurtleId, RealKey ] -> itemstats_srv:decrement(RealKey, TurtleId, Count);
@@ -51,11 +56,14 @@ mc_response('POST', "/itemstats/dec/" ++ Key, Req) ->
Req:ok({"text/plain", "ok"});
% Regular api
mc_response('GET', "/iteminfo/name/" ++ Key, Req) ->
+ statistics_srv:read(),
{"name", Name} = proplists:lookup("name", iteminfo_srv:get_item(Key)),
Req:ok({"text/plain", Name});
mc_response('GET', "/iteminfo/full/" ++ Key, Req) ->
+ statistics_srv:read(),
Req:ok({"text/json", mochijson2:encode([{K, list_to_binary(V)} || {K, V} <-iteminfo_srv:get_item(Key)])});
mc_response('PUT', "/iteminfo/set/" ++ Key, Req) ->
+ statistics_srv:write(),
iteminfo_srv:set_item(Key, mochiweb_util:parse_qs(Req:recv_body())),
Req:ok({"text/plain", "ok"});
mc_response(_Method, _Path, Req) ->
@@ -0,0 +1,73 @@
+-module(statistics_srv).
+
+-behaviour(gen_server).
+
+-export([start_link/0, uptime/0, complete_requests/0, writes/0, reads/0, write/0, read/0, record_request/0]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
+
+-record(state, {started, requests=0, reads=0, writes=0}).
+
+%% API
+
+write() ->
+ gen_server:cast(?MODULE, {write}).
+
+read() ->
+ gen_server:cast(?MODULE, {read}).
+
+record_request() ->
+ gen_server:cast(?MODULE, {request}).
+
+uptime() ->
+ gen_server:call(?MODULE, {uptime}).
+
+complete_requests() ->
+ gen_server:call(?MODULE, {complete_requests}).
+
+writes() ->
+ gen_server:call(?MODULE, {writes}).
+
+reads() ->
+ gen_server:call(?MODULE, {reads}).
+
+%% gen_server API
+start_link() ->
+ gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
+
+init([]) ->
+ {ok, #state{started=calendar:universal_time()}}.
+
+handle_call({uptime}, _From, State) ->
+ {reply, calendar:time_difference(State#state.started, calendar:universal_time()), State};
+handle_call({complete_requests}, _From, State) ->
+ {reply, State#state.requests, State};
+handle_call({reads}, _From, State) ->
+ {reply, State#state.reads, State};
+handle_call({writes}, _From, State) ->
+ {reply, State#state.writes, State};
+handle_call(_Request, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast({write}, State) ->
+ #state{writes=Writes} = State, Writes,
+ {noreply, State#state{writes = Writes+1}};
+handle_cast({read}, State) ->
+ #state{reads=Reads} = State, Reads,
+ {noreply, State#state{reads = Reads+1}};
+handle_cast({request}, State) ->
+ #state{requests=Req} = State, Req,
+ {noreply, State#state{requests = Req+1}};
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldSvn, State, _Extra) ->
+ {ok, State}.
+
+%% Internal API
+
@@ -0,0 +1,50 @@
+-module(statistics_sup).
+
+-behaviour(supervisor).
+
+%% API
+-export([start_link/0]).
+
+%% Supervisor callbacks
+-export([init/1]).
+
+-define(CHILD(Id, Mod, Type, Args), {Id, {Mod, start_link, Args},
+ permanent, 5000, Type, [Mod]}).
+
+%%%===================================================================
+%%% API functions
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @doc
+%% Starts the supervisor
+%%
+%% @spec start_link() -> {ok, Pid} | ignore | {error, Error}
+%% @end
+%%--------------------------------------------------------------------
+start_link() ->
+ supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+
+%%%===================================================================
+%%% Supervisor callbacks
+%%%===================================================================
+
+%%--------------------------------------------------------------------
+%% @private
+%% @doc
+%% Whenever a supervisor is started using supervisor:start_link/[2,3],
+%% this function is called by the new process to find out about
+%% restart strategy, maximum restart frequency and child
+%% specifications.
+%%
+%% @spec init(Args) -> {ok, {SupFlags, [ChildSpec]}} |
+%% ignore |
+%% {error, Reason}
+%% @end
+%%--------------------------------------------------------------------
+init([]) ->
+ {ok, {{one_for_one, 5, 10}, [?CHILD('statistics_srv', 'statistics_srv', worker, [])]}}.
+
+%%%===================================================================
+%%% Internal functions
+%%%===================================================================

0 comments on commit f0393aa

Please sign in to comment.