Skip to content

Commit

Permalink
New daemon mode, readme update and logging tool.
Browse files Browse the repository at this point in the history
  • Loading branch information
jinnipark committed Dec 1, 2012
1 parent 8974a32 commit 450e72c
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 48 deletions.
23 changes: 13 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
REBAR=./rebar
ERL=erl

node=fubar
app=fubar
APP=fubar

mqtt_port=1883
node=fubar
master=undefined
host=localhost
port=22

# Compile source codes only.
compile:
Expand All @@ -15,27 +16,29 @@ compile:
test: compile
mkdir -p priv/data/$(node)
$(ERL) -pa ebin deps/*/ebin +A 100 +K true +P 1000000 +W w -boot start_sasl \
-sname $(node) -s reloader -s $(app) -mnesia dir '"priv/data/$(node)"' \
-sname $(node) -s reloader -s $(APP) -mnesia dir '"priv/data/$(node)"' \
-env MQTT_PORT $(mqtt_port) -env FUBAR_MASTER $(master)

# Start the program in production mode.
run: compile
mkdir -p priv/data/$(node)
$(ERL) -pa ebin deps/*/ebin +A 100 +K true +P 1000000 +W w -boot start_sasl \
-sname $(node) -s reloader -s $(app) -detached -mnesia dir '"priv/data/$(node)"' \
-env MQTT_PORT $(mqtt_port) -env FUBAR_MASTER $(master)
mkdir -p priv/data
mkdir -p /tmp/
run_erl -daemon /tmp/$(node)/ $(CURDIR)/priv/log/$(node) \
"$(ERL) -pa $(CURDIR)/ebin $(CURDIR)/deps/*/ebin +A 100 +K true +P 1000000 +W w -boot start_sasl \
-sname $(node) -s $(APP) -mnesia dir '\"$(CURDIR)/priv/data/$(node)\"' \
-env MQTT_PORT $(mqtt_port) -env FUBAR_MASTER $(master)"

# Debug running program in production mode.
debug: compile
$(ERL) -pa ebin deps/*/ebin -sname debug -remsh $(node)@`hostname -s`
ssh $(host) -p $(port) -t to_erl /tmp/

# Launch a shell for client.
client: compile
$(ERL) -pa ebin deps/*/ebin +A 100 +K true +P 1000000 +W w -s reloader

# Make a textual log snapshot.
log:
priv/script/dump-log.escript $(node)`date "-sasl-+%Y%m%dT%H%M%S.log"` priv/log/$(node)@`hostname -s`
priv/script/dump-log.escript $(node)

# Perform unit tests.
check: compile
Expand Down
47 changes: 32 additions & 15 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ An MQTT message broker written in erlang targeted to support internet scale appl

Note) If you want to more than one broker node in a computer,
You have to use different node name and listen port as:
$ make test master_node=name@host node=other mqtt_port=1884
$ make test master=name@host node=other mqtt_port=1884

2. Using account control
Modify {auth, undefined} in src/fubar.app.src as {auth, mqtt_account}.
Expand All @@ -55,26 +55,43 @@ An MQTT message broker written in erlang targeted to support internet scale appl
4. Starting a broker in daemon mode
Use 'run' instead of 'test'.
$ make run

Note) You may not start more than one daemon in a machine.

5. Accessing shell of a running daemon
5. Getting a daemon shell
$ make debug

6. Dumping log as a text file
$ make log
If you are debuggin from remote machine (port defaults to ssh 22):
$ make debug host=xxx.xxx.xxx.xxx port=xx

7. Broker state is preserved
6. Broker state is preserved
The broker restores all the state -- accounts, topics and subscriptions - on restart.
To clear this state, do:
$ make reset

7. Dumping logs to text files
SASL logs can be taken as:
$ make log

8. Understanding trace logs
(fubar@host)1> {'PROFILE', <<"c2">>},
{"since origin", <<"c1">>, 2.01} % millisec from c1 to c2
{"since from", <<"t1">>, 1.55} % millisec from t1 to c2
{"since via", <<"t1">>, 1.55} % t1 is the last message handler
Other logs such as trace, error, warning, info and debug can be taken from the shell as:
(fubar@host)1> fubar_log:dump(trace, "trace.log").

9. Changing log level
Uncomment {d, 'DEBUG'} in rebar.config and rebuild everything by:
$ make clean
$ make deps
$ make
8. Log management
Start up log classes can be controlled in the fubar application meta file, src/fubar.app.src.
~ {fubar_log, [{dir, "priv/log"},
~ {max_bytes, 10485760},
~ {max_files, 10},
~ {classes, [trace, error]}
~ ]},

Other log classes - warning, info or debug - can be turned on/off by putting
them in the meta file or at runtime by calling fubar_log:open/1.
(fubar@host)1> fubar_log:open(debug).

After turning a log class on, fubar_log:show/1, fubar_log:hide/1 controls
whether or not to print the log in the shell.
(fubar@host)2> fubar_log:show(debug).
(fubar@host)3> fubar_log:hide(trace).

Without regard to the show/hide status of a log class, logs in the class
are stored in filesystem until fubar_log:close/1 is called.
18 changes: 13 additions & 5 deletions priv/script/dump-log.escript
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
#!/usr/bin/env escript
%% -*- erlang -*-
%%! -sname dump-log
main([Filename, ReportDir]) ->
main([Prefix]) ->
% Find log dir and settings.
application:load(fubar),
Props = fubar:settings(fubar_log),
Dir = filename:join(proplists:get_value(dir, Props), Prefix),
% Dump sasl log.
ok = application:start(sasl),
{ok, _Pid} = rb:start([{report_dir, ReportDir}]),
rb:start_log(Filename),
{ok, _Pid} = rb:start([{report_dir, Dir}]),
{{Y, M, D}, {H, Min, S}} = calendar:universal_time(),
Base = io_lib:format("~s-~4..0B~2..0B~2..0BT~2..0B~2..0B~2..0B-", [Prefix, Y, M, D, H, Min, S]),
rb:start_log(Base++"sasl.log"),
rb:show(),
rb:stop_log();
rb:stop_log(),
rb:stop();
main(_) ->
usage().

usage() ->
io:format("Usage: ~s <filename> <report_dir>~n", [escript:script_name()]),
io:format("Usage: ~s <log_dir> <prefix>~n", [escript:script_name()]),
halt(1).
2 changes: 1 addition & 1 deletion src/fubar.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{fubar_log, [{dir, "priv/log"},
{max_bytes, 10485760},
{max_files, 10},
{classes, [trace, error]}
{classes, [trace, error, warning, info, debug]}
]},
{mqtt_protocol, [{max_packet_size, 4096},
{dispatch, mqtt_server}
Expand Down
3 changes: 2 additions & 1 deletion src/fubar.erl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
start() ->
application:load(?MODULE),
Settings = ?PROPS_TO_RECORD(settings(fubar_log), settings),
Path = filename:join(Settings#settings.dir, io_lib:format("~s", [node()])),
[Name | _] = string:tokens(lists:flatten(io_lib:format("~s", [node()])), "@"),
Path = filename:join(Settings#settings.dir, Name),
ok = filelib:ensure_dir(Path++"/"),
error_logger:add_report_handler(
log_mf_h, log_mf_h:init(Path, Settings#settings.max_bytes, Settings#settings.max_files)),
Expand Down
55 changes: 39 additions & 16 deletions src/fubar_log.erl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
%%
%% Exports
%%
-export([start_link/0, log/3, trace/2, dump/2,
-export([start_link/0, log/3, trace/2, dump/0, dump/2,
open/1, close/1, show/1, hide/1, interval/1, state/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

Expand All @@ -41,7 +41,8 @@
-spec start_link() -> {ok, pid()} | {error, reason()}.
start_link() ->
State = ?PROPS_TO_RECORD(fubar:settings(?MODULE), ?MODULE),
Path = filename:join(State#?MODULE.dir, io_lib:format("~s", [node()])),
[Name | _] = string:tokens(lists:flatten(io_lib:format("~s", [node()])), "@"),
Path = filename:join(State#?MODULE.dir, Name),
ok = filelib:ensure_dir(Path++"/"),
gen_server:start({local, ?MODULE}, ?MODULE, State#?MODULE{dir=Path}, []).

Expand Down Expand Up @@ -71,21 +72,27 @@ trace(Tag, #fubar{id=Id, origin={Origin, T1}, from={From, T2}, via={Via, T3}, pa
{Via, timer:now_diff(Now, T3)/1000}},
{payload, Payload}}).

%% @doc Dump a log class as a text file.
-spec dump(atom(), string()) -> ok.
dump(Class, Path) ->
%% @doc Dump all log classes to text log files.
dump() ->
case state() of
#?MODULE{dir=Dir, classes=Classes} ->
[Name | _] = string:tokens(lists:flatten(io_lib:format("~s", [node()])), "@"),
{{Y, M, D}, {H, Min, S}} = calendar:universal_time(),
Base = io_lib:format("~s-~4..0B~2..0B~2..0BT~2..0B~2..0B~2..0B-",
[Name, Y, M, D, H, Min, S]),
lists:map(fun({Class, _, _}) ->
Filename = io_lib:format("~s~s.log", [Base, Class]),
{Class, catch dump(Dir, Class, lists:flatten(Filename))}
end, Classes);
Error ->
Error
end.

%% @doc Dump a log class to a text log file.
dump(Class, Filename) ->
case state() of
#?MODULE{dir=Dir} ->
case file:open(Path, [write]) of
{ok, File} ->
LogFile = filename:join(Dir, io_lib:format("~s", [Class])),
disk_log:open([{name, Class}, {file, LogFile}]),
consume_log(Class, start, File),
disk_log:close(Class),
file:close(File);
Error1 ->
Error1
end;
dump(Dir, Class, Filename);
Error ->
Error
end.
Expand Down Expand Up @@ -212,12 +219,28 @@ consume_log(Log, Last, Io) ->
null ->
start;
_ ->
Print = fun(Term) -> io:format(Io, "~p~n", [Term]) end,
Print = fun(Term) -> io:format(Io, "~p~n~n", [Term]) end,
lists:foreach(Print, Terms)
end,
consume_log(Log, Current, Io)
end.

dump(Dir, Class, Filename) ->
Path = filename:join(Dir, io_lib:format("~s", [Class])),
case disk_log:open([{name, Class}, {file, Path}, {type, wrap}]) of
{error, Reason} ->
{error, Reason};
_ ->
case file:open(Filename, [write]) of
{ok, File} ->
consume_log(Class, start, File),
file:close(File);
Error1 ->
Error1
end,
disk_log:close(Class)
end.

%%
%% Unit Tests
%%
Expand Down

0 comments on commit 450e72c

Please sign in to comment.