Files
coredns/plugin/pkg/replacer/replacer.go

209 lines
4.4 KiB
Go
Raw Normal View History

package replacer
2016-03-18 20:57:35 +00:00
import (
"context"
2016-03-18 20:57:35 +00:00
"strconv"
"strings"
"time"
"github.com/coredns/coredns/plugin/metadata"
"github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/request"
2016-03-18 20:57:35 +00:00
"github.com/miekg/dns"
)
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// Replacer replaces labels for values in strings.
type Replacer struct {
valueFunc func(request.Request, *dnstest.Recorder, string) string
labels []string
2016-03-18 20:57:35 +00:00
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// labels are all supported labels that can be used in the default Replacer.
var labels = []string{
"{type}",
"{name}",
"{class}",
"{proto}",
"{size}",
"{remote}",
"{port}",
"{local}",
// Header values.
headerReplacer + "id}",
headerReplacer + "opcode}",
headerReplacer + "do}",
headerReplacer + "bufsize}",
// Recorded replacements.
"{rcode}",
"{rsize}",
"{duration}",
headerReplacer + "rflags}",
2016-03-18 20:57:35 +00:00
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// value returns the current value of label.
func value(state request.Request, rr *dnstest.Recorder, label string) string {
switch label {
case "{type}":
return state.Type()
case "{name}":
return state.Name()
case "{class}":
return state.Class()
case "{proto}":
return state.Proto()
case "{size}":
return strconv.Itoa(state.Req.Len())
case "{remote}":
return addrToRFC3986(state.IP())
case "{port}":
return state.Port()
case "{local}":
return addrToRFC3986(state.LocalIP())
// Header placeholders (case-insensitive).
case headerReplacer + "id}":
return strconv.Itoa(int(state.Req.Id))
case headerReplacer + "opcode}":
return strconv.Itoa(state.Req.Opcode)
case headerReplacer + "do}":
return boolToString(state.Do())
case headerReplacer + "bufsize}":
return strconv.Itoa(state.Size())
// Recorded replacements.
case "{rcode}":
if rr == nil {
return EmptyValue
}
rcode := dns.RcodeToString[rr.Rcode]
if rcode == "" {
rcode = strconv.Itoa(rr.Rcode)
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
return rcode
case "{rsize}":
if rr == nil {
return EmptyValue
}
return strconv.Itoa(rr.Len)
case "{duration}":
if rr == nil {
return EmptyValue
}
return strconv.FormatFloat(time.Since(rr.Start).Seconds(), 'f', -1, 64) + "s"
case headerReplacer + "rflags}":
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
if rr != nil && rr.Msg != nil {
return flagsToString(rr.Msg.MsgHdr)
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
return EmptyValue
2016-03-18 20:57:35 +00:00
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
return EmptyValue
}
2016-03-18 20:57:35 +00:00
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// New makes a new replacer. This only needs to be called once in the setup and then call Replace for each incoming message.
// A replacer is safe for concurrent use.
func New() Replacer {
return Replacer{
valueFunc: value,
labels: labels,
}
2016-03-18 20:57:35 +00:00
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// Replace performs a replacement of values on s and returns the string with the replaced values.
func (r Replacer) Replace(ctx context.Context, state request.Request, rr *dnstest.Recorder, s string) string {
for _, placeholder := range r.labels {
if strings.Contains(s, placeholder) {
s = strings.Replace(s, placeholder, r.valueFunc(state, rr, placeholder), -1)
2016-03-18 20:57:35 +00:00
}
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
// Metadata label replacements. Scan for {/ and search for next }, replace that metadata label with
// any meta data that is available.
b := strings.Builder{}
for strings.Contains(s, labelReplacer) {
idxStart := strings.Index(s, labelReplacer)
endOffset := idxStart + len(labelReplacer)
idxEnd := strings.Index(s[endOffset:], "}")
if idxEnd > -1 {
label := s[idxStart+2 : endOffset+idxEnd]
fm := metadata.ValueFunc(ctx, label)
replacement := EmptyValue
if fm != nil {
replacement = fm()
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
b.WriteString(s[:idxStart])
b.WriteString(replacement)
s = s[endOffset+idxEnd+1:]
} else {
break
2016-03-18 20:57:35 +00:00
}
}
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
b.WriteString(s)
return b.String()
2016-03-18 20:57:35 +00:00
}
2016-04-03 17:16:46 +01:00
func boolToString(b bool) string {
if b {
return "true"
}
return "false"
}
// flagsToString checks all header flags and returns those
// that are set as a string separated with commas
func flagsToString(h dns.MsgHdr) string {
flags := make([]string, 7)
i := 0
if h.Response {
flags[i] = "qr"
i++
}
if h.Authoritative {
flags[i] = "aa"
i++
}
if h.Truncated {
flags[i] = "tc"
i++
}
if h.RecursionDesired {
flags[i] = "rd"
i++
}
if h.RecursionAvailable {
flags[i] = "ra"
i++
}
if h.Zero {
flags[i] = "z"
i++
}
if h.AuthenticatedData {
flags[i] = "ad"
i++
}
if h.CheckingDisabled {
flags[i] = "cd"
i++
}
return strings.Join(flags[:i], ",")
}
// addrToRFC3986 will add brackets to the address if it is an IPv6 address.
func addrToRFC3986(addr string) string {
if strings.Contains(addr, ":") {
return "[" + addr + "]"
}
return addr
}
const (
pkg/replace: make it more efficient. (#2544) * pkg/replace: make it more efficient. Remove the map that is allocated on every write and make it more static, but just defining a function that gets called for a label and returns its value. Remove the interface definition and just implement what is needed in our case. Add benchmark test for replace as well. Extend metadata test to test multiple values (pretty sure this didn't work, but there wasn't a test for it, so can't be sure). Update all callers to use it - concurrent use should be fine as we pass everything by value. Benchmarks in replacer: new: BenchmarkReplacer-4 300000 4717 ns/op 240 B/op 8 allocs/op old: BenchmarkReplacer-4 300000 4368 ns/op 384 B/op 11 allocs/op Added benchmark function to the old code to test it. ~~~ func BenchmarkReplacer(b *testing.B) { w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion("example.org.", dns.TypeHINFO) r.MsgHdr.AuthenticatedData = true b.ResetTimer() b.ReportAllocs() repl := New(context.TODO(), r, w, "") for i := 0; i < b.N; i++ { repl.Replace("{type} {name} {size}") } } ~~~ New code contains (of course a different one). The amount of ops is more, which might be good to look at some more. For all the allocations is seems it was quite performant. This looks to be 50% faster, and there is less allocations in log plugin: old: BenchmarkLogged-4 20000 70526 ns/op new: BenchmarkLogged-4 30000 57558 ns/op Signed-off-by: Miek Gieben <miek@miek.nl> * Stickler bot Signed-off-by: Miek Gieben <miek@miek.nl> * Improve test coverage Signed-off-by: Miek Gieben <miek@miek.nl> * typo Signed-off-by: Miek Gieben <miek@miek.nl> * Add test for malformed log lines Signed-off-by: Miek Gieben <miek@miek.nl>
2019-02-12 07:38:49 +00:00
headerReplacer = "{>"
labelReplacer = "{/"
// EmptyValue is the default empty value.
EmptyValue = "-"
)