Browse Source

Document how to create a threadsafe registry

My first iteration of a metrics client had code like this:

```go
// Increment a counter with the given name.
func Increment(name string) {
	mn := getWithNamespace(name)
	m := metrics.GetOrRegister(mn, metrics.NewMeter()).(metrics.Meter)
	m.Mark(1)
}
```

Which contained a massive resource leak - every anonymous NewMeter() call
appends a new arbiter, so I had one arbiter for each function call! Instead
document the right way to do this so people hopefully don't get as lost.
Kevin Burke 10 năm trước cách đây
mục cha
commit
7282ad6453
4 tập tin đã thay đổi với 47 bổ sung3 xóa
  1. 9 0
      README.md
  2. 13 3
      gauge_test.go
  3. 17 0
      metrics_test.go
  4. 8 0
      timer_test.go

+ 9 - 0
README.md

@@ -39,6 +39,15 @@ t.Time(func() {})
 t.Update(47)
 ```
 
+Register() is not threadsafe. For threadsafe metric registration use
+GetOrRegister:
+
+```
+t := metrics.GetOrRegisterTimer("account.create.latency", nil)
+t.Time(func() {})
+t.Update(47)
+```
+
 Periodically log every metric in human-readable form to standard error:
 
 ```go

+ 13 - 3
gauge_test.go

@@ -1,6 +1,9 @@
 package metrics
 
-import "testing"
+import (
+	"fmt"
+	"testing"
+)
 
 func BenchmarkGuage(b *testing.B) {
 	g := NewGauge()
@@ -51,8 +54,15 @@ func TestFunctionalGauge(t *testing.T) {
 
 func TestGetOrRegisterFunctionalGauge(t *testing.T) {
 	r := NewRegistry()
-	NewRegisteredFunctionalGauge("foo", r, func() int64 { return 47})
+	NewRegisteredFunctionalGauge("foo", r, func() int64 { return 47 })
 	if g := GetOrRegisterGauge("foo", r); 47 != g.Value() {
 		t.Fatal(g)
 	}
-}
+}
+
+func ExampleGetOrRegisterGauge() {
+	m := "server.bytes_sent"
+	g := GetOrRegisterGauge(m, nil)
+	g.Update(47)
+	fmt.Println(g.Value()) // Output: 47
+}

+ 17 - 0
metrics_test.go

@@ -1,6 +1,7 @@
 package metrics
 
 import (
+	"fmt"
 	"io/ioutil"
 	"log"
 	"sync"
@@ -105,3 +106,19 @@ func BenchmarkMetrics(b *testing.B) {
 	wgR.Wait()
 	wgW.Wait()
 }
+
+func Example() {
+	c := NewCounter()
+	Register("money", c)
+	c.Inc(17)
+
+	// Threadsafe registration
+	t := GetOrRegisterTimer("db.get.latency", nil)
+	t.Time(func() {})
+	t.Update(1)
+
+	fmt.Println(c.Count())
+	fmt.Println(t.Min())
+	// Output: 17
+	// 1
+}

+ 8 - 0
timer_test.go

@@ -1,6 +1,7 @@
 package metrics
 
 import (
+	"fmt"
 	"math"
 	"testing"
 	"time"
@@ -79,3 +80,10 @@ func TestTimerZero(t *testing.T) {
 		t.Errorf("tm.RateMean(): 0.0 != %v\n", rateMean)
 	}
 }
+
+func ExampleGetOrRegisterTimer() {
+	m := "account.create.latency"
+	t := GetOrRegisterTimer(m, nil)
+	t.Update(47)
+	fmt.Println(t.Max()) // Output: 47
+}