emqx_logger_textfmt.erl 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2021-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_logger_textfmt).
  17. -export([format/2]).
  18. -export([check_config/1]).
  19. -export([try_format_unicode/1]).
  20. check_config(X) -> logger_formatter:check_config(X).
  21. format(#{msg := {report, ReportMap}, meta := Meta} = Event, Config) when is_map(ReportMap) ->
  22. ReportList = enrich_report(ReportMap, Meta),
  23. Report =
  24. case is_list_report_acceptable(Meta) of
  25. true ->
  26. ReportList;
  27. false ->
  28. maps:from_list(ReportList)
  29. end,
  30. logger_formatter:format(Event#{msg := {report, Report}}, Config);
  31. format(#{msg := {string, String}} = Event, Config) ->
  32. format(Event#{msg => {"~ts ", [String]}}, Config);
  33. %% trace
  34. format(#{msg := Msg0, meta := Meta} = Event, Config) ->
  35. Msg1 = enrich_client_info(Msg0, Meta),
  36. Msg2 = enrich_mfa(Msg1, Meta),
  37. Msg3 = enrich_topic(Msg2, Meta),
  38. logger_formatter:format(Event#{msg := Msg3}, Config).
  39. is_list_report_acceptable(#{report_cb := Cb}) ->
  40. Cb =:= fun logger:format_otp_report/1 orelse Cb =:= fun logger:format_report/1;
  41. is_list_report_acceptable(_) ->
  42. false.
  43. enrich_report(ReportRaw, Meta) ->
  44. %% clientid and peername always in emqx_conn's process metadata.
  45. %% topic can be put in meta using ?SLOG/3, or put in msg's report by ?SLOG/2
  46. Topic =
  47. case maps:get(topic, Meta, undefined) of
  48. undefined -> maps:get(topic, ReportRaw, undefined);
  49. Topic0 -> Topic0
  50. end,
  51. ClientId = maps:get(clientid, Meta, undefined),
  52. Peer = maps:get(peername, Meta, undefined),
  53. MFA = maps:get(mfa, Meta, undefined),
  54. Line = maps:get(line, Meta, undefined),
  55. Msg = maps:get(msg, ReportRaw, undefined),
  56. %% turn it into a list so that the order of the fields is determined
  57. lists:foldl(
  58. fun
  59. ({_, undefined}, Acc) -> Acc;
  60. (Item, Acc) -> [Item | Acc]
  61. end,
  62. maps:to_list(maps:without([topic, msg, clientid], ReportRaw)),
  63. [
  64. {topic, try_format_unicode(Topic)},
  65. {clientid, try_format_unicode(ClientId)},
  66. {peername, Peer},
  67. {line, Line},
  68. {mfa, mfa(MFA)},
  69. {msg, Msg}
  70. ]
  71. ).
  72. try_format_unicode(undefined) ->
  73. undefined;
  74. try_format_unicode(Char) ->
  75. List =
  76. try
  77. case unicode:characters_to_list(Char) of
  78. {error, _, _} -> error;
  79. {incomplete, _, _} -> error;
  80. Binary -> Binary
  81. end
  82. catch
  83. _:_ ->
  84. error
  85. end,
  86. case List of
  87. error -> io_lib:format("~0p", [Char]);
  88. _ -> List
  89. end.
  90. enrich_mfa({Fmt, Args}, #{mfa := Mfa, line := Line}) when is_list(Fmt) ->
  91. {Fmt ++ " mfa: ~ts line: ~w", Args ++ [mfa(Mfa), Line]};
  92. enrich_mfa(Msg, _) ->
  93. Msg.
  94. enrich_client_info({Fmt, Args}, #{clientid := ClientId, peername := Peer}) when is_list(Fmt) ->
  95. {" ~ts@~ts " ++ Fmt, [ClientId, Peer | Args]};
  96. enrich_client_info({Fmt, Args}, #{clientid := ClientId}) when is_list(Fmt) ->
  97. {" ~ts " ++ Fmt, [ClientId | Args]};
  98. enrich_client_info({Fmt, Args}, #{peername := Peer}) when is_list(Fmt) ->
  99. {" ~ts " ++ Fmt, [Peer | Args]};
  100. enrich_client_info(Msg, _) ->
  101. Msg.
  102. enrich_topic({Fmt, Args}, #{topic := Topic}) when is_list(Fmt) ->
  103. {" topic: ~ts" ++ Fmt, [Topic | Args]};
  104. enrich_topic(Msg, _) ->
  105. Msg.
  106. mfa(undefined) -> undefined;
  107. mfa({M, F, A}) -> [atom_to_list(M), ":", atom_to_list(F), "/" ++ integer_to_list(A)].