From 3eb02e96bc134806a7b432b4002708af90432d33 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Thu, 26 Feb 2009 17:28:25 +0000 Subject: - add descriptions to metrics - move document_* metrics to couch_db module and merge them into database_* metrics git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@748217 13f79535-47bb-0310-9956-ffa450edef68 --- src/couchdb/couch_db.erl | 7 +++- src/couchdb/couch_httpd_db.erl | 18 +++++----- src/couchdb/couch_stats.hrl | 13 +++---- src/couchdb/couch_stats_aggregator.erl | 66 ++++++++++++++++++++++++++++++---- 4 files changed, 82 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/couchdb/couch_db.erl b/src/couchdb/couch_db.erl index d9caa36f..963c834b 100644 --- a/src/couchdb/couch_db.erl +++ b/src/couchdb/couch_db.erl @@ -92,6 +92,7 @@ open_doc(Db, IdOrDocInfo) -> open_doc(Db, IdOrDocInfo, []). open_doc(Db, Id, Options) -> + couch_stats_collector:increment({couchdb, database_reads}), case open_doc_int(Db, Id, Options) of {ok, #doc{deleted=true}=Doc} -> case lists:member(deleted, Options) of @@ -105,6 +106,7 @@ open_doc(Db, Id, Options) -> end. open_doc_revs(Db, Id, Revs, Options) -> + couch_stats_collector:increment({couchdb, database_reads}), [Result] = open_doc_revs_int(Db, [{Id, Revs}], Options), Result. @@ -284,6 +286,7 @@ update_docs(#db{update_pid=UpdatePid}=Db, Docs, Options) -> update_docs(#db{update_pid=UpdatePid}=Db, Docs, Options, true). update_docs(Db, Docs, Options, false) -> + couch_stats_collector:increment({couchdb, database_changes}), DocBuckets = group_alike_docs(Docs), Ids = [Id || [#doc{id=Id}|_] <- DocBuckets], @@ -320,7 +323,9 @@ update_docs(Db, Docs, Options, false) -> write_and_commit(Db, DocBuckets2, Options); update_docs(Db, Docs, Options, true) -> - % go ahead and generate the new revision ids for the documents. + couch_stats_collector:increment({couchdb, database_changes}), + + % go ahead and generate the new revision ids for the documents. Docs2 = lists:map( fun(#doc{id=Id,revs=Revs}=Doc) -> case Id of diff --git a/src/couchdb/couch_httpd_db.erl b/src/couchdb/couch_httpd_db.erl index 78339911..53eff650 100644 --- a/src/couchdb/couch_httpd_db.erl +++ b/src/couchdb/couch_httpd_db.erl @@ -80,7 +80,7 @@ db_req(#httpd{method='POST',path_parts=[DbName]}=Req, Db) -> Doc = couch_doc:from_json_obj(couch_httpd:json_body(Req)), DocId = couch_util:new_uuid(), {ok, NewRev} = couch_db:update_doc(Db, Doc#doc{id=DocId, revs=[]}, []), - couch_stats_collector:increment({httpd, document_creates}), + % couch_stats_collector:increment({httpd, document_creates}), DocUrl = absolute_uri(Req, binary_to_list(<<"/",DbName/binary,"/",DocId/binary>>)), send_json(Req, 201, [{"Location", DocUrl}], {[ @@ -379,7 +379,7 @@ db_doc_req(#httpd{method='DELETE'}=Req, Db, DocId) -> couch_httpd:send_error(Req, 409, <<"missing_rev">>, <<"Document rev/etag must be specified to delete">>); RevToDelete -> - couch_stats_collector:increment({httpd, document_deletes}), + % couch_stats_collector:increment({httpd, document_deletes}), {ok, NewRev} = couch_db:delete_doc(Db, DocId, [RevToDelete]), send_json(Req, 200, {[ {ok, true}, @@ -394,7 +394,7 @@ db_doc_req(#httpd{method='GET'}=Req, Db, DocId) -> open_revs = Revs, options = Options } = parse_doc_query(Req), - couch_stats_collector:increment({httpd, document_reads}), + % couch_stats_collector:increment({httpd, document_reads}), case Revs of [] -> Doc = couch_doc_open(Db, DocId, Rev, Options), @@ -471,10 +471,10 @@ db_doc_req(#httpd{method='PUT'}=Req, Db, DocId) -> end, case extract_header_rev(Req, ExplicitRev) of missing_rev -> - couch_stats_collector:increment({httpd, document_creates}), + % couch_stats_collector:increment({httpd, document_creates}), Revs = []; Rev -> - couch_stats_collector:increment({httpd, document_updates}), + % couch_stats_collector:increment({httpd, document_updates}), Revs = [Rev] end, {ok, NewRev} = couch_db:update_doc(Db, Doc#doc{id=DocId, revs=Revs}, Options), @@ -498,7 +498,7 @@ db_doc_req(#httpd{method='COPY'}=Req, Db, SourceDocId) -> % save new doc {ok, NewTargetRev} = couch_db:update_doc(Db, Doc#doc{id=TargetDocId, revs=TargetRev}, []), - couch_stats_collector:increment({httpd, document_copies}), + % couch_stats_collector:increment({httpd, document_copies}), send_json(Req, 201, [{"Etag", "\"" ++ binary_to_list(NewTargetRev) ++ "\""}], {[ {ok, true}, @@ -525,7 +525,7 @@ db_doc_req(#httpd{method='MOVE'}=Req, Db, SourceDocId) -> #doc{id=SourceDocId, revs=[SourceRev], deleted=true} ], {ok, ResultRevs} = couch_db:update_docs(Db, Docs, []), - couch_stats_collector:increment({httpd, document_moves}), + % couch_stats_collector:increment({httpd, document_moves}), DocResults = lists:zipwith( fun(FDoc, NewRev) -> @@ -629,10 +629,10 @@ db_attachment_req(#httpd{method=Method}=Req, Db, DocId, FileNameParts) Doc = case extract_header_rev(Req, couch_httpd:qs_value(Req, "rev")) of missing_rev -> % make the new doc - couch_stats_collector:increment({httpd, document_creates}), + % couch_stats_collector:increment({httpd, document_creates}), #doc{id=DocId}; Rev -> - couch_stats_collector:increment({httpd, document_updates}), + % couch_stats_collector:increment({httpd, document_updates}), case couch_db:open_doc_revs(Db, DocId, [Rev], []) of {ok, [{ok, Doc0}]} -> Doc0#doc{revs=[Rev]}; {ok, [Error]} -> throw(Error) diff --git a/src/couchdb/couch_stats.hrl b/src/couchdb/couch_stats.hrl index 7b51aa0c..47a9a86f 100644 --- a/src/couchdb/couch_stats.hrl +++ b/src/couchdb/couch_stats.hrl @@ -11,11 +11,12 @@ % the License. -record(aggregates, { - min=0, - max=0, - mean=0.0, + min = 0, + max = 0, + mean = 0.0, variance = 0.0, - stddev=0.0, - count=0, - last=0 + stddev = 0.0, + count = 0, + last = 0, + description }). diff --git a/src/couchdb/couch_stats_aggregator.erl b/src/couchdb/couch_stats_aggregator.erl index 3d3db0ef..2a1e5797 100644 --- a/src/couchdb/couch_stats_aggregator.erl +++ b/src/couchdb/couch_stats_aggregator.erl @@ -23,7 +23,8 @@ time_passed/0, clear_aggregates/1]). -record(state, { - aggregates = [] + aggregates = [], + descriptions = [] }). -define(COLLECTOR, couch_stats_collector). @@ -61,6 +62,7 @@ all() -> init(_) -> ets:new(?MODULE, [named_table, set, protected]), init_timers(), + init_descriptions(), {ok, #state{}}. handle_call({get, Key}, _, State) -> @@ -141,8 +143,8 @@ do_clear_aggregates(Time, #state{aggregates=Stats}) -> end, Stats), #state{aggregates=NewStats}. -%% default Time is 0, which is when CouchDB started get_aggregate(Key, State) -> + %% default Time is 0, which is when CouchDB started get_aggregate(Key, State, '0'). get_aggregate(Key, #state{aggregates=StatsList}, Time) -> Aggregates = case proplists:lookup(Key, StatsList) of @@ -151,11 +153,17 @@ get_aggregate(Key, #state{aggregates=StatsList}, Time) -> {Key, Stats} -> case proplists:lookup(Time, Stats) of none -> #aggregates{}; % empty record again - {Time, Stat} -> Stat + {Time, Stat} -> Stat#aggregates{description=get_description(Key)} end end, Aggregates. +get_description(Key) -> + case ets:lookup(?MODULE, Key) of + [] -> <<"No description yet.">>; + [{_Key, Description}] -> Description + end. + %% updates all aggregates for Key update_aggregates_loop(Key, Values, State, CounterType) -> #state{aggregates=AllStats} = State, @@ -193,7 +201,9 @@ update_aggregates_loop(Key, Values, State, CounterType) -> % put the newly calculated aggregates into State and delete the previous % entry - #state{aggregates=[{Key, NewStats} | proplists:delete(Key, AllStats)]}. + #state{ + aggregates=[{Key, NewStats} | proplists:delete(Key, AllStats)] + }. % does the actual updating of the aggregate record update_aggregates(Value, Stat, CounterType) -> @@ -241,7 +251,7 @@ update_aggregates(Value, Stat, CounterType) -> end. -aggregate_to_json_term(#aggregates{min=Min,max=Max,mean=Mean,stddev=Stddev,count=Count,last=Last}) -> +aggregate_to_json_term(#aggregates{min=Min,max=Max,mean=Mean,stddev=Stddev,count=Count,last=Last,description=Description}) -> {[ % current is redundant, but reads nicer in JSON {current, Last}, @@ -250,7 +260,8 @@ aggregate_to_json_term(#aggregates{min=Min,max=Max,mean=Mean,stddev=Stddev,count {min, Min}, {max, Max}, {stddev, Stddev}, - {resolution, 1} + {resolution, 1}, + {description, Description} ]}. get_stats(Key, State) -> @@ -275,6 +286,49 @@ do_get_all(#state{aggregates=Stats}=State) -> {[{LastMod, {lists:sort(LastVals)}} | LastRestMods]} end. + +init_descriptions() -> + + % ets is probably overkill here, but I didn't manage to keep the + % descriptions in the gen_server state. Which means there is probably + % a bug in one of the handle_call() functions most likely the one that + % handles the time_passed message. But don't tell anyone, the math is + % correct :) -- Jan + + % please keep this in alphabetical order + ets:insert(?MODULE, {{couchdb, database_changes}, <<"Number of times a database was changed">>}), + ets:insert(?MODULE, {{couchdb, database_reads}, <<"Number of times a document was read from a database">>}), + ets:insert(?MODULE, {{couchdb, open_databases}, <<"Number of open databases">>}), + ets:insert(?MODULE, {{couchdb, request_time}, <<"Length of a request inside CouchDB without Mochiweb">>}), + + ets:insert(?MODULE, {{http_status_codes, '200'}, <<"Number of HTTP 200 OK responses">>}), + ets:insert(?MODULE, {{http_status_codes, '201'}, <<"Number of HTTP 201 Created responses">>}), + ets:insert(?MODULE, {{http_status_codes, '202'}, <<"Number of HTTP 202 Accepted responses">>}), + ets:insert(?MODULE, {{http_status_codes, '301'}, <<"Number of HTTP 301 Moved Permanently responses">>}), + ets:insert(?MODULE, {{http_status_codes, '304'}, <<"Number of HTTP 304 Not Modified responses">>}), + ets:insert(?MODULE, {{http_status_codes, '400'}, <<"Number of HTTP 400 Bad Request responses">>}), + ets:insert(?MODULE, {{http_status_codes, '401'}, <<"Number of HTTP 401 Unauthorized responses">>}), + ets:insert(?MODULE, {{http_status_codes, '403'}, <<"Number of HTTP 403 Forbidden responses">>}), + ets:insert(?MODULE, {{http_status_codes, '404'}, <<"Number of HTTP 404 Not Found responses">>}), + ets:insert(?MODULE, {{http_status_codes, '405'}, <<"Number of HTTP 405 Method Not Allowed responses">>}), + ets:insert(?MODULE, {{http_status_codes, '409'}, <<"Number of HTTP 409 Conflict responses">>}), + ets:insert(?MODULE, {{http_status_codes, '412'}, <<"Number of HTTP 412 Precondition Failed responses">>}), + ets:insert(?MODULE, {{http_status_codes, '500'}, <<"Number of HTTP 500 Internal Server Error responses">>}), + + ets:insert(?MODULE, {{httpd, bulk_requests}, <<"Number of bulk requests">>}), + ets:insert(?MODULE, {{httpd, copy_requests}, <<"Number of HTTP COPY requests">>}), + ets:insert(?MODULE, {{httpd, delete_requests}, <<"Number of HTTP DELETE requests">>}), + ets:insert(?MODULE, {{httpd, get_requests}, <<"Number of HTTP GET requests">>}), + ets:insert(?MODULE, {{httpd, head_requests}, <<"Number of HTTP HEAD requests">>}), + ets:insert(?MODULE, {{httpd, move_requests}, <<"Number of HTTP MOVE requests">>}), + ets:insert(?MODULE, {{httpd, post_requests}, <<"Number of HTTP POST requests">>}), + ets:insert(?MODULE, {{httpd, requests}, <<"Number of HTTP requests">>}), + ets:insert(?MODULE, {{httpd, temporary_view_reads}, <<"Number of temporary view reads">>}), + ets:insert(?MODULE, {{httpd, view_reads}, <<"Number of view reads">>}), + ets:insert(?MODULE, {{httpd, put_requests}, <<"Number of HTTP PUT requests">>}). + % please keep this in alphabetical order + + % Timer init_timers() -> -- cgit v1.2.3