|
15 | 15 | default_formatter/1,
|
16 | 16 | default_console_formatter/1,
|
17 | 17 | default_file_formatter/1,
|
| 18 | + default_journald_formatter/1, |
18 | 19 | default_syslog_formatter/1,
|
19 | 20 | enable_quick_dbg/1,
|
20 | 21 | use_colored_logging/0,
|
21 | 22 | use_colored_logging/1,
|
22 |
| - translate_formatter_conf/2]). |
| 23 | + translate_formatter_conf/2, |
| 24 | + translate_journald_fields_conf/2]). |
23 | 25 | -export([filter_log_event/2]).
|
24 | 26 |
|
25 | 27 | -ifdef(TEST).
|
@@ -121,6 +123,10 @@ default_console_formatter(Context) ->
|
121 | 123 | default_file_formatter(Context) ->
|
122 | 124 | default_formatter(Context#{output_supports_colors => false}).
|
123 | 125 |
|
| 126 | +default_journald_formatter(_Context) -> |
| 127 | + {rabbit_logger_text_fmt, #{prefix_format => [], |
| 128 | + use_colors => false}}. |
| 129 | + |
124 | 130 | default_syslog_formatter(Context) ->
|
125 | 131 | {Module, Config} = default_file_formatter(Context),
|
126 | 132 | case Module of
|
@@ -155,8 +161,8 @@ enable_quick_dbg(#{dbg_output := Output, dbg_mods := Mods}) ->
|
155 | 161 | {rabbit_logger_text_fmt, formatter_plaintext_conf()} |
|
156 | 162 | {rabbit_logger_json_fmt, formatter_json_conf()}.
|
157 | 163 | %% @doc
|
158 |
| -%% Called from the Cuttlefish schema to derive the actual configuration from |
159 |
| -%% several Cuttlefish variables. |
| 164 | +%% Called from the Cuttlefish schema to derive the actual formatter |
| 165 | +%% configuration from several Cuttlefish variables. |
160 | 166 |
|
161 | 167 | translate_formatter_conf(Var, Conf) when is_list(Var) ->
|
162 | 168 | try
|
@@ -404,7 +410,7 @@ translate_json_formatter_conf(Var, Conf, GenericConfig) ->
|
404 | 410 |
|
405 | 411 | -spec parse_json_field_mapping(string()) -> json_field_map().
|
406 | 412 | %% @doc
|
407 |
| -%% Parses the field_map pattern. |
| 413 | +%% Parses the JSON formatter field_map pattern. |
408 | 414 | %%
|
409 | 415 | %% The pattern is of the form: `time:ts level msg *:-'.
|
410 | 416 | %%
|
@@ -496,5 +502,73 @@ parse_json_verbosity_mapping([], #{'$REST' := Default} = Mapping) ->
|
496 | 502 | parse_json_verbosity_mapping([], Mapping) ->
|
497 | 503 | Mapping.
|
498 | 504 |
|
| 505 | +-spec translate_journald_fields_conf(string(), cuttlefish_conf:conf()) -> |
| 506 | + proplists:proplist(). |
| 507 | +%% @doc |
| 508 | +%% Called from the Cuttlefish schema to create the actual journald handler |
| 509 | +%% configuration. |
| 510 | + |
| 511 | +translate_journald_fields_conf(Var, Conf) when is_list(Var) -> |
| 512 | + try |
| 513 | + RawFieldMapping = cuttlefish:conf_get(Var, Conf), |
| 514 | + parse_journald_field_mapping(RawFieldMapping) |
| 515 | + catch |
| 516 | + Class:Reason:Stacktrace -> |
| 517 | + ?LOG_ERROR( |
| 518 | + rabbit_prelaunch_errors:format_exception( |
| 519 | + Class, Reason, Stacktrace), |
| 520 | + #{domain => ?RMQLOG_DOMAIN_PRELAUNCH}), |
| 521 | + throw({configuration_translation_failure, Reason}) |
| 522 | + end. |
| 523 | + |
| 524 | +-spec parse_journald_field_mapping(string()) -> |
| 525 | + [atom() | {atom(), atom()}]. |
| 526 | +%% @doc |
| 527 | +%% Parses the journald fields pattern. |
| 528 | +%% |
| 529 | +%% The pattern is of the form: `SYSLOG_IDENTIFIER="rabbitmq-server" pid |
| 530 | +%% CODE_FILE=file'. |
| 531 | +%% |
| 532 | +%% `SYSLOG_IDENTIFIER="rabbitmq"' means the `SYSLOG_IDENTIFIER' field should |
| 533 | +%% be set to the string `rabbitmq-server'. |
| 534 | +%% |
| 535 | +%% `pid' means that field should be kept as-is. |
| 536 | +%% |
| 537 | +%% `CODE_FILE=file' means the `CODE_FILE' field should be set to the value of |
| 538 | +%% the `pid' field. |
| 539 | + |
| 540 | +parse_journald_field_mapping(RawMapping) -> |
| 541 | + parse_journald_field_mapping(string:split(RawMapping, " ", all), []). |
| 542 | + |
| 543 | +parse_journald_field_mapping([Entry | Rest], Mapping) -> |
| 544 | + Mapping1 = case string:split(Entry, "=", leading) of |
| 545 | + [[$_ | _], _] -> |
| 546 | + throw({bad_journald_mapping, |
| 547 | + leading_underscore_forbidden, |
| 548 | + Entry}); |
| 549 | + [Name, Value] -> |
| 550 | + case re:run(Name, "^[A-Z0-9_]+$", [{capture, none}]) of |
| 551 | + match -> |
| 552 | + ReOpts = [{capture, all_but_first, list}], |
| 553 | + case re:run(Value, "^\"(.+)\"$", ReOpts) of |
| 554 | + {match, [Data]} -> |
| 555 | + [{Name, Data} | Mapping]; |
| 556 | + nomatch -> |
| 557 | + Field = list_to_atom(Value), |
| 558 | + [{Name, Field} | Mapping] |
| 559 | + end; |
| 560 | + nomatch -> |
| 561 | + throw({bad_journald_mapping, |
| 562 | + name_with_invalid_characters, |
| 563 | + Entry}) |
| 564 | + end; |
| 565 | + [FieldS] -> |
| 566 | + Field = list_to_atom(FieldS), |
| 567 | + [Field | Mapping] |
| 568 | + end, |
| 569 | + parse_journald_field_mapping(Rest, Mapping1); |
| 570 | +parse_journald_field_mapping([], Mapping) -> |
| 571 | + lists:reverse(Mapping). |
| 572 | + |
499 | 573 | levels() ->
|
500 | 574 | [debug, info, notice, warning, error, critical, alert, emergency].
|
0 commit comments