Use the new truncation in bytes functions to ensure strings are not butchered

Signed-off-by: gotjosh <josue.abreu@gmail.com>
This commit is contained in:
gotjosh 2022-11-11 15:14:35 +00:00
parent 7f94b16470
commit f51f51ec72
No known key found for this signature in database
GPG Key ID: A6E1DDE38FF3C74E
3 changed files with 30 additions and 12 deletions

View File

@ -20,6 +20,7 @@ import (
"io"
"net/http"
"net/url"
"strings"
"github.com/go-kit/log"
"github.com/go-kit/log/level"
@ -100,15 +101,32 @@ func TruncateInRunes(s string, n int) (string, bool) {
// TruncateInBytes truncates a string to fit the given size in Bytes.
func TruncateInBytes(s string, n int) (string, bool) {
// First, measure the string the w/o a to-rune conversion.
if len(s) <= n {
return s, false
}
// The truncationMarker itself is 3 bytes, we can't return any part of the string when it's less than 3.
if n <= 3 {
return string(s[:n]), true
switch n {
case 3:
return truncationMarker, true
default:
return strings.Repeat(".", n), true
}
}
return string(s[:n-3]) + truncationMarker, true // In bytes, the truncation marker is 3 bytes.
// Now, to ensure we don't butcher the string we need to remove using runes.
r := []rune(s)
truncationTarget := n - 3
// Next, let's truncate the runes to the lower possible number.
truncatedRunes := r[:truncationTarget]
for len(string(truncatedRunes)) > truncationTarget {
truncatedRunes = r[:len(truncatedRunes)-1]
}
return string(truncatedRunes) + truncationMarker, true
}
// TmplText is using monadic error handling in order to make string templating

View File

@ -49,7 +49,7 @@ func TestTruncate(t *testing.T) {
in: "abcde",
n: 2,
runes: expect{out: "ab", trunc: true},
bytes: expect{out: "ab", trunc: true},
bytes: expect{out: "..", trunc: true},
},
{
in: "abcde",
@ -73,25 +73,25 @@ func TestTruncate(t *testing.T) {
in: "a⌘cde",
n: 5,
runes: expect{out: "a⌘cde", trunc: false},
bytes: expect{out: "a\xe2…", trunc: true},
bytes: expect{out: "a…", trunc: true},
},
{
in: "a⌘cdef",
n: 5,
runes: expect{out: "a⌘cd…", trunc: true},
bytes: expect{out: "a\xe2…", trunc: true},
bytes: expect{out: "a…", trunc: true},
},
{
in: "世界cdef",
n: 3,
runes: expect{out: "世界c", trunc: true},
bytes: expect{out: "", trunc: true},
bytes: expect{out: "", trunc: true},
},
{
in: "❤️✅🚀🔥❌",
n: 4,
runes: expect{out: "❤️✅…", trunc: true},
bytes: expect{out: "\xe2…", trunc: true},
in: "❤️✅🚀🔥❌❤️✅🚀🔥❌❤️✅🚀🔥❌❤️✅🚀🔥❌",
n: 19,
runes: expect{out: "❤️✅🚀🔥❌❤️✅🚀🔥❌❤️✅🚀🔥❌…", trunc: true},
bytes: expect{out: "❤️✅🚀…", trunc: true},
},
}
@ -117,8 +117,8 @@ func TestTruncate(t *testing.T) {
t.Run(fmt.Sprintf("%s(%s,%d)", fnName, tc.in, tc.n), func(t *testing.T) {
s, trunc := fn(tc.in, tc.n)
require.Equal(t, truncated, trunc)
require.Equal(t, out, s)
require.Equal(t, truncated, trunc)
})
}
}

View File

@ -94,7 +94,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
return false, err
}
message, truncated := notify.Truncate(message, maxMessageSize)
message, truncated := notify.TruncateInBytes(message, maxMessageSize)
if truncated {
level.Debug(n.logger).Log("msg", "message truncated due to exceeding maximum allowed length by webex", "truncated_message", message)
}