Skip to content
Browse files

Fix logging, add option handling

This commit address an issue and adds a feature

Issue

When the switch to lager was made a bug was introduced where
initialization of basho bench could fail before lager is started.
Specifically, if a malformed config was passed basho bench would exit
with no indication as to why.  This was because the config was read
for `test_dir` to determine where to write the log files but lager
cannot start until the log file locations are determined.  Thus a
chicken-egg problem.  This commit changes that behavior, pulling the
test_dir (now called results_dir) from command line options.

Feature

In order to pass the results_dir as a command line option I thought it
would be best to add proper argument handling in the form of getopt.
In addition to the `-d` option I also added `--bench-name`.  By
default basho bench stores the results of a run under a directory with
the current iso8601 timestamp.  This is a great default but many times
I want to name the results of a run for posterity and this required an
extra copy operation afterwards.  The `-n` option allows you to name a
test run which will also be used as the name of the directory.  By
default basho bench will act as it did before but the `-d` and `-n`
options give you more control on where to store results.
  • Loading branch information...
1 parent b96f16f commit be7093151c4167fc156dfbb967c9a0fbc3ad6b41 @rzezeski rzezeski committed Nov 9, 2012
Showing with 62 additions and 35 deletions.
  1. +1 −0 include/basho_bench.hrl
  2. +4 −2 rebar.config
  3. +57 −33 src/basho_bench.erl
View
1 include/basho_bench.hrl
@@ -1,5 +1,6 @@
-define(FAIL_MSG(Str, Args), ?ERROR(Str, Args), halt(1)).
+-define(STD_ERR(Str, Args), io:format(standard_error, Str, Args)).
-define(CONSOLE(Str, Args), lager:info(Str, Args)).
View
6 rebar.config
@@ -23,13 +23,15 @@
{riakc, ".*",
{git, "git://github.com/basho/riak-erlang-client", {tag, "1.2.1"}}},
{mochiweb, "1.5.1",
- {git, "git://github.com/basho/mochiweb", {tag, "1.5.1-riak-1.0.x-fixes"}}}
+ {git, "git://github.com/basho/mochiweb", {tag, "1.5.1-riak-1.0.x-fixes"}}},
+ {getopt, ".*",
+ {git, "git://github.com/jcomellas/getopt", {tag, "v0.4"}}}
]}.
{erl_opts, [{src_dirs, [src]},
{parse_transform, lager_transform}]}.
-{escript_incl_apps, [lager, bear, folsom, ibrowse, riakc, mochiweb, protobuffs ]}.
+{escript_incl_apps, [lager, getopt, bear, folsom, ibrowse, riakc, mochiweb, protobuffs ]}.
%% Uncomment to use the Java client bench driver
%% {escript_emu_args, "%%! -name bb@127.0.0.1 -setcookie YOUR_ERLANG_COOKIE\n"}.
View
90 src/basho_bench.erl
@@ -2,7 +2,7 @@
%%
%% basho_bench: Benchmarking Suite
%%
-%% Copyright (c) 2009-2010 Basho Techonologies
+%% Copyright (c) 2009-2012 Basho Techonologies
%%
%% This file is provided to you under the Apache License,
%% Version 2.0 (the "License"); you may not use this file
@@ -29,33 +29,25 @@
%% API
%% ====================================================================
-main([]) ->
- io:format("Usage: basho_bench CONFIG_FILE ..~n");
+cli_options() ->
+ [
+ {help, $h, "help", undefined, "Print usage"},
+ {results_dir, $d, "results-dir", string, "Base directory to store test results, defaults to ./tests"},
+ {bench_name, $n, "bench-name", string, "Name to identify the run, defaults to timestamp"}
+ ].
+
+main(Args) ->
+ {Opts, Configs} = check_args(getopt:parse(cli_options(), Args)),
+ ok = maybe_show_usage(Opts),
+ BenchName = bench_name(Opts),
+ TestDir = test_dir(Opts, BenchName),
-main(Configs) ->
- %% Load baseline configs
ok = application:load(basho_bench),
register(basho_bench, self()),
+ basho_bench_config:set(test_id, BenchName),
- %% Load the config files
- basho_bench_config:load(Configs),
-
- %% Setup working directory for this test. All logs, stats, and config
- %% info will be placed here
- %% Define these dirs before Lager starts
- {ok, Cwd} = file:get_cwd(),
- TestId = id(),
- TestDir = filename:join([Cwd, basho_bench_config:get(test_dir), TestId]),
- ok = filelib:ensure_dir(filename:join(TestDir, "foobar")),
-
- basho_bench_config:set(test_id, TestId),
-
- %% Start Lager
application:load(lager),
-
- %% Fileoutput
ConsoleLagerLevel = basho_bench_config:get(lager_level, debug),
- filelib:ensure_dir(TestDir),
ErrorLog = filename:join([TestDir, "error.log"]),
ConsoleLog = filename:join([TestDir, "console.log"]),
CrashLog = filename:join([TestDir, "crash.log"]),
@@ -66,9 +58,12 @@ main(Configs) ->
[ {ErrorLog, error, 10485760, "$D0", 5},
{ConsoleLog, debug, 10485760, "$D0", 5} ]} ]),
application:set_env(lager, crash_log, CrashLog),
-
lager:start(),
+ %% Make sure this happens after starting lager or failures wont
+ %% show.
+ basho_bench_config:load(Configs),
+
%% Init code path
add_code_paths(basho_bench_config:get(code_paths, [])),
@@ -81,10 +76,6 @@ main(Configs) ->
load_source_files(SourceDir)
end,
- %% Create a link to the test dir for convenience
- TestLink = filename:join([Cwd, basho_bench_config:get(test_dir), "current"]),
- [] = os:cmd(?FMT("rm -f ~s; ln -sf ~s ~s", [TestLink, TestDir, TestLink])),
-
%% Copy the config into the test dir for posterity
[ begin {ok, _} = file:copy(Config, filename:join(TestDir, filename:basename(Config))) end
|| Config <- Configs ],
@@ -104,13 +95,49 @@ main(Configs) ->
wait_for_stop(Mref, DurationMins).
-
-
-
%% ====================================================================
%% Internal functions
%% ====================================================================
+print_usage() ->
+ getopt:usage(cli_options(), escript:script_name(), "CONFIG_FILE").
+
+check_args({ok, {Opts, Args}}) ->
+ {Opts, Args};
+check_args({error, {Reason, _Data}}) ->
+ ?STD_ERR("Failed to parse arguments: ~p~n", [Reason]),
+ print_usage(),
+ halt(1).
+
+maybe_show_usage(Opts) ->
+ case lists:member(help, Opts) of
+ true ->
+ print_usage(),
+ halt(0);
+ false ->
+ ok
+ end.
+
+bench_name(Opts) ->
+ case proplists:get_value(bench_name, Opts, id()) of
+ "current" ->
+ ?STD_ERR("Cannot use name 'current'~n", []),
+ halt(1);
+ Name ->
+ Name
+ end.
+
+test_dir(Opts, Name) ->
+ {ok, CWD} = file:get_cwd(),
+ DefaultResultsDir = filename:join([CWD, "tests"]),
+ ResultsDir = proplists:get_value(results_dir, Opts, DefaultResultsDir),
+ ResultsDirAbs = filename:absname(ResultsDir),
+ TestDir = filename:join([ResultsDirAbs, Name]),
+ ok = filelib:ensure_dir(filename:join(TestDir, "foobar")),
+ Link = filename:join([ResultsDir, "current"]),
+ [] = os:cmd(?FMT("rm -f ~s; ln -sf ~s ~s", [Link, TestDir, Link])),
+ TestDir.
+
wait_for_stop(Mref, infinity) ->
receive
{'DOWN', Mref, _, _, Info} ->
@@ -131,16 +158,13 @@ wait_for_stop(Mref, DurationMins) ->
?CONSOLE("Test completed after ~p mins.\n", [DurationMins])
end.
-
-
%%
%% Construct a string suitable for use as a unique ID for this test run
%%
id() ->
{{Y, M, D}, {H, Min, S}} = calendar:local_time(),
?FMT("~w~2..0w~2..0w_~2..0w~2..0w~2..0w", [Y, M, D, H, Min, S]).
-
add_code_paths([]) ->
ok;
add_code_paths([Path | Rest]) ->

0 comments on commit be70931

Please sign in to comment.
Something went wrong with that request. Please try again.