func TestStatic(t *testing.T) { var ( instances = []string{"foo", "bar", "baz"} endpoints = map[string]endpoint.Endpoint{ "foo": func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }, "bar": func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }, "baz": func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil }, } factory = func(instance string) (endpoint.Endpoint, error) { if e, ok := endpoints[instance]; ok { return e, nil } return nil, fmt.Errorf("%s: not found", instance) } ) p := static.NewPublisher(instances, factory, log.NewNopLogger()) have, err := p.Endpoints() if err != nil { t.Fatal(err) } want := []endpoint.Endpoint{endpoints["foo"], endpoints["bar"], endpoints["baz"]} if fmt.Sprint(want) != fmt.Sprint(have) { t.Fatalf("want %v, have %v", want, have) } }
func testEmitter() (*Emitter, *syncbuf) { buf := &syncbuf{buf: &bytes.Buffer{}} e := &Emitter{ prefix: "prefix.", mgr: conn.NewManager(mockDialer(buf), "", "", time.After, log.NewNopLogger()), logger: log.NewNopLogger(), keyVals: make(chan keyVal), quitc: make(chan chan struct{}), } go e.loop(time.Millisecond * 20) return e, buf }
func Example() { // Let's say this is a service that means to register itself. // First, we will set up some context. var ( etcdServer = "http://10.0.0.1:2379" // don't forget schema and port! prefix = "/services/foosvc/" // known at compile time instance = "1.2.3.4:8080" // taken from runtime or platform, somehow key = prefix + instance // should be globally unique value = "http://" + instance // based on our transport ctx = context.Background() ) // Build the client. client, err := NewClient(ctx, []string{etcdServer}, ClientOptions{}) if err != nil { panic(err) } // Build the registrar. registrar := NewRegistrar(client, Service{ Key: key, Value: value, }, log.NewNopLogger()) // Register our instance. registrar.Register() // At the end of our service lifecycle, for example at the end of func main, // we should make sure to deregister ourselves. This is important! Don't // accidentally skip this step by invoking a log.Fatal or os.Exit in the // interim, which bypasses the defer stack. defer registrar.Deregister() // It's likely that we'll also want to connect to other services and call // their methods. We can build a subscriber to listen for changes from etcd // and build endpoints, wrap it with a load-balancer to pick a single // endpoint, and finally wrap it with a retry strategy to get something that // can be used as an endpoint directly. barPrefix := "/services/barsvc" subscriber, err := NewSubscriber(client, barPrefix, barFactory, log.NewNopLogger()) if err != nil { panic(err) } balancer := lb.NewRoundRobin(subscriber) retry := lb.Retry(3, 3*time.Second, balancer) // And now retry can be used like any other endpoint. req := struct{}{} if _, err = retry(ctx, req); err != nil { panic(err) } }
func TestIssue292(t *testing.T) { // The util/conn.Manager won't attempt to reconnect to the provided endpoint // if the endpoint is initially unavailable (e.g. dial tcp :8080: // getsockopt: connection refused). If the endpoint is up when // conn.NewManager is called and then goes down/up, it reconnects just fine. var ( tickc = make(chan time.Time) after = func(time.Duration) <-chan time.Time { return tickc } dialconn = net.Conn(nil) dialerr = errors.New("fail") dialer = func(string, string) (net.Conn, error) { return dialconn, dialerr } mgr = NewManager(dialer, "netw", "addr", after, log.NewNopLogger()) ) if conn := mgr.Take(); conn != nil { t.Fatal("first Take should have yielded nil conn, but didn't") } dialconn, dialerr = &mockConn{}, nil select { case tickc <- time.Now(): case <-time.After(time.Second): t.Fatal("manager isn't listening for a tick, despite a failed dial") } if !within(time.Second, func() bool { return mgr.Take() != nil }) { t.Fatal("second Take should have yielded good conn, but didn't") } }
func TestBadFactory(t *testing.T) { logger := log.NewNopLogger() factory := func(string) (endpoint.Endpoint, io.Closer, error) { return nil, nil, errors.New("kaboom") } client := &fakeClient{ responses: map[string]*stdetcd.Response{"/foo": fakeResponse}, } p, err := kitetcd.NewPublisher(client, "/foo", factory, logger) if err != nil { t.Fatalf("failed to create new publisher: %v", err) } defer p.Stop() endpoints, err := p.Endpoints() if err != nil { t.Fatal(err) } if want, have := 0, len(endpoints); want != have { t.Errorf("want %q, have %q", want, have) } }
// NewScribeCollector returns a new Scribe-backed Collector. addr should be a // TCP endpoint of the form "host:port". timeout is passed to the Thrift dial // function NewTSocketFromAddrTimeout. batchSize and batchInterval control the // maximum size and interval of a batch of spans; as soon as either limit is // reached, the batch is sent. The logger is used to log errors, such as batch // send failures; users should provide an appropriate context, if desired. func NewScribeCollector(addr string, timeout time.Duration, options ...ScribeOption) (Collector, error) { factory := scribeClientFactory(addr, timeout) client, err := factory() if err != nil { return nil, err } c := &ScribeCollector{ client: client, factory: factory, spanc: make(chan *Span), sendc: make(chan struct{}), batch: []*scribe.LogEntry{}, batchInterval: defaultBatchInterval * time.Second, batchSize: 100, shouldSample: SampleRate(1.0, rand.Int63()), logger: log.NewNopLogger(), category: defaultScribeCategory, quit: make(chan struct{}), } for _, option := range options { option(c) } c.nextSend = time.Now().Add(c.batchInterval) go c.loop() return c, nil }
func TestQuery(t *testing.T) { g := New(dbPath, log.NewNopLogger()) ts, err := g.Query("", 0, 100) if err != nil { t.Fatalf("g.Query(%q, %d, %d): got error: %s", "", 0, 100, err) } if want, got := 24, len(ts); want != got { t.Errorf("g.Query(%q, %d, %d): want %d threads got %d", "", 0, 100, want, got) } ts, err = g.Query("", 0, 20) if err != nil { t.Fatalf("g.Query(%q, %d, %d): got error: %s", "", 0, 20, err) } if want, got := 20, len(ts); want != got { t.Errorf("g.Query(%q, %d, %d): want %d threads got %d", "", 0, 20, want, got) } ts, err = g.Query("", 20, 100) if err != nil { t.Fatalf("g.Query(%q, %d, %d): got error: %s", "", 20, 100, err) } if want, got := 4, len(ts); want != got { t.Errorf("g.Query(%q, %d, %d): want %d threads got %d", "", 20, 100, want, got) } }
func TestRefreshNoChange(t *testing.T) { var ( addr = &net.SRV{Target: "my-target", Port: 5678} addrs = []*net.SRV{addr} name = "my-name" ticker = time.NewTicker(time.Second) lookups = uint32(0) lookupSRV = func(string, string, string) (string, []*net.SRV, error) { atomic.AddUint32(&lookups, 1) return "", addrs, nil } e = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } factory = func(string) (endpoint.Endpoint, io.Closer, error) { return e, nil, nil } logger = log.NewNopLogger() ) ticker.Stop() tickc := make(chan time.Time) ticker.C = tickc p := NewPublisherDetailed(name, ticker, lookupSRV, factory, logger) defer p.Stop() if want, have := uint32(1), atomic.LoadUint32(&lookups); want != have { t.Errorf("want %d, have %d", want, have) } tickc <- time.Now() if want, have := uint32(2), atomic.LoadUint32(&lookups); want != have { t.Errorf("want %d, have %d", want, have) } }
func TestBadFactory(t *testing.T) { var ( name = "some-name" ticker = time.NewTicker(time.Second) addr = &net.SRV{Target: "foo", Port: 1234} addrs = []*net.SRV{addr} lookupSRV = func(a, b, c string) (string, []*net.SRV, error) { return "", addrs, nil } creates = uint32(0) factory = func(s string) (endpoint.Endpoint, io.Closer, error) { atomic.AddUint32(&creates, 1) return nil, nil, errors.New("kaboom") } logger = log.NewNopLogger() ) p := NewPublisherDetailed(name, ticker, lookupSRV, factory, logger) defer p.Stop() endpoints, err := p.Endpoints() if err != nil { t.Error(err) } if want, have := 0, len(endpoints); want != have { t.Errorf("want %q, have %q", want, have) } if want, have := uint32(1), atomic.LoadUint32(&creates); want != have { t.Errorf("want %d, have %d", want, have) } }
func TestBadLookup(t *testing.T) { var ( name = "some-name" ticker = time.NewTicker(time.Second) lookups = uint32(0) lookupSRV = func(string, string, string) (string, []*net.SRV, error) { atomic.AddUint32(&lookups, 1) return "", nil, errors.New("kaboom") } e = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } factory = func(string) (endpoint.Endpoint, io.Closer, error) { return e, nil, nil } logger = log.NewNopLogger() ) p := NewPublisherDetailed(name, ticker, lookupSRV, factory, logger) defer p.Stop() endpoints, err := p.Endpoints() if err != nil { t.Error(err) } if want, have := 0, len(endpoints); want != have { t.Errorf("want %d, have %d", want, have) } if want, have := uint32(1), atomic.LoadUint32(&lookups); want != have { t.Errorf("want %d, have %d", want, have) } }
func TestGraphite(t *testing.T) { p, err := NewGraphiteProvider("network", "address", "prefix", time.Second, log.NewNopLogger()) if err != nil { t.Fatal(err) } testProvider(t, "Graphite", p) }
func TestPublisher(t *testing.T) { var ( target = "my-target" port = uint16(1234) addr = &net.SRV{Target: target, Port: port} addrs = []*net.SRV{addr} name = "my-name" ttl = time.Second logger = log.NewNopLogger() e = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } ) oldLookup := lookupSRV defer func() { lookupSRV = oldLookup }() lookupSRV = mockLookupSRV(addrs, nil, nil) factory := func(instance string) (endpoint.Endpoint, error) { if want, have := addr2instance(addr), instance; want != have { t.Errorf("want %q, have %q", want, have) } return e, nil } p, err := NewPublisher(name, ttl, factory, logger) if err != nil { t.Fatal(err) } defer p.Stop() if _, err := p.Endpoints(); err != nil { t.Fatal(err) } }
func TestBadFactory(t *testing.T) { var ( logger = log.NewNopLogger() e = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } ) factory := func(instance string) (endpoint.Endpoint, error) { return e, errors.New("_") } machines := []string{"http://127.0.0.1:2379"} client := etcd.NewClient(machines) p, err := NewPublisher(client, "/stream", factory, logger) if err != nil { t.Fatalf("failed to create new publisher: %v", err) } defer p.Stop() endpoints, err := p.Endpoints() if err != nil { t.Fatal(err) } if want, have := 0, len(endpoints); want != have { t.Errorf("want %q, have %q", want, have) } }
func TestBadFactory(t *testing.T) { var ( addr = &net.SRV{Target: "foo", Port: 1234} addrs = []*net.SRV{addr} name = "some-name" ttl = time.Second factory = func(string) (endpoint.Endpoint, io.Closer, error) { return nil, nil, errors.New("kaboom") } logger = log.NewNopLogger() ) oldLookup := lookupSRV defer func() { lookupSRV = oldLookup }() lookupSRV = mockLookupSRV(addrs, nil, nil) p := NewPublisher(name, ttl, factory, logger) defer p.Stop() endpoints, err := p.Endpoints() if err != nil { t.Error(err) } if want, have := 0, len(endpoints); want != have { t.Errorf("want %q, have %q", want, have) } }
func TestPublisherStoppped(t *testing.T) { var ( logger = log.NewNopLogger() e = func(context.Context, interface{}) (interface{}, error) { return struct{}{}, nil } ) factory := func(instance string) (endpoint.Endpoint, error) { return e, errors.New("_") } client := &fakeClient{ responses: map[string]*stdetcd.Response{"/foo": fakeResponse}, } p, err := kitetcd.NewPublisher(client, "/foo", factory, logger) if err != nil { t.Fatalf("failed to create new publisher: %v", err) } p.Stop() _, have := p.Endpoints() if want := loadbalancer.ErrPublisherStopped; want != have { t.Fatalf("want %v, have %v", want, have) } }
func TestRefreshNoChange(t *testing.T) { var ( tick = make(chan time.Time) target = "my-target" port = uint16(5678) addr = &net.SRV{Target: target, Port: port} addrs = []*net.SRV{addr} name = "my-name" ttl = time.Second factory = func(string) (endpoint.Endpoint, io.Closer, error) { return nil, nil, errors.New("kaboom") } logger = log.NewNopLogger() ) oldTicker := newTicker defer func() { newTicker = oldTicker }() newTicker = func(time.Duration) *time.Ticker { return &time.Ticker{C: tick} } var resolves uint64 oldLookup := lookupSRV defer func() { lookupSRV = oldLookup }() lookupSRV = mockLookupSRV(addrs, nil, &resolves) p := NewPublisher(name, ttl, factory, logger) defer p.Stop() tick <- time.Now() if want, have := uint64(2), resolves; want != have { t.Errorf("want %d, have %d", want, have) } }
func TestDogStatsd(t *testing.T) { p, err := NewDogStatsdProvider("network", "address", "prefix", time.Second, log.NewNopLogger()) if err != nil { t.Fatal(err) } testProvider(t, "DogStatsd", p) }
func testServer(t *testing.T) (cancel, step func(), resp <-chan *http.Response) { var ( ctx, cancelfn = context.WithCancel(context.Background()) stepch = make(chan bool) endpoint = func(context.Context, interface{}) (interface{}, error) { <-stepch; return struct{}{}, nil } response = make(chan *http.Response) handler = httptransport.Server{ Context: ctx, Endpoint: endpoint, DecodeRequestFunc: func(*http.Request) (interface{}, error) { return struct{}{}, nil }, EncodeResponseFunc: func(http.ResponseWriter, interface{}) error { return nil }, Before: []httptransport.RequestFunc{func(ctx context.Context, r *http.Request) context.Context { return ctx }}, After: []httptransport.ResponseFunc{func(ctx context.Context, w http.ResponseWriter) { return }}, Logger: log.NewNopLogger(), } ) go func() { server := httptest.NewServer(handler) defer server.Close() resp, err := http.Get(server.URL) if err != nil { t.Error(err) return } response <- resp }() return cancelfn, func() { stepch <- true }, response }
func TestHistogram(t *testing.T) { // The histogram test is actually like 4 gauge tests. prefix, name := "statsd.", "histogram_test" label, value := "abc", "def" // ignored for Graphite re50 := regexp.MustCompile(prefix + name + `.p50 ([0-9\.]+) [0-9]+`) re90 := regexp.MustCompile(prefix + name + `.p90 ([0-9\.]+) [0-9]+`) re95 := regexp.MustCompile(prefix + name + `.p95 ([0-9\.]+) [0-9]+`) re99 := regexp.MustCompile(prefix + name + `.p99 ([0-9\.]+) [0-9]+`) g := New(prefix, log.NewNopLogger()) histogram := g.NewHistogram(name, 50).With(label, value) quantiles := func() (float64, float64, float64, float64) { var buf bytes.Buffer g.WriteTo(&buf) match50 := re50.FindStringSubmatch(buf.String()) p50, _ := strconv.ParseFloat(match50[1], 64) match90 := re90.FindStringSubmatch(buf.String()) p90, _ := strconv.ParseFloat(match90[1], 64) match95 := re95.FindStringSubmatch(buf.String()) p95, _ := strconv.ParseFloat(match95[1], 64) match99 := re99.FindStringSubmatch(buf.String()) p99, _ := strconv.ParseFloat(match99[1], 64) return p50, p90, p95, p99 } if err := teststat.TestHistogram(histogram, quantiles, 0.01); err != nil { t.Fatal(err) } }
func TestPublisherAddressOverride(t *testing.T) { var ( ctx = context.Background() logger = log.NewNopLogger() client = newTestClient(consulState) ) p, err := NewPublisher(client, testFactory, logger, "search", "db") if err != nil { t.Fatalf("publisher setup failed: %s", err) } defer p.Stop() eps, err := p.Endpoints() if err != nil { t.Fatalf("endpoints failed: %s", err) } if have, want := len(eps), 1; have != want { t.Fatalf("have %v, want %v", have, want) } ins, err := eps[0](ctx, struct{}{}) if err != nil { t.Fatal(err) } if have, want := ins.(string), "10.0.0.10:9000"; have != want { t.Errorf("have %#v, want %#v", have, want) } }
func loadConfiguration(l log.Logger, cfgFile string) (Config, error) { if l == nil { l = log.NewNopLogger() } var err error var buf []byte if _, err := os.Stat(cfgFile); err == nil { l.Log("level", "debug", "msg", "Loading config", "source", cfgFile) buf, err = ioutil.ReadFile(cfgFile) if err != nil { l.Log("level", "error", "msg", "Could not load config", "source", cfgFile) buf = []byte(defaultConfig) } } else { l.Log("level", "error", "msg", "Loading default config due to error", "err", err) buf = []byte(defaultConfig) } var cfg Config err = yaml.Unmarshal(buf, &cfg) if err != nil { return Config{}, err } return cfg, nil }
// NewProvider will use the values in the Metrics config object // to generate a new go-kit/metrics/provider.Provider implementation. // If no type is given, a no-op implementation will be used. func (cfg Config) NewProvider() (provider.Provider, error) { if cfg.Logger == nil { cfg.Logger = log.NewNopLogger() } if cfg.Path == "" { cfg.Path = "/debug/vars" } if cfg.Interval == 0 { cfg.Interval = time.Second * 30 } switch cfg.Type { case Statsd: return provider.NewStatsdProvider(cfg.Network, cfg.Addr, cfg.Prefix, cfg.Interval, cfg.Logger) case DogStatsd: return provider.NewDogStatsdProvider(cfg.Network, cfg.Addr, cfg.Prefix, cfg.Interval, cfg.Logger) case Graphite: return provider.NewGraphiteProvider(cfg.Network, cfg.Addr, cfg.Prefix, cfg.Interval, cfg.Logger) case Prometheus: return provider.NewPrometheusProvider(cfg.Namespace, cfg.Subsystem), nil case Expvar: return provider.NewExpvarProvider(cfg.Prefix), nil default: return provider.NewDiscardProvider(), nil } }
func BenchmarkDiscard(b *testing.B) { logger := log.NewNopLogger() b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { logger.Log("k", "v") } }
func TestNopLogger(t *testing.T) { logger := log.NewNopLogger() if err := logger.Log("abc", 123); err != nil { t.Error(err) } if err := log.NewContext(logger).With("def", "ghi").Log(); err != nil { t.Error(err) } }
func BenchmarkValueBindingTimestamp(b *testing.B) { logger := log.NewNopLogger() lc := log.NewContext(logger).With("ts", log.DefaultTimestamp) b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { lc.Log("k", "v") } }
func BenchmarkOneWith(b *testing.B) { logger := log.NewNopLogger() lc := log.NewContext(logger).With("k", "v") b.ReportAllocs() b.ResetTimer() for i := 0; i < b.N; i++ { lc.Log("k", "v") } }
func TestBadFactory(t *testing.T) { cache := New(func(string) (endpoint.Endpoint, io.Closer, error) { return nil, nil, errors.New("bad factory") }, log.NewNopLogger()) cache.Update([]string{"foo:1234", "bar:5678"}) if want, have := 0, len(cache.Endpoints()); want != have { t.Errorf("want %d, have %d", want, have) } }
func TestCounter(t *testing.T) { prefix, name := "abc.", "def" label, value := "label", "value" // ignored regex := `^` + prefix + name + `:([0-9\.]+)\|c$` s := New(prefix, log.NewNopLogger()) counter := s.NewCounter(name, 1.0).With(label, value) valuef := teststat.SumLines(s, regex) if err := teststat.TestCounter(counter, valuef); err != nil { t.Fatal(err) } }
func TestTimingSampled(t *testing.T) { prefix, name := "statsd.", "sampled_timing_test" label, value := "foo", "bar" // ignored regex := `^` + prefix + name + `:([0-9\.]+)\|ms\|@0\.01[0]*$` s := New(prefix, log.NewNopLogger()) timing := s.NewTiming(name, 0.01).With(label, value) quantiles := teststat.Quantiles(s, regex, 50) if err := teststat.TestHistogram(timing, quantiles, 0.02); err != nil { t.Fatal(err) } }
func TestTiming(t *testing.T) { prefix, name := "statsd.", "timing_test" label, value := "abc", "def" // ignored regex := `^` + prefix + name + `:([0-9\.]+)\|ms$` s := New(prefix, log.NewNopLogger()) timing := s.NewTiming(name, 1.0).With(label, value) quantiles := teststat.Quantiles(s, regex, 50) // no |@0.X if err := teststat.TestHistogram(timing, quantiles, 0.01); err != nil { t.Fatal(err) } }