Skip to content

Commit ffb7ab1

Browse files
committed
feat(metrics): avoid back and forth data conversion
Instead of converting bytes to string and use regex to dedup new line characters and trim spaces, do the processing on byte data. Signed-off-by: AyushSenapati <a.p.senapati008@gmail.com>
1 parent c9177d7 commit ffb7ab1

File tree

2 files changed

+53
-24
lines changed

2 files changed

+53
-24
lines changed

app/kuma-dp/pkg/dataplane/metrics/server.go

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ import (
1111
"net/http"
1212
"net/url"
1313
"os"
14-
"regexp"
1514
"strconv"
16-
"strings"
1715
"sync"
1816
"time"
1917

@@ -230,38 +228,53 @@ func processMetrics(metrices <-chan []byte, contentType expfmt.Format) []byte {
230228
}
231229
}
232230

233-
str := processNewlineChars(buf.String(), true, true)
234-
str = fmt.Sprintf("%s\n", str)
231+
processedMetrics := processNewlineChars(buf.Bytes(), true, true)
232+
processedMetrics = append(processedMetrics, '\n')
233+
buf.Reset()
234+
_, err := buf.Write(processedMetrics)
235+
if err != nil {
236+
panic(err)
237+
}
235238

236-
// if the content type is not OpenMetrics, we don't need to add EOF marker
237-
if !(contentType == expfmt.FmtOpenMetrics_1_0_0 || contentType == expfmt.FmtOpenMetrics_0_0_1) {
238-
return []byte(str)
239+
if contentType == expfmt.FmtOpenMetrics_1_0_0 || contentType == expfmt.FmtOpenMetrics_0_0_1 {
240+
// make metrics OpenMetrics compliant
241+
buf.Write([]byte("# EOF\n"))
242+
return buf.Bytes()
239243
}
240244

241-
// make metrics OpenMetrics compliant
242-
return []byte(fmt.Sprintf("%s# EOF\n", str))
245+
return buf.Bytes()
243246
}
244247

245-
// processNewlineChars processes the newline characters in the text.
246-
// If dedup is true, it replaces multiple newline characters with a single newline character.
248+
// processNewlineChars processes the newline characters in the byteData.
249+
// If dedup is true, it replaces multiple consecutive newline characters with a single newline character.
247250
// If trim is true, it trims the leading and trailing newline characters.
248-
func processNewlineChars(text string, dedup, trim bool) string {
251+
func processNewlineChars(byteData []byte, dedup, trim bool) []byte {
249252
if dedup {
250-
// Create a regular expression to match multiple newline characters.
251-
reg := regexp.MustCompile(`(\r\n?|\n){2,}`)
252-
253-
// Replace all the matches with a single newline character.
254-
text = reg.ReplaceAllString(text, "\n")
253+
byteData = dedupFn(byteData, '\n', '\n')
255254
}
256-
257255
if trim {
258-
// Trim the leading and trailing newline characters.
259-
text = strings.TrimFunc(text, func(r rune) bool {
260-
return r == '\n'
261-
})
256+
byteData = bytes.TrimSpace(byteData)
262257
}
258+
return byteData
259+
}
263260

264-
return text
261+
func dedupFn(input []byte, old, new byte) []byte {
262+
var deduped []byte
263+
264+
var last byte
265+
if len(input) > 0 {
266+
last = input[0]
267+
}
268+
for i := 1; i < len(input); i++ {
269+
if last == old && input[i] == last {
270+
last = new
271+
continue
272+
}
273+
deduped = append(deduped, last)
274+
last = input[i]
275+
}
276+
deduped = append(deduped, last)
277+
return deduped
265278
}
266279

267280
// selectContentType selects the highest priority content type supported by the applications.

app/kuma-dp/pkg/dataplane/metrics/server_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ var _ = Describe("ProcessNewlineChars", func() {
181181

182182
DescribeTable("should",
183183
func(given testCase) {
184-
actual := processNewlineChars(given.input, given.deduplicate, given.trim)
184+
actual := string(processNewlineChars([]byte(given.input), given.deduplicate, given.trim))
185185
Expect(actual).To(Equal(given.expected))
186186
},
187187
Entry("should not deduplicate or trim newline characters", testCase{
@@ -210,3 +210,19 @@ var _ = Describe("ProcessNewlineChars", func() {
210210
}),
211211
)
212212
})
213+
214+
var _ = Describe("Dedup", func() {
215+
type testCase struct {
216+
input string
217+
expected string
218+
}
219+
DescribeTable("should", func(given testCase) {
220+
actual := string(dedupFn([]byte(given.input), '\n', '\n'))
221+
Expect(actual).To(Equal(given.expected))
222+
},
223+
Entry("should deduplicate newline characters", testCase{
224+
input: "This is a test.\n\n\n\nThis is another test.\n",
225+
expected: "This is a test.\nThis is another test.\n",
226+
}),
227+
)
228+
})

0 commit comments

Comments
 (0)