Skip to content

Commit b5c0b0a

Browse files
authored
Merge pull request #23 from InjectiveLabs/f/v2
feat: v2 direction
2 parents b179025 + 25711ce commit b5c0b0a

10 files changed

Lines changed: 583 additions & 72 deletions

File tree

client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ var (
3939
mixPanelClient *mixpanel.ApiClient
4040
)
4141

42+
func Tracer() trace.Tracer {
43+
return tracer
44+
}
45+
4246
type StatterConfig struct {
4347
Addr string // localhost:8125
4448
Prefix string // metrics prefix

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ require (
2929
cosmossdk.io/depinject v1.0.0-alpha.4 // indirect
3030
cosmossdk.io/errors v1.0.1 // indirect
3131
cosmossdk.io/log v1.3.1 // indirect
32-
cosmossdk.io/math v1.3.0 // indirect
32+
cosmossdk.io/math v1.5.3 // indirect
3333
cosmossdk.io/store v1.1.0 // indirect
3434
cosmossdk.io/x/tx v0.13.2 // indirect
3535
github.com/DataDog/appsec-internal-go v1.5.0 // indirect

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ cosmossdk.io/errors v1.0.1 h1:bzu+Kcr0kS/1DuPBtUFdWjzLqyUuCiyHjyJB6srBV/0=
1010
cosmossdk.io/errors v1.0.1/go.mod h1:MeelVSZThMi4bEakzhhhE/CKqVv3nOJDA25bIqRDu/U=
1111
cosmossdk.io/log v1.3.1 h1:UZx8nWIkfbbNEWusZqzAx3ZGvu54TZacWib3EzUYmGI=
1212
cosmossdk.io/log v1.3.1/go.mod h1:2/dIomt8mKdk6vl3OWJcPk2be3pGOS8OQaLUM/3/tCM=
13-
cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE=
14-
cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k=
13+
cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U=
14+
cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ=
1515
cosmossdk.io/store v1.1.0 h1:LnKwgYMc9BInn9PhpTFEQVbL9UK475G2H911CGGnWHk=
1616
cosmossdk.io/store v1.1.0/go.mod h1:oZfW/4Fc/zYqu3JmQcQdUJ3fqu5vnYTn3LZFFy8P8ng=
1717
cosmossdk.io/x/tx v0.13.2 h1:Kh90UH30bhnnUdJH+CmWLyaH8IKdY6BBGY3EkdOk82o=

metrics.go

Lines changed: 97 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"runtime"
88
"strconv"
99
"strings"
10+
"sync/atomic"
1011
"time"
1112

1213
log "github.com/InjectiveLabs/suplog"
@@ -165,26 +166,28 @@ func reportTiming(ctx context.Context, fn string, tags ...Tags) (context.Context
165166
tagArray = append(tagArray, getSingleTag("func_name", fn))
166167

167168
doneC := make(chan struct{})
168-
go func(name string, start time.Time) {
169-
timeout := time.NewTimer(config.StuckFunctionTimeout)
170-
defer timeout.Stop()
171-
172-
select {
173-
case <-doneC:
174-
return
175-
case <-timeout.C:
176-
clientMux.RLock()
177-
defer clientMux.RUnlock()
178-
179-
err := fmt.Errorf("detected stuck function: %s stuck for %v", name, time.Since(start))
180-
fmt.Println(err)
181-
client.Incr("func.stuck", tagArray, 1)
182-
if span != nil {
183-
span.SetStatus(codes.Error, "stuck")
184-
span.End()
169+
if !disableStuckFuncReport.Load() {
170+
go func(name string, start time.Time) {
171+
timeout := time.NewTimer(config.StuckFunctionTimeout)
172+
defer timeout.Stop()
173+
174+
select {
175+
case <-doneC:
176+
return
177+
case <-timeout.C:
178+
clientMux.RLock()
179+
defer clientMux.RUnlock()
180+
181+
err := fmt.Errorf("detected stuck function: %s stuck for %v", name, time.Since(start))
182+
fmt.Println(err)
183+
client.Incr("func.stuck", tagArray, 1)
184+
if span != nil {
185+
span.SetStatus(codes.Error, "stuck")
186+
span.End()
187+
}
185188
}
186-
}
187-
}(fn, t)
189+
}(fn, t)
190+
}
188191

189192
return spanCtx, func(stopTags ...Tags) {
190193
d := time.Since(t)
@@ -212,21 +215,24 @@ func ReportClosureFuncTiming(name string, tags ...Tags) StopTimerFunc {
212215
tagArray = append(tagArray, getSingleTag("func_name", name))
213216

214217
doneC := make(chan struct{})
215-
go func(name string, start time.Time) {
216-
timeout := time.NewTimer(config.StuckFunctionTimeout)
217-
defer timeout.Stop()
218-
219-
select {
220-
case <-doneC:
221-
return
222-
case <-timeout.C:
223-
clientMux.RLock()
224-
defer clientMux.RUnlock()
225-
226-
log.Warningf("detected stuck function: %s stuck for %v", name, time.Since(start))
227-
client.Incr("func.stuck", tagArray, 1)
228-
}
229-
}(name, t)
218+
219+
if !disableStuckFuncReport.Load() {
220+
go func(name string, start time.Time) {
221+
timeout := time.NewTimer(config.StuckFunctionTimeout)
222+
defer timeout.Stop()
223+
224+
select {
225+
case <-doneC:
226+
return
227+
case <-timeout.C:
228+
clientMux.RLock()
229+
defer clientMux.RUnlock()
230+
231+
log.Warningf("detected stuck function: %s stuck for %v", name, time.Since(start))
232+
client.Incr("func.stuck", tagArray, 1)
233+
}
234+
}(name, t)
235+
}
230236

231237
return func(stopTags ...Tags) {
232238
d := time.Since(t)
@@ -432,65 +438,108 @@ func ToString(i interface{}) (v string, ok bool) {
432438
case float64:
433439
v = strconv.FormatFloat(x, 'f', -1, 64)
434440
case *string:
435-
if x != nil {
441+
if x == nil {
442+
v = "nil"
443+
} else {
436444
v = *x
437445
}
438446
case *int:
439-
if x != nil {
447+
if x == nil {
448+
v = "nil"
449+
} else {
440450
v = strconv.FormatInt(int64(*x), 10)
441451
}
442452
case *int8:
443-
if x != nil {
453+
if x == nil {
454+
v = "nil"
455+
} else {
444456
v = strconv.FormatInt(int64(*x), 10)
445457
}
446458
case *int16:
447-
if x != nil {
459+
if x == nil {
460+
v = "nil"
461+
} else {
448462
v = strconv.FormatInt(int64(*x), 10)
449463
}
450464
case *int32:
451-
if x != nil {
465+
if x == nil {
466+
v = "nil"
467+
} else {
452468
v = strconv.FormatInt(int64(*x), 10)
453469
}
454470
case *int64:
455-
if x != nil {
471+
if x == nil {
472+
v = "nil"
473+
} else {
456474
v = strconv.FormatInt(*x, 10)
457475
}
458476
case *uint:
459-
if x != nil {
477+
if x == nil {
478+
v = "nil"
479+
} else {
460480
v = strconv.FormatUint(uint64(*x), 10)
461481
}
462482
case *uint8:
463-
if x != nil {
483+
if x == nil {
484+
v = "nil"
485+
} else {
464486
v = strconv.FormatUint(uint64(*x), 10)
465487
}
466488
case *uint16:
467-
if x != nil {
489+
if x == nil {
490+
v = "nil"
491+
} else {
468492
v = strconv.FormatUint(uint64(*x), 10)
469493
}
470494
case *uint32:
471-
if x != nil {
495+
if x == nil {
496+
v = "nil"
497+
} else {
472498
v = strconv.FormatUint(uint64(*x), 10)
473499
}
474500
case *uint64:
475-
if x != nil {
501+
if x == nil {
502+
v = "nil"
503+
} else {
476504
v = strconv.FormatUint(*x, 10)
477505
}
478506
case *float32:
479-
if x != nil {
507+
if x == nil {
508+
v = "nil"
509+
} else {
480510
v = strconv.FormatFloat(float64(*x), 'f', -1, 32)
481511
}
482512
case *float64:
483-
if x != nil {
513+
if x == nil {
514+
v = "nil"
515+
} else {
484516
v = strconv.FormatFloat(*x, 'f', -1, 64)
485517
}
486518
case bool:
487519
v = strconv.FormatBool(x)
488520
case *bool:
489-
v = strconv.FormatBool(*x)
521+
if x == nil {
522+
v = "nil"
523+
} else {
524+
v = strconv.FormatBool(*x)
525+
}
526+
case fmt.Stringer:
527+
rv := reflect.ValueOf(x)
528+
if rv.Kind() == reflect.Ptr && rv.IsNil() {
529+
v = "nil"
530+
} else {
531+
v = x.String()
532+
}
490533
case nil:
491534
v = "nil"
492535
default:
493536
ok = false
494537
}
495538
return v, ok
496539
}
540+
541+
var disableStuckFuncReport atomic.Bool
542+
543+
func DisableStuckFuncReport() {
544+
disableStuckFuncReport.Store(true)
545+
}

metrics_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ func TestToString(t *testing.T) {
9393
{"*float32", func() *float32 { f := float32(42.42); return &f }(), "42.42", true},
9494
{"*float64", func() *float64 { f := float64(42.42); return &f }(), "42.42", true},
9595
{"*bool", func() *bool { b := true; return &b }(), "true", true},
96+
{"nil *string", (*string)(nil), "nil", true},
97+
{"nil *int", (*int)(nil), "nil", true},
98+
{"nil *bool", (*bool)(nil), "nil", true},
99+
{"stringer", stringerTag("custom"), "tag:custom", true},
96100
{"nil", nil, "nil", true},
97101
{"unsupported type", struct{}{}, "", false},
98102
}
@@ -106,6 +110,12 @@ func TestToString(t *testing.T) {
106110
}
107111
}
108112

113+
type stringerTag string
114+
115+
func (t stringerTag) String() string {
116+
return "tag:" + string(t)
117+
}
118+
109119
func record(t *testing.T) *statterRecorder {
110120
t.Helper()
111121
var rec statterRecorder

otel.go

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"strings"
77
"sync"
8+
"sync/atomic"
89
"time"
910

1011
"go.opentelemetry.io/otel"
@@ -17,11 +18,23 @@ import (
1718
sdktrace "go.opentelemetry.io/otel/sdk/trace"
1819
)
1920

21+
var (
22+
useOTelCounters atomic.Bool
23+
)
24+
25+
// ForceOTelCounters enables monotonic OTel counters for otelStatter instances
26+
// created after this call. Call it before creating statters to change the
27+
// global default.
28+
func ForceOTelCounters() {
29+
useOTelCounters.Store(true)
30+
}
31+
2032
type otelStatter struct {
21-
meter otelmetric.Meter
22-
meterProvider *sdkmetric.MeterProvider
23-
prefix string
24-
useCounters bool
33+
meter otelmetric.Meter
34+
meterProvider *sdkmetric.MeterProvider
35+
prefix string
36+
useCounters bool
37+
effectiveUseOTelCounters bool
2538

2639
mu sync.RWMutex
2740
counters map[string]otelmetric.Int64Counter
@@ -30,6 +43,10 @@ type otelStatter struct {
3043
histograms map[string]otelmetric.Float64Histogram
3144
}
3245

46+
func (s *otelStatter) shouldUseOTelCounters() bool {
47+
return s.effectiveUseOTelCounters
48+
}
49+
3350
func newOTELResource(baseTags []string) *resource.Resource {
3451
attrs := []attribute.KeyValue{}
3552
for _, tag := range baseTags {
@@ -70,14 +87,15 @@ func newOTELStatter(endpoint, prefix string, insecure bool, headers map[string]s
7087
otel.SetMeterProvider(mp)
7188

7289
return &otelStatter{
73-
meter: mp.Meter(prefix),
74-
meterProvider: mp,
75-
prefix: prefix,
76-
useCounters: useCounters,
77-
counters: make(map[string]otelmetric.Int64Counter),
78-
updownCounters: make(map[string]otelmetric.Int64UpDownCounter),
79-
gauges: make(map[string]otelmetric.Float64Gauge),
80-
histograms: make(map[string]otelmetric.Float64Histogram),
90+
meter: mp.Meter(prefix),
91+
meterProvider: mp,
92+
prefix: prefix,
93+
useCounters: useCounters,
94+
effectiveUseOTelCounters: useCounters || useOTelCounters.Load(),
95+
counters: make(map[string]otelmetric.Int64Counter),
96+
updownCounters: make(map[string]otelmetric.Int64UpDownCounter),
97+
gauges: make(map[string]otelmetric.Float64Gauge),
98+
histograms: make(map[string]otelmetric.Float64Histogram),
8199
}, nil
82100
}
83101

@@ -204,7 +222,7 @@ func (s *otelStatter) getHistogram(name string) (otelmetric.Float64Histogram, er
204222
}
205223

206224
func (s *otelStatter) Count(name string, value int64, tags []string, rate float64) error {
207-
if s.useCounters {
225+
if s.shouldUseOTelCounters() {
208226
if value < 0 {
209227
return fmt.Errorf("counter value must be non-negative")
210228
}
@@ -224,7 +242,7 @@ func (s *otelStatter) Count(name string, value int64, tags []string, rate float6
224242
}
225243

226244
func (s *otelStatter) Incr(name string, tags []string, rate float64) error {
227-
if s.useCounters {
245+
if s.shouldUseOTelCounters() {
228246
c, err := s.getCounter(name)
229247
if err != nil {
230248
return err

0 commit comments

Comments
 (0)