mirror of
https://github.com/hanzoai/traces.git
synced 2026-10-30 18:20:41 +00:00
* Standardise error formatting using standard library errors package * Standardise improve non-idiomatic error messages * Make github.com/pkg/errors an indirect dependency Co-authored-by: A. Stoewer <[email protected]>
83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
package util
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/grafana/dskit/grpcutil"
|
|
"github.com/grafana/dskit/services"
|
|
|
|
util_log "github.com/grafana/tempo/pkg/util/log"
|
|
)
|
|
|
|
// Notifications about address resolution. All notifications are sent on the same goroutine.
|
|
type DNSNotifications interface {
|
|
// New address has been discovered by DNS watcher for supplied hostname.
|
|
AddressAdded(address string)
|
|
|
|
// Previously-discovered address is no longer resolved for the hostname.
|
|
AddressRemoved(address string)
|
|
}
|
|
|
|
type dnsWatcher struct {
|
|
watcher grpcutil.Watcher
|
|
notifications DNSNotifications
|
|
}
|
|
|
|
// NewDNSWatcher creates a new DNS watcher and returns a service that is wrapping it.
|
|
func NewDNSWatcher(address string, dnsLookupPeriod time.Duration, notifications DNSNotifications) (services.Service, error) {
|
|
resolver, err := grpcutil.NewDNSResolverWithFreq(dnsLookupPeriod, util_log.Logger)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
watcher, err := resolver.Resolve(address, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
w := &dnsWatcher{
|
|
watcher: watcher,
|
|
notifications: notifications,
|
|
}
|
|
return services.NewBasicService(nil, w.watchDNSLoop, nil), nil
|
|
}
|
|
|
|
// watchDNSLoop watches for changes in DNS and sends notifications.
|
|
func (w *dnsWatcher) watchDNSLoop(servCtx context.Context) error {
|
|
go func() {
|
|
// Close the watcher, when this service is asked to stop.
|
|
// Closing the watcher makes watchDNSLoop exit, since it only iterates on watcher updates, and has no other
|
|
// way to stop. We cannot close the watcher in `stopping` method, because it is only called *after*
|
|
// watchDNSLoop exits.
|
|
<-servCtx.Done()
|
|
w.watcher.Close()
|
|
}()
|
|
|
|
for {
|
|
updates, err := w.watcher.Next()
|
|
if err != nil {
|
|
// watcher.Next returns error when Close is called, but we call Close when our context is done.
|
|
// we don't want to report error in that case.
|
|
if servCtx.Err() != nil {
|
|
return nil
|
|
}
|
|
return fmt.Errorf("error from DNS watcher: %w", err)
|
|
}
|
|
|
|
for _, update := range updates {
|
|
switch update.Op {
|
|
case grpcutil.Add:
|
|
w.notifications.AddressAdded(update.Addr)
|
|
|
|
case grpcutil.Delete:
|
|
w.notifications.AddressRemoved(update.Addr)
|
|
|
|
default:
|
|
return fmt.Errorf("unknown op: %v", update.Op)
|
|
}
|
|
}
|
|
}
|
|
}
|