summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/www/script/test/stats.js95
-rw-r--r--src/couchdb/couch_db.erl7
-rw-r--r--src/couchdb/couch_httpd_db.erl18
-rw-r--r--src/couchdb/couch_stats.hrl13
-rw-r--r--src/couchdb/couch_stats_aggregator.erl66
5 files changed, 117 insertions, 82 deletions
diff --git a/share/www/script/test/stats.js b/share/www/script/test/stats.js
index db0c6573..649007dd 100644
--- a/share/www/script/test/stats.js
+++ b/share/www/script/test/stats.js
@@ -86,40 +86,40 @@ couchTests.stats = function(debug) {
}
};
- var document_read_count_tests = {
- 'should increase read document counter when a document is read': function(name) {
+ var database_read_count_tests = {
+ 'should increase database reads counter when a document is read': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
db.save({"_id":"test"});
- var reads = requestStatsTest("httpd", "document_reads").current;
+ var reads = requestStatsTest("couchdb", "database_reads").current;
db.open("test");
- var new_reads = requestStatsTest("httpd", "document_reads").current;
+ var new_reads = requestStatsTest("couchdb", "database_reads").current;
TEquals(reads + 1 , new_reads, name);
},
- 'should not increase read document counter when a non-document is read': function(name) {
+ 'should not increase database read counter when a non-document is read': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
db.save({"_id":"test"});
- var reads = requestStatsTest("httpd", "document_reads").current;
+ var reads = requestStatsTest("couchdb", "database_reads").current;
CouchDB.request("GET", "/");
- var new_reads = requestStatsTest("httpd", "document_reads").current;
+ var new_reads = requestStatsTest("couchdb", "database_reads").current;
TEquals(reads, new_reads, name);
},
- 'should increase read document counter when a document\'s revisions are read': function(name) {
+ 'should increase database read counter when a document\'s revisions are read': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
db.save({"_id":"test"});
- var reads = requestStatsTest("httpd", "document_reads").current;
+ var reads = requestStatsTest("couchdb", "database_reads").current;
db.open("test", {"open_revs":"all"});
- var new_reads = requestStatsTest("httpd", "document_reads").current;
+ var new_reads = requestStatsTest("couchdb", "database_reads").current;
TEquals(reads + 1 , new_reads, name);
}
@@ -208,18 +208,18 @@ couchTests.stats = function(debug) {
};
var document_write_count_tests = {
- 'should increment counter for document creates': function(name) {
+ 'should increment database changes counter for document creates': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
- var creates = requestStatsTest("httpd", "document_creates").current;
+ var creates = requestStatsTest("couchdb", "database_changes").current;
db.save({"a":"1"});
- var new_creates = requestStatsTest("httpd", "document_creates").current;
+ var new_creates = requestStatsTest("couchdb", "database_changes").current;
TEquals(creates + 1, new_creates, name);
},
- 'should not increment counter for document creates when updating a doc': function(name) {
+ 'should increment database changes counter for document updates': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
@@ -227,38 +227,13 @@ couchTests.stats = function(debug) {
var doc = {"_id":"test"};
db.save(doc);
- var creates = requestStatsTest("httpd", "document_creates").current;
+ var updates = requestStatsTest("couchdb", "database_changes").current;
db.save(doc);
- var new_creates = requestStatsTest("httpd", "document_creates").current;
-
- TEquals(creates, new_creates, name);
- },
- 'should increment counter for document updates': function(name) {
- var db = new CouchDB("test_suite_db");
- db.deleteDb();
- db.createDb();
-
- var doc = {"_id":"test"};
- db.save(doc);
-
- var updates = requestStatsTest("httpd", "document_updates").current;
- db.save(doc);
- var new_updates = requestStatsTest("httpd", "document_updates").current;
+ var new_updates = requestStatsTest("couchdb", "database_changes").current;
TEquals(updates + 1, new_updates, name);
},
- 'should not increment counter for document updates when creating a document': function(name) {
- var db = new CouchDB("test_suite_db");
- db.deleteDb();
- db.createDb();
-
- var updates = requestStatsTest("httpd", "document_updates").current;
- db.save({"a":"1"});
- var new_updates = requestStatsTest("httpd", "document_updates").current;
-
- TEquals(updates, new_updates, name);
- },
- 'should increment counter for document deletes': function(name) {
+ 'should increment database changes counter for document deletes': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
@@ -266,13 +241,13 @@ couchTests.stats = function(debug) {
var doc = {"_id":"test"};
db.save(doc);
- var deletes = requestStatsTest("httpd", "document_deletes").current;
+ var deletes = requestStatsTest("couchdb", "database_changes").current;
db.deleteDoc(doc);
- var new_deletes = requestStatsTest("httpd", "document_deletes").current;
+ var new_deletes = requestStatsTest("couchdb", "database_changes").current;
TEquals(deletes + 1, new_deletes, name);
},
- 'should increment the copy counter': function(name) {
+ 'should increment database changes counter for document copies': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
@@ -280,15 +255,15 @@ couchTests.stats = function(debug) {
var doc = {"_id":"test"};
db.save(doc);
- var copies = requestStatsTest("httpd", "document_copies").current;
+ var copies = requestStatsTest("couchdb", "database_changes").current;
CouchDB.request("COPY", "/test_suite_db/test", {
headers: {"Destination":"copy_of_test"}
});
- var new_copies = requestStatsTest("httpd", "document_copies").current;
+ var new_copies = requestStatsTest("couchdb", "database_changes").current;
TEquals(copies + 1, new_copies, name);
},
- 'should increment the move counter': function(name) {
+ 'should increment database changes counter for document moves': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
@@ -296,11 +271,11 @@ couchTests.stats = function(debug) {
var doc = {"_id":"test"};
db.save(doc);
- var moves = requestStatsTest("httpd", "document_moves").current;
+ var moves = requestStatsTest("couchdb", "database_changes").current;
CouchDB.request("MOVE", "/test_suite_db/test?rev=" + doc._rev, {
headers: {"Destination":"move_of_test"}
});
- var new_moves = requestStatsTest("httpd", "document_moves").current;
+ var new_moves = requestStatsTest("couchdb", "database_changes").current;
TEquals(moves + 1, new_moves, name);
},
@@ -318,31 +293,31 @@ couchTests.stats = function(debug) {
TEquals(bulks + 1, new_bulks, name);
},
- 'should increment counter for document creates using POST': function(name) {
+ 'should increment database changes counter for document creates using POST': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
- var creates = requestStatsTest("httpd", "document_creates").current;
+ var creates = requestStatsTest("couchdb", "database_changes").current;
CouchDB.request("POST", "/test_suite_db", {body:'{"a":"1"}'});
- var new_creates = requestStatsTest("httpd", "document_creates").current;
+ var new_creates = requestStatsTest("couchdb", "database_changes").current;
TEquals(creates + 1, new_creates, name);
},
- 'should increment document create counter when adding attachment': function(name) {
+ 'should increment database changes counter when adding attachment': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
- var creates = requestStatsTest("httpd", "document_creates").current;
+ var creates = requestStatsTest("couchdb", "database_changes").current;
CouchDB.request("PUT", "/test_suite_db/bin_doc2/foo2.txt", {
body:"This is no base64 encoded text",
headers:{"Content-Type": "text/plain;charset=utf-8"}
});
- var new_creates = requestStatsTest("httpd", "document_creates").current;
+ var new_creates = requestStatsTest("couchdb", "database_changes").current;
TEquals(creates + 1, new_creates, name);
},
- 'should increment document update counter when adding attachment to existing doc': function(name) {
+ 'should increment database changes counter when adding attachment to existing doc': function(name) {
var db = new CouchDB("test_suite_db");
db.deleteDb();
db.createDb();
@@ -350,12 +325,12 @@ couchTests.stats = function(debug) {
var doc = {_id:"test"};
db.save(doc);
- var updates = requestStatsTest("httpd", "document_updates").current;
+ var updates = requestStatsTest("couchdb", "database_changes").current;
CouchDB.request("PUT", "/test_suite_db/test/foo2.txt?rev=" + doc._rev, {
body:"This is no base64 encoded text",
headers:{"Content-Type": "text/plain;charset=utf-8"}
});
- var new_updates = requestStatsTest("httpd", "document_updates").current;
+ var new_updates = requestStatsTest("couchdb", "database_changes").current;
TEquals(updates + 1, new_updates, name);
}
@@ -428,7 +403,7 @@ couchTests.stats = function(debug) {
var tests = [
open_databases_tests,
request_count_tests,
- document_read_count_tests,
+ database_read_count_tests,
view_read_count_tests,
http_requests_by_method_tests,
document_write_count_tests,
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() ->