Skip to content

Commit 97e32f6

Browse files
committed
Respect maximum message length
... to avoid [MESSAGE_TOO_LONG errors](https://core.telegram.org/method/messages.sendMessage#return-errors)
1 parent 17b66bd commit 97e32f6

2 files changed

Lines changed: 60 additions & 8 deletions

File tree

lib/telegram_logger_backend/formatter.ex

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
11
defmodule LoggerTelegramBackend.Formatter do
22
@moduledoc false
33

4+
@max_length 4096
5+
46
def format_event(message, level, metadata) do
5-
"""
6-
<b>[#{level}]</b> #{format_message(message)}
7-
<pre>#{format_metadata(metadata)}</pre>
8-
"""
7+
level_str = "[#{level}]"
8+
metadata_str = format_metadata(metadata)
9+
10+
max_length = @max_length - String.length(level_str) - String.length(metadata_str) - 1
11+
message_str = format_message(message, max_length)
12+
13+
"<b>#{level_str}</b> " <> message_str <> "\n<pre>#{metadata_str}</pre>"
914
end
1015

11-
defp format_message(message) do
16+
defp format_message(message, max_length) do
1217
message
1318
|> to_string
1419
|> String.trim()
20+
|> limit_length(max_length)
1521
|> escape_special_chars()
1622
|> highlight_title()
1723
end
1824

25+
defp limit_length(str, max) do
26+
case String.split_at(str, max - 3) do
27+
{m, ""} -> m
28+
{m, _} -> m <> "..."
29+
end
30+
end
31+
1932
defp escape_special_chars(message) do
2033
special_chars = [
2134
{"&", "&amp;"},

test/logger_telegram_backend_test.exs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ defmodule LoggerTelegramBackendTest do
44
require Logger
55

66
setup_all do
7-
Logger.remove_backend(:console)
7+
:ok = Logger.configure(truncate: :infinity)
8+
:ok = Logger.remove_backend(:console)
89
end
910

1011
test "logs the message to the specified sender" do
@@ -32,14 +33,52 @@ defmodule LoggerTelegramBackendTest do
3233
}
3334
end
3435

36+
test "shortens the message if necessary" do
37+
:ok = configure(metadata: [:function, :module])
38+
39+
message = List.duplicate("E", 9999) |> to_string
40+
Logger.info(message)
41+
assert_receive {:text, log}
42+
43+
assert log ==
44+
"""
45+
<b>[info]</b> <b>#{List.duplicate("E", 4000)}...</b>
46+
<pre>Function: \"test shortens the message if necessary/1\"
47+
Module: LoggerTelegramBackendTest</pre>
48+
"""
49+
|> String.trim_trailing()
50+
end
51+
52+
test "shortens the message based on its graphemes not bytes" do
53+
:ok = configure(metadata: [])
54+
55+
for grapheme <- ["A", "é", "💜"] do
56+
message = List.duplicate(grapheme, 9999) |> to_string
57+
Logger.info(message)
58+
59+
assert_receive {:text, log}
60+
assert log == "<b>[info]</b> <b>#{List.duplicate(grapheme, 4086)}...</b>\n<pre></pre>"
61+
end
62+
end
63+
64+
test "shortens the message and escapes special chars afterwards" do
65+
:ok = configure(metadata: [])
66+
67+
message = List.duplicate("&", 9999) |> to_string
68+
Logger.info(message)
69+
70+
assert_receive {:text, log}
71+
assert log == "<b>[info]</b> <b>#{List.duplicate("&amp;", 4086)}...</b>\n<pre></pre>"
72+
end
73+
3574
test "escapes special chars" do
3675
:ok = configure(metadata: [])
3776

3877
Logger.info("<>&")
3978
Logger.info("<code>FOO</code>")
4079

41-
assert_receive {:text, "<b>[info]</b> <b>&lt;&gt;&amp;</b>\n<pre></pre>\n"}
42-
assert_receive {:text, "<b>[info]</b> <b>&lt;code&gt;FOO&lt;/code&gt;</b>\n<pre></pre>\n"}
80+
assert_receive {:text, "<b>[info]</b> <b>&lt;&gt;&amp;</b>\n<pre></pre>"}
81+
assert_receive {:text, "<b>[info]</b> <b>&lt;code&gt;FOO&lt;/code&gt;</b>\n<pre></pre>"}
4382
end
4483

4584
test "logs multiple message smoothly" do

0 commit comments

Comments
 (0)