Skip to content

Commit 9bd0a41

Browse files
committed
Support pretty printing records found in a module at compile time
1 parent 8d353aa commit 9bd0a41

File tree

4 files changed

+96
-3
lines changed

4 files changed

+96
-3
lines changed

‎src/lager.erl‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
clear_all_traces/0, stop_trace/1, status/0,
2929
get_loglevel/1, set_loglevel/2, set_loglevel/3, get_loglevels/0,
3030
minimum_loglevel/1, posix_error/1,
31-
safe_format/3, safe_format_chop/3,dispatch_log/5]).
31+
safe_format/3, safe_format_chop/3,dispatch_log/5, pr/2]).
3232

3333
-type log_level() :: debug | info | notice | warning | error | critical | alert | emergency.
3434
-type log_level_number() :: 0..7.
@@ -265,3 +265,33 @@ safe_format(Fmt, Args, Limit, Options) ->
265265
%% @private
266266
safe_format_chop(Fmt, Args, Limit) ->
267267
safe_format(Fmt, Args, Limit, [{chomp, true}]).
268+
269+
%% @doc Print a record lager found during parse transform
270+
pr(Record, Module) when is_tuple(Record), is_atom(element(1, Record)) ->
271+
try Module:module_info(attributes) of
272+
Attrs ->
273+
case lists:keyfind(lager_records, 1, Attrs) of
274+
false ->
275+
Record;
276+
{lager_records, Records} ->
277+
RecordName = element(1, Record),
278+
RecordSize = tuple_size(Record) - 1,
279+
case lists:filter(fun({Name, Fields}) when Name == RecordName,
280+
length(Fields) == RecordSize ->
281+
true;
282+
(_) ->
283+
false
284+
end, Records) of
285+
false ->
286+
Record;
287+
[{RecordName, RecordFields}|_] ->
288+
{'$lager_record', RecordName,
289+
lists:zip(RecordFields, tl(tuple_to_list(Record)))}
290+
end
291+
end
292+
catch
293+
error:undef ->
294+
Record
295+
end;
296+
pr(Record, _) ->
297+
Record.

‎src/lager_transform.erl‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@
3131
parse_transform(AST, Options) ->
3232
TruncSize = proplists:get_value(lager_truncation_size, Options, ?DEFAULT_TRUNCATION),
3333
put(truncation_size, TruncSize),
34+
erlang:put(records, []),
3435
walk_ast([], AST).
3536

3637
walk_ast(Acc, []) ->
37-
lists:reverse(Acc);
38+
insert_record_attribute(Acc);
3839
walk_ast(Acc, [{attribute, _, module, {Module, _PmodArgs}}=H|T]) ->
3940
%% A wild parameterized module appears!
4041
put(module, Module),
@@ -46,6 +47,14 @@ walk_ast(Acc, [{function, Line, Name, Arity, Clauses}|T]) ->
4647
put(function, Name),
4748
walk_ast([{function, Line, Name, Arity,
4849
walk_clauses([], Clauses)}|Acc], T);
50+
walk_ast(Acc, [{attribute, _, record, {Name, Fields}}=H|T]) ->
51+
FieldNames = lists:map(fun({record_field, _, {atom, _, FieldName}}) ->
52+
FieldName;
53+
({record_field, _, {atom, _, FieldName}, _Default}) ->
54+
FieldName
55+
end, Fields),
56+
stash_record({Name, FieldNames}),
57+
walk_ast([H|Acc], T);
4958
walk_ast(Acc, [H|T]) ->
5059
walk_ast([H|Acc], T).
5160

@@ -129,3 +138,19 @@ concat_lists({nil, _Line}, B) ->
129138
B;
130139
concat_lists({cons, Line, Element, Tail}, B) ->
131140
{cons, Line, Element, concat_lists(Tail, B)}.
141+
142+
stash_record(Record) ->
143+
Records = case erlang:get(records) of
144+
undefined ->
145+
[];
146+
R ->
147+
R
148+
end,
149+
erlang:put(records, [Record|Records]).
150+
151+
insert_record_attribute(AST) ->
152+
lists:foldl(fun({attribute, Line, module, _}=E, Acc) ->
153+
[E, {attribute, Line, lager_records, erlang:get(records)}|Acc];
154+
(E, Acc) ->
155+
[E|Acc]
156+
end, [], AST).

‎src/lager_trunc_io.erl‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,11 @@ print(Port, _Max, _Options) when is_port(Port) ->
262262
L = erlang:port_to_list(Port),
263263
{L, length(L)};
264264

265+
print({'$lager_record', Name, Fields}, Max, Options) ->
266+
Leader = "#" ++ atom_to_list(Name) ++ "{",
267+
{RC, Len} = record_fields(Fields, Max - length(Leader) + 1, dec_depth(Options)),
268+
{[Leader, RC, "}"], Len + length(Leader) + 1};
269+
265270
print(Tuple, Max, Options) when is_tuple(Tuple) ->
266271
{TC, Len} = tuple_contents(Tuple, Max-2, Options),
267272
{[${, TC, $}], Len + 2};
@@ -436,6 +441,23 @@ escape($\f) -> "\\f";
436441
escape($\b) -> "\\b";
437442
escape($\v) -> "\\v".
438443

444+
record_fields([], _, _) ->
445+
{"", 0};
446+
record_fields(_, Max, #print_options{depth=D}) when Max < 4; D == 0 ->
447+
{"...", 3};
448+
record_fields([{Field, Value}|T], Max, Options) ->
449+
{ExtraChars, Terminator} = case T of
450+
[] ->
451+
{1, []};
452+
_ ->
453+
{2, ","}
454+
end,
455+
{FieldStr, FieldLen} = print(Field, Max - ExtraChars, Options),
456+
{ValueStr, ValueLen} = print(Value, Max - (FieldLen + ExtraChars), Options),
457+
{Final, FLen} = record_fields(T, Max - (FieldLen + ValueLen + ExtraChars), dec_depth(Options)),
458+
{[FieldStr++"="++ValueStr++Terminator|Final], FLen + FieldLen + ValueLen + ExtraChars}.
459+
460+
439461
-ifdef(TEST).
440462
%%--------------------
441463
%% The start of a test suite. So far, it only checks for not crashing.

‎test/lager_test_backend.erl‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
-ifdef(TEST).
3030
-include_lib("eunit/include/eunit.hrl").
31-
-export([pop/0, count/0, count_ignored/0, flush/0]).
31+
-export([pop/0, count/0, count_ignored/0, flush/0, print_state/0]).
3232
-endif.
3333

3434
init(Level) ->
@@ -51,6 +51,10 @@ handle_call(get_loglevel, #state{level=Level} = State) ->
5151
{ok, Level, State};
5252
handle_call({set_loglevel, Level}, State) ->
5353
{ok, ok, State#state{level=lager_util:level_to_num(Level)}};
54+
handle_call(print_state, State) ->
55+
spawn(fun() -> lager:info("State ~p", [lager:pr(State, ?MODULE)]) end),
56+
timer:sleep(100),
57+
{ok, ok, State};
5458
handle_call(_Request, State) ->
5559
{ok, ok, State}.
5660

@@ -89,6 +93,9 @@ count_ignored() ->
8993
flush() ->
9094
gen_event:call(lager_event, ?MODULE, flush).
9195

96+
print_state() ->
97+
gen_event:call(lager_event, ?MODULE, print_state).
98+
9299
has_line_numbers() ->
93100
%% are we R15 or greater
94101
Rel = erlang:system_info(otp_release),
@@ -220,6 +227,15 @@ lager_test_() ->
220227
?assertEqual(1, count()),
221228
ok
222229
end
230+
},
231+
{"record printing works",
232+
fun() ->
233+
print_state(),
234+
{Level, _Time, Message, _Metadata} = pop(),
235+
?assertMatch(Level, lager_util:level_to_num(info)),
236+
?assertEqual("State #state{level=6,buffer=[],ignored=[]}", lists:flatten(Message)),
237+
ok
238+
end
223239
}
224240
]
225241
}.

0 commit comments

Comments
 (0)