1%% This Source Code Form is subject to the terms of the Mozilla Public 2%% License, v. 2.0. If a copy of the MPL was not distributed with this 3%% file, You can obtain one at https://mozilla.org/MPL/2.0/. 4%% 5%% Copyright (c) 2021 VMware, Inc. or its affiliates. All rights reserved. 6%% 7 8-module(rabbit_logger_text_fmt). 9 10-export([format/2]). 11 12format(#{msg := Msg, meta := Meta} = LogEvent, Config) -> 13 Prefix = format_prefix(LogEvent, Config), 14 Color = pick_color(LogEvent, Config), 15 FormattedMsg = rabbit_logger_fmt_helpers:format_msg(Msg, Meta, Config), 16 prepend_prefix_to_msg_and_add_color( 17 Prefix, Color, FormattedMsg, LogEvent, Config). 18 19format_prefix(LogEvent, #{prefix_format := PrefixFormat} = Config) -> 20 format_prefix(PrefixFormat, LogEvent, Config, []); 21format_prefix(LogEvent, Config) -> 22 %% Default prefix format. 23 format_prefix([time, " [", level, "] ", pid, " "], LogEvent, Config, []). 24 25format_prefix([String | Rest], LogEvent, Config, Prefix) 26 when is_list(String) -> 27 format_prefix(Rest, LogEvent, Config, [String | Prefix]); 28format_prefix([Var | Rest], LogEvent, Config, Prefix) 29 when is_atom(Var) -> 30 String = format_var(Var, LogEvent, Config), 31 format_prefix(Rest, LogEvent, Config, [String | Prefix]); 32format_prefix([], _, _, Prefix) -> 33 lists:reverse(Prefix). 34 35format_var(level, #{level := Level}, Config) -> 36 rabbit_logger_fmt_helpers:format_level(Level, Config); 37format_var(time, #{meta := #{time := Timestamp}}, Config) -> 38 rabbit_logger_fmt_helpers:format_time(Timestamp, Config); 39format_var(Var, #{meta := Meta}, _) -> 40 case maps:get(Var, Meta, undefined) of 41 undefined -> 42 io_lib:format("<unknown ~s>", [Var]); 43 Value -> 44 case io_lib:char_list(Value) of 45 true -> io_lib:format("~s", [Value]); 46 false -> io_lib:format("~p", [Value]) 47 end 48 end. 49 50pick_color(#{level := Level}, #{use_colors := true} = Config) -> 51 ColorStart = level_to_color(Level, Config), 52 ColorEnd = "\033[0m", 53 {ColorStart, ColorEnd}; 54pick_color(_, _) -> 55 {"", ""}. 56 57level_to_color(Level, #{color_esc_seqs := ColorEscSeqs}) -> 58 maps:get(Level, ColorEscSeqs); 59level_to_color(debug, _) -> "\033[38;5;246m"; 60level_to_color(info, _) -> ""; 61level_to_color(notice, _) -> "\033[38;5;87m"; 62level_to_color(warning, _) -> "\033[38;5;214m"; 63level_to_color(error, _) -> "\033[38;5;160m"; 64level_to_color(critical, _) -> "\033[1;37m\033[48;5;20m"; 65level_to_color(alert, _) -> "\033[1;37m\033[48;5;93m"; 66level_to_color(emergency, _) -> "\033[1;37m\033[48;5;196m". 67 68prepend_prefix_to_msg_and_add_color( 69 Prefix, {ColorStart, ColorEnd}, FormattedMsg, LogEvent, Config) -> 70 Lines = split_lines(FormattedMsg, Config), 71 [[ColorStart, 72 format_line(Prefix, Line, LogEvent, Config), 73 ColorEnd, 74 $\n] 75 || Line <- Lines]. 76 77split_lines(FormattedMsg, _) -> 78 FlattenMsg = lists:flatten(FormattedMsg), 79 string:split(FlattenMsg, [$\n], all). 80 81format_line(Prefix, Msg, LogEvent, #{line_format := Format} = Config) -> 82 format_line(Format, Msg, LogEvent, Config, [Prefix]); 83format_line(Prefix, Msg, LogEvent, Config) -> 84 format_line([msg], Msg, LogEvent, Config, [Prefix]). 85 86format_line([msg | Rest], Msg, LogEvent, Config, Line) -> 87 format_line(Rest, Msg, LogEvent, Config, [Msg | Line]); 88format_line([String | Rest], Msg, LogEvent, Config, Line) 89 when is_list(String) -> 90 format_line(Rest, Msg, LogEvent, Config, [String | Line]); 91format_line([Var | Rest], Msg, LogEvent, Config, Line) 92 when is_atom(Var) -> 93 String = format_var(Var, LogEvent, Config), 94 format_line(Rest, Msg, LogEvent, Config, [String | Line]); 95format_line([], _, _, _, Line) -> 96 remove_trailing_whitespaces(Line). 97 98remove_trailing_whitespaces([Tail | Line]) -> 99 Tail1 = string:strip(Tail, right), 100 lists:reverse([Tail1 | Line]). 101