Merge remote-tracking branch 'origin/v3' into v3

# Conflicts:
#	client/noop.go
#	errors/errors_test.go
#	logger/unwrap/unwrap_test.go
#	register/memory/memory_test.go
#	server/noop_test.go
#	service.go
#	util/dns/cache.go
#	util/dns/conn.go
#	util/structfs/metadata_ec2.go
#	util/time/duration.go
This commit is contained in:
2024-12-09 13:18:13 +03:00
25 changed files with 248 additions and 123 deletions

View File

@@ -6,6 +6,9 @@ import (
"net"
"sync"
"time"
"go.unistack.org/micro/v3/meter"
"go.unistack.org/micro/v3/semconv"
)
// DialFunc is a [net.Resolver.Dial] function.
@@ -19,6 +22,11 @@ func NewNetResolver(opts ...Option) *net.Resolver {
o(&options)
}
if options.Meter == nil {
options.Meter = meter.DefaultMeter
opts = append(opts, Meter(options.Meter))
}
return &net.Resolver{
PreferGo: true,
StrictErrors: options.Resolver.StrictErrors,
@@ -56,6 +64,7 @@ type Options struct {
PreferIPV4 bool
PreferIPV6 bool
Timeout time.Duration
Meter meter.Meter
}
// MaxCacheEntries sets the maximum number of entries to cache.
@@ -87,6 +96,13 @@ func NegativeCache(b bool) Option {
}
}
// Meter sets meter.Meter
func Meter(m meter.Meter) Option {
return func(o *Options) {
o.Meter = m
}
}
// Timeout sets upstream *net.Resolver timeout
func Timeout(td time.Duration) Option {
return func(o *Options) {
@@ -156,7 +172,6 @@ func (c *cache) put(req string, res string) {
}
c.Lock()
defer c.Unlock()
if c.entries == nil {
c.entries = make(map[string]cacheEntry)
}
@@ -165,6 +180,8 @@ func (c *cache) put(req string, res string) {
var tested, evicted int
for k, e := range c.entries {
if time.Until(e.deadline) <= 0 {
c.opts.Meter.Counter(semconv.CacheItemsTotal, "type", "dns").Dec()
c.opts.Meter.Counter(semconv.CacheRequestTotal, "type", "dns", "method", "evict").Inc()
// delete expired entry
delete(c.entries, k)
evicted++
@@ -175,6 +192,8 @@ func (c *cache) put(req string, res string) {
continue
}
if evicted == 0 && c.opts.MaxCacheEntries > 0 && len(c.entries) >= c.opts.MaxCacheEntries {
c.opts.Meter.Counter(semconv.CacheItemsTotal, "type", "dns").Dec()
c.opts.Meter.Counter(semconv.CacheRequestTotal, "type", "dns", "method", "evict").Inc()
// delete at least one entry
delete(c.entries, k)
}
@@ -186,6 +205,9 @@ func (c *cache) put(req string, res string) {
deadline: time.Now().Add(ttl),
value: res[2:],
}
c.opts.Meter.Counter(semconv.CacheItemsTotal, "type", "dns").Inc()
c.Unlock()
}
func (c *cache) get(req string) (res string) {
@@ -210,6 +232,7 @@ func (c *cache) get(req string) (res string) {
// prepend correct ID
return req[:2] + entry.value
}
return ""
}
@@ -310,10 +333,18 @@ func getUint32(s string) int {
func cachingRoundTrip(cache *cache, network, address string) roundTripper {
return func(ctx context.Context, req string) (res string, err error) {
cache.opts.Meter.Counter(semconv.CacheRequestInflight, "type", "dns").Inc()
defer cache.opts.Meter.Counter(semconv.CacheRequestInflight, "type", "dns").Dec()
// check cache
if res = cache.get(req); res != "" {
return res, nil
}
cache.opts.Meter.Counter(semconv.CacheRequestTotal, "type", "dns", "method", "get", "status", "miss").Inc()
ts := time.Now()
defer func() {
cache.opts.Meter.Summary(semconv.CacheRequestLatencyMicroseconds, "type", "dns", "method", "get").UpdateDuration(ts)
cache.opts.Meter.Histogram(semconv.CacheRequestDurationSeconds, "type", "dns", "method", "get").UpdateDuration(ts)
}()
switch {
case cache.opts.PreferIPV4 && cache.opts.PreferIPV6:
@@ -340,6 +371,7 @@ func cachingRoundTrip(cache *cache, network, address string) roundTripper {
var d net.Dialer
conn, err = d.DialContext(ctx, network, address)
}
if err != nil {
return "", err
}

View File

@@ -12,5 +12,11 @@ func TestCache(t *testing.T) {
if err != nil {
t.Fatal(err)
}
t.Logf("addrs %v", addrs)
addrs, err = net.LookupHost("unistack.org")
if err != nil {
t.Fatal(err)
}
_ = addrs
}

View File

@@ -67,15 +67,20 @@ func (c *dnsConn) RemoteAddr() net.Addr {
}
func (c *dnsConn) SetDeadline(t time.Time) error {
_ = c.SetReadDeadline(t)
_ = c.SetWriteDeadline(t)
var err error
if err = c.SetReadDeadline(t); err != nil {
return err
}
if err = c.SetWriteDeadline(t); err != nil {
return err
}
return nil
}
func (c *dnsConn) SetReadDeadline(t time.Time) error {
c.Lock()
defer c.Unlock()
c.deadline = t
c.Unlock()
return nil
}