add "alignLeft" and "alignRight" functions (#9672)

Fixes https://github.com/grafana/loki/issues/9667
pull/8886/head^2
Gregor Zeitlinger 3 years ago committed by GitHub
parent 98d1307c7d
commit b1917a6178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CHANGELOG.md
  2. 28
      docs/sources/query/template_functions.md
  3. 28
      pkg/logql/log/fmt.go
  4. 60
      pkg/logql/log/fmt_test.go

@ -34,6 +34,7 @@
* [8684](https://github.com/grafana/loki/pull/8684) **oleksii-boiko-ua**: Helm: Add hpa templates for read, write and backend components.
* [9535](https://github.com/grafana/loki/pull/9535) **salvacorts** Index stats cache can be configured independently of the results cache. If it's not configured, but it's enabled, it will use the results cache configuration.
* [9604](https://github.com/grafana/loki/pull/9604) **dannykopping**: Querier: configurable writeback queue bytes size
* [9672](https://github.com/grafana/loki/pull/9672) **zeitlinger**: Add `alignLeft` and `alignRight` line formatting functions.
##### Fixes

@ -234,6 +234,32 @@ Examples:
{{ trimPrefix "-" "-hello" }} // output: hello
```
## alignLeft
Use this function to format a string to a fixed with, aligning the content to the left.
Signature: `alignLeft(count int, src string) string`
Examples:
```template
`{{ alignLeft 5 "hello world"}}` // output: "hello"
`{{ alignLeft 5 "hi"}}` // output: "hi "
```
## alignRight
Use this function to format a string to a fixed with, aligning the content to the right.
Signature: `alignRight(count int, src string) string`
Examples:
```template
`{{ alignRight 5 "hello world"}}` // output: "world"
`{{ alignRight 5 "hi"}}` // output: " hi"
```
## indent
The indent function indents every line in a given string to the specified indent width. This is useful when aligning multi-line strings.
@ -672,7 +698,7 @@ Examples:
```template
{{ default "-" "" }} // output: -
{{ default "-" "foo" }} // output: foo
{{ default "" "foo" }} // output: foo
```
Example of a query to print a `-` if the `http_request_headers_x_forwarded_for` label is empty:

@ -67,6 +67,8 @@ var (
"unixEpochMillis": unixEpochMillis,
"unixEpochNanos": unixEpochNanos,
"toDateInZone": toDateInZone,
"alignLeft": alignLeft,
"alignRight": alignRight,
}
// sprig template functions
@ -396,6 +398,32 @@ func trunc(c int, s string) string {
return s
}
func alignLeft(count int, src string) string {
runes := []rune(src)
l := len(runes)
if count < 0 || count == l {
return src
}
pad := count - l
if pad > 0 {
return src + strings.Repeat(" ", pad)
}
return string(runes[:count])
}
func alignRight(count int, src string) string {
runes := []rune(src)
l := len(runes)
if count < 0 || count == l {
return src
}
pad := count - l
if pad > 0 {
return strings.Repeat(" ", pad) + src
}
return string(runes[l-count:])
}
type Decolorizer struct{}
// RegExp to select ANSI characters courtesy of https://github.com/acarl005/stripansi

@ -459,6 +459,24 @@ func Test_lineFormatter_Format(t *testing.T) {
labels.FromStrings("foo", "aSdtIGEgc3RyaW5nLCBlbmNvZGUgbWUh"),
[]byte("1"),
},
{
"alignLeft",
newMustLineFormatter("{{ alignLeft 4 .foo }}"),
labels.FromStrings("foo", "hello"),
1656353124120000000,
[]byte("hell"),
labels.FromStrings("foo", "hello"),
[]byte("1"),
},
{
"alignRight",
newMustLineFormatter("{{ alignRight 4 .foo }}"),
labels.FromStrings("foo", "hello"),
1656353124120000000,
[]byte("ello"),
labels.FromStrings("foo", "hello"),
[]byte("1"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@ -721,6 +739,48 @@ func Test_trunc(t *testing.T) {
}
}
func Test_AlignLeft(t *testing.T) {
tests := []struct {
s string
c int
want string
}{
{"Hello, 世界", -1, "Hello, 世界"},
{"Hello, 世界", 0, ""},
{"Hello, 世界", 1, "H"},
{"Hello, 世界", 8, "Hello, 世"},
{"Hello, 世界", 20, "Hello, 世界 "},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%s%d", tt.s, tt.c), func(t *testing.T) {
if got := alignLeft(tt.c, tt.s); got != tt.want {
t.Errorf("alignLeft() = %q, want %q for %q with %v", got, tt.want, tt.s, tt.c)
}
})
}
}
func Test_AlignRight(t *testing.T) {
tests := []struct {
s string
c int
want string
}{
{"Hello, 世界", -1, "Hello, 世界"},
{"Hello, 世界", 0, ""},
{"Hello, 世界", 1, "界"},
{"Hello, 世界", 2, "世界"},
{"Hello, 世界", 20, " Hello, 世界"},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%s%d", tt.s, tt.c), func(t *testing.T) {
if got := alignRight(tt.c, tt.s); got != tt.want {
t.Errorf("alignRight() = %q, want %q for %q with %v", got, tt.want, tt.s, tt.c)
}
})
}
}
func Test_substring(t *testing.T) {
tests := []struct {
start int

Loading…
Cancel
Save