diff --git a/CHANGELOG.md b/CHANGELOG.md index 38e9d07ed9..e5bec6cd68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ * [8061](https://github.com/grafana/loki/pull/8061) **kavirajk**: Remove circle from Loki OSS * [8131](https://github.com/grafana/loki/pull/8131) **jeschkies**: Compile Promtail ARM and ARM64 with journald support. * [8212](https://github.com/grafana/loki/pull/8212) **kavirajk**: ingester: Add `ingester_memory_streams_labels_bytes metric` for more visibility of size of metadata of in-memory streams. +* [8271](https://github.com/grafana/loki/pull/8271) **kavirajk**: logql: Support urlencode and urldecode template functions ##### Fixes diff --git a/docs/sources/logql/template_functions.md b/docs/sources/logql/template_functions.md index 4a4d853cf0..9e5f9402e3 100644 --- a/docs/sources/logql/template_functions.md +++ b/docs/sources/logql/template_functions.md @@ -716,3 +716,33 @@ Example of a query to print how many times XYZ occurs in a line: ```logql {job="xyzlog"} | line_format `{{ __line__ | count "XYZ"}}` ``` + +## urlencode + +Use this function to encode the URL(s) in log messages. + +Signature: + +`urlencode(string) string` + +Examples: + +```template +"{{ .request_url | urlencode }}" +`{{ urlencode .request_url}}` +``` + +## urldecode + +Use this function to decode the URL(s) in log messages. + +Signature: + +`urldecode(string) string` + +Examples: + +```template +"{{ .request_url | urldecode }}" +`{{ urldecode .request_url}}` +``` diff --git a/pkg/logql/log/fmt.go b/pkg/logql/log/fmt.go index 94b26f195c..58357c4b95 100644 --- a/pkg/logql/log/fmt.go +++ b/pkg/logql/log/fmt.go @@ -3,6 +3,7 @@ package log import ( "bytes" "fmt" + "net/url" "strings" "text/template" "text/template/parse" @@ -57,6 +58,8 @@ var ( matches := r.FindAllStringIndex(s, -1) return len(matches), nil }, + "urldecode": url.QueryUnescape, + "urlencode": url.QueryEscape, } // sprig template functions diff --git a/pkg/logql/log/fmt_test.go b/pkg/logql/log/fmt_test.go index ada072928f..58fd7d2366 100644 --- a/pkg/logql/log/fmt_test.go +++ b/pkg/logql/log/fmt_test.go @@ -111,6 +111,28 @@ func Test_lineFormatter_Format(t *testing.T) { labels.Labels{{Name: "foo", Value: "BLIp"}, {Name: "bar", Value: "blop"}}, nil, }, + { + "urlencode", + newMustLineFormatter(`{{.foo | urlencode }} {{ urlencode .foo }}`), // assert both syntax forms + labels.Labels{ + {Name: "foo", Value: `/loki/api/v1/query?query=sum(count_over_time({stream_filter="some_stream",environment="prod", host=~"someec2.*"}`}, + }, + 0, + []byte("%2Floki%2Fapi%2Fv1%2Fquery%3Fquery%3Dsum%28count_over_time%28%7Bstream_filter%3D%22some_stream%22%2Cenvironment%3D%22prod%22%2C+host%3D~%22someec2.%2A%22%7D %2Floki%2Fapi%2Fv1%2Fquery%3Fquery%3Dsum%28count_over_time%28%7Bstream_filter%3D%22some_stream%22%2Cenvironment%3D%22prod%22%2C+host%3D~%22someec2.%2A%22%7D"), + labels.Labels{{Name: "foo", Value: `/loki/api/v1/query?query=sum(count_over_time({stream_filter="some_stream",environment="prod", host=~"someec2.*"}`}}, + nil, + }, + { + "urldecode", + newMustLineFormatter(`{{.foo | urldecode }} {{ urldecode .foo }}`), // assert both syntax forms + labels.Labels{ + {Name: "foo", Value: `%2Floki%2Fapi%2Fv1%2Fquery%3Fquery%3Dsum%28count_over_time%28%7Bstream_filter%3D%22some_stream%22%2Cenvironment%3D%22prod%22%2C+host%3D~%22someec2.%2A%22%7D`}, + }, + 0, + []byte(`/loki/api/v1/query?query=sum(count_over_time({stream_filter="some_stream",environment="prod", host=~"someec2.*"} /loki/api/v1/query?query=sum(count_over_time({stream_filter="some_stream",environment="prod", host=~"someec2.*"}`), + labels.Labels{{Name: "foo", Value: `%2Floki%2Fapi%2Fv1%2Fquery%3Fquery%3Dsum%28count_over_time%28%7Bstream_filter%3D%22some_stream%22%2Cenvironment%3D%22prod%22%2C+host%3D~%22someec2.%2A%22%7D`}}, + nil, + }, { "repeat", newMustLineFormatter(`{{ "foo" | repeat 3 }}`),