···32323333<small>* new levels</small>
34343535-This allow to provide finer graded verbosity control, however due to
3636-compatibility reasons, in Elixir backends we need to translate these levels back
3737-to "old" set of 4. The current table looks like:
3535+This allow to provide finer graded verbosity control, due to compatibility
3636+reasons, in Elixir backends we need to translate these levels back to "old" set
3737+of 4. The current table looks like:
38383939| Call level | What Elixir backend will see |
4040| -- | -- |
···49495050<small>* "translated" messages</small>
51515252-However we can set verbosity to all levels. This may be confusing during the
5353-transition period, but we cannot change the behaviour until Elixir 2 (which is
5454-not happening any time soon).
5252+We can set verbosity to all levels. This may be confusing during the transition
5353+period, but we cannot change the behaviour until Elixir 2 (which is not
5454+happening any time soon).
55555656Usage of the new levels is "obvious":
5757···170170One of the biggest new features in the Elixir 1.11 is support for structured
171171logging. This mean that the log message do not need to be free-form string, but
172172instead we can pass structure, that can provide more machine-readable data for
173173-processing in log aggregators. In Elixir 1.11 is is simple as passing map as a
173173+processing in log aggregators. In Elixir 1.11 is simple as passing map as a
174174first argument to the `Logger` macros:
175175176176```elixir
···276276}
277277```
278278279279-Additionally you can see there that we can have more information available in
280280-the structured log that would otherwise needed to be crammed somewhere into the
281281-text message, even if it is not important in "regular" Ops observability.
279279+You can see there that we can have more information available in the structured
280280+log that would otherwise needed to be crammed somewhere into the text message,
281281+even if it is not important in "regular" Ops observability.
282282283283This can raise a question - why not use metadata for such functionality, like it
284284is available in [`LoggerJSON`][] or [`Ink`][]? The reason is that their reason
···300300 },
301301 # Metadata
302302 %{
303303- domain: [:otp, :elixir],
304303 error_logger: %{tag: :error_msg},
305304 report_cb: &GenServer.format_report/1
306305 }
···398397 that metadata is for filtering?). It supports multiple possible relations
399398 between the log domain and defined domain.
400399- `level` - allow filtering (in or out) messages depending on their level, in
401401- both directions. So it will allow you to filter messages with higher level for
400400+ both directions. It will allow you to filter messages with higher level for
402401 some handlers. Just remember, that it will not receive messages that will not
403402 pass primary/module level.
404403- `progress` - filters all reports from `supervisor` and
···410409411410### Modifying a message
412411413413-Sometimes (hopefully rarely) there is need to alter messages in the system. For
414414-example we may need to prevent sensitive information from being logged. When
415415-using "old" Elixir approach you could abuse translators, but that was error
416416-prone, as first successful translator was breaking pipeline, so you couldn't
417417-just smash one on top and then keep rest working as is. With "new" approach and
418418-structured logging you can just traverse the report and replace all occurences
419419-of the unsafe data with anonymised data. For example:
412412+Sometimes there is need to alter messages in the system. For example we may need
413413+to prevent sensitive information from being logged. When using "old" Elixir
414414+approach you could abuse translators, but that was error prone, as first
415415+successful translator was breaking pipeline, so you couldn't just smash one on
416416+top and then keep rest working as is. With "new" approach and structured logging
417417+you can just traverse the report and replace all occurences of the unsafe data
418418+with anonymised data. For example:
420419421420```elixir
422421def filter_out_password(%{msg: {:report, report}} = event, _opts) do
···454453This snippet will replace all occurences of `:password` or `"password"` with
455454filtered out value.
456455457457-There is disadvantage of such approach though - it will make all messages with
458458-such fields allowed in case if your filter has `:filter_default` set to `:stop`.
459459-That mean, that if you want to make some of them rejected anyway, then you will
460460-need to manually add additional step to reject messages that do not fit into
461461-your patterns. Alternatively you can use `filter_default: :log` and then use
462462-opt-out logging. There currently is no way to alter the message and make other
463463-filters decide whether log it or not (as of OTP 24).
456456+The disadvantage of such approach - it will make all messages with such fields
457457+allowed in case if your filter has `:filter_default` set to `:stop`. That mean,
458458+that if you want to make some of them rejected anyway, then you will need to
459459+manually add additional step to reject messages that do not fit into your
460460+patterns. Alternatively you can use `filter_default: :log` and then use opt-out
461461+logging. There currently is no way to alter the message and make other filters
462462+decide whether log it or not (as of OTP 24).
464463465464## Summary
466465