Compare commits

...

5 Commits

Author SHA1 Message Date
8fcc23f639 fixup tracing
Some checks failed
build / test (push) Failing after 1m46s
codeql / analyze (go) (push) Failing after 1m45s
build / lint (push) Successful in 9m12s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-06 07:30:17 +03:00
25dda1f34c fixup tracing
Some checks failed
build / test (push) Failing after 1m31s
codeql / analyze (go) (push) Failing after 1m49s
build / lint (push) Successful in 9m17s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-05 20:20:34 +03:00
fe66086c40 fixup tracing
Some checks failed
build / test (push) Failing after 2m10s
codeql / analyze (go) (push) Failing after 2m7s
build / lint (push) Successful in 9m15s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-05 16:20:05 +03:00
7329bc23bc export lag for all partition, not only owned
Some checks failed
build / test (push) Failing after 1m14s
build / lint (push) Successful in 9m28s
codeql / analyze (go) (push) Failing after 14m55s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-02 23:01:04 +03:00
c240631cdb fixup panic
Some checks failed
build / test (push) Failing after 1m32s
codeql / analyze (go) (push) Failing after 2m37s
build / lint (push) Successful in 9m31s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-02 10:32:33 +03:00
4 changed files with 58 additions and 68 deletions

View File

@@ -1,12 +1,14 @@
package kgo package kgo
import ( import (
"context"
"sync" "sync"
"go.unistack.org/micro/v3/broker" "go.unistack.org/micro/v3/broker"
) )
type event struct { type event struct {
ctx context.Context
topic string topic string
err error err error
sync.RWMutex sync.RWMutex
@@ -14,6 +16,10 @@ type event struct {
ack bool ack bool
} }
func (p *event) Context() context.Context {
return p.ctx
}
func (p *event) Topic() string { func (p *event) Topic() string {
return p.topic return p.topic
} }

30
kgo.go
View File

@@ -73,7 +73,7 @@ func (k *Broker) Name() string {
return k.opts.Name return k.opts.Name
} }
func (k *Broker) connect(ctx context.Context, opts ...kgo.Opt) (*kgo.Client, error) { func (k *Broker) connect(ctx context.Context, opts ...kgo.Opt) (*kgo.Client, *hookTracer, error) {
var c *kgo.Client var c *kgo.Client
var err error var err error
@@ -90,28 +90,33 @@ func (k *Broker) connect(ctx context.Context, opts ...kgo.Opt) (*kgo.Client, err
} }
} }
htracer := &hookTracer{group: group, clientID: clientID, tracer: k.opts.Tracer}
opts = append(opts, opts = append(opts,
kgo.WithHooks(&hookMeter{meter: k.opts.Meter}), kgo.WithHooks(&hookMeter{meter: k.opts.Meter}),
kgo.WithHooks(&hookTracer{group: group, clientID: clientID, tracer: k.opts.Tracer}), kgo.WithHooks(htracer),
) )
select { select {
case <-ctx.Done(): case <-ctx.Done():
if ctx.Err() != nil { if ctx.Err() != nil {
sp.SetStatus(tracer.SpanStatusError, ctx.Err().Error()) if sp != nil {
sp.SetStatus(tracer.SpanStatusError, ctx.Err().Error())
}
} }
return nil, ctx.Err() return nil, nil, ctx.Err()
default: default:
c, err = kgo.NewClient(opts...) c, err = kgo.NewClient(opts...)
if err == nil { if err == nil {
err = c.Ping(ctx) // check connectivity to cluster err = c.Ping(ctx) // check connectivity to cluster
} }
if err != nil { if err != nil {
sp.SetStatus(tracer.SpanStatusError, err.Error()) if sp != nil {
return nil, err sp.SetStatus(tracer.SpanStatusError, err.Error())
}
return nil, nil, err
} }
} }
return c, nil return c, htracer, nil
} }
func (k *Broker) Connect(ctx context.Context) error { func (k *Broker) Connect(ctx context.Context) error {
@@ -127,7 +132,7 @@ func (k *Broker) Connect(ctx context.Context) error {
nctx = ctx nctx = ctx
} }
c, err := k.connect(nctx, k.kopts...) c, _, err := k.connect(nctx, k.kopts...)
if err != nil { if err != nil {
return err return err
} }
@@ -230,13 +235,9 @@ func (k *Broker) Publish(ctx context.Context, topic string, msg *broker.Message,
} }
func (k *Broker) publish(ctx context.Context, msgs []*broker.Message, opts ...broker.PublishOption) error { func (k *Broker) publish(ctx context.Context, msgs []*broker.Message, opts ...broker.PublishOption) error {
var span tracer.Span
ctx, span = k.opts.Tracer.Start(ctx, "Publish")
defer span.Finish()
k.Lock() k.Lock()
if !k.connected { if !k.connected {
c, err := k.connect(ctx, k.kopts...) c, _, err := k.connect(ctx, k.kopts...)
if err != nil { if err != nil {
k.Unlock() k.Unlock()
return err return err
@@ -370,7 +371,7 @@ func (k *Broker) Subscribe(ctx context.Context, topic string, handler broker.Han
} }
} }
c, err := k.connect(ctx, kopts...) c, htracer, err := k.connect(ctx, kopts...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -388,6 +389,7 @@ func (k *Broker) Subscribe(ctx context.Context, topic string, handler broker.Han
} }
sub.c = c sub.c = c
sub.htracer = htracer
go sub.poll(ctx) go sub.poll(ctx)

View File

@@ -12,6 +12,7 @@ import (
"go.unistack.org/micro/v3/logger" "go.unistack.org/micro/v3/logger"
"go.unistack.org/micro/v3/metadata" "go.unistack.org/micro/v3/metadata"
"go.unistack.org/micro/v3/semconv" "go.unistack.org/micro/v3/semconv"
"go.unistack.org/micro/v3/tracer"
) )
type tp struct { type tp struct {
@@ -23,6 +24,7 @@ type consumer struct {
c *kgo.Client c *kgo.Client
topic string topic string
partition int32 partition int32
htracer *hookTracer
opts broker.SubscribeOptions opts broker.SubscribeOptions
kopts broker.Options kopts broker.Options
handler broker.Handler handler broker.Handler
@@ -34,6 +36,7 @@ type consumer struct {
type subscriber struct { type subscriber struct {
c *kgo.Client c *kgo.Client
topic string topic string
htracer *hookTracer
opts broker.SubscribeOptions opts broker.SubscribeOptions
kopts broker.Options kopts broker.Options
handler broker.Handler handler broker.Handler
@@ -106,10 +109,8 @@ func (s *subscriber) poll(ctx context.Context) {
} }
s.Lock() s.Lock()
for tp := range s.consumers { for p, l := range lmap {
if v, ok := lmap[tp.p]; ok { s.kopts.Meter.Counter(semconv.BrokerGroupLag, "topic", s.topic, "group", s.opts.Group, "partition", strconv.Itoa(int(p)), "lag", strconv.Itoa(int(l.Lag)))
s.kopts.Meter.Counter(semconv.BrokerGroupLag, "topic", s.topic, "group", s.opts.Group, "partition", strconv.Itoa(int(tp.p)), "lag", strconv.Itoa(int(v.Lag)))
}
} }
s.Unlock() s.Unlock()
@@ -180,13 +181,13 @@ func (s *subscriber) assigned(_ context.Context, c *kgo.Client, assigned map[str
c: c, c: c,
topic: topic, topic: topic,
partition: partition, partition: partition,
htracer: s.htracer,
quit: make(chan struct{}), quit: make(chan struct{}),
done: make(chan struct{}), done: make(chan struct{}),
recs: make(chan kgo.FetchTopicPartition, 100), recs: make(chan kgo.FetchTopicPartition, 100),
handler: s.handler, handler: s.handler,
kopts: s.kopts, kopts: s.kopts,
opts: s.opts, opts: s.opts,
} }
s.Lock() s.Lock()
s.consumers[tp{topic, partition}] = pc s.consumers[tp{topic, partition}] = pc
@@ -212,6 +213,7 @@ func (pc *consumer) consume() {
return return
case p := <-pc.recs: case p := <-pc.recs:
for _, record := range p.Records { for _, record := range p.Records {
ctx, sp := pc.htracer.WithProcessSpan(record)
ts := time.Now() ts := time.Now()
pc.kopts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", record.Topic, "topic", record.Topic).Inc() pc.kopts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", record.Topic, "topic", record.Topic).Inc()
p := eventPool.Get().(*event) p := eventPool.Get().(*event)
@@ -221,6 +223,7 @@ func (pc *consumer) consume() {
p.err = nil p.err = nil
p.ack = false p.ack = false
p.msg.Header = metadata.New(len(record.Headers)) p.msg.Header = metadata.New(len(record.Headers))
p.ctx = ctx
for _, hdr := range record.Headers { for _, hdr := range record.Headers {
p.msg.Header.Set(hdr.Key, string(hdr.Value)) p.msg.Header.Set(hdr.Key, string(hdr.Value))
} }
@@ -229,7 +232,11 @@ func (pc *consumer) consume() {
} else if pc.opts.BodyOnly { } else if pc.opts.BodyOnly {
p.msg.Body = record.Value p.msg.Body = record.Value
} else { } else {
if err := pc.kopts.Codec.Unmarshal(record.Value, p.msg); err != nil { sp.AddEvent("codec unmarshal start")
err := pc.kopts.Codec.Unmarshal(record.Value, p.msg)
sp.AddEvent("codec unmarshal stop")
if err != nil {
sp.SetStatus(tracer.SpanStatusError, err.Error())
pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "failure").Inc() pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "failure").Inc()
p.err = err p.err = err
p.msg.Body = record.Value p.msg.Body = record.Value
@@ -259,13 +266,17 @@ func (pc *consumer) consume() {
pc.kopts.Meter.Histogram(semconv.SubscribeMessageDurationSeconds, "endpoint", record.Topic, "topic", record.Topic).Update(te.Seconds()) pc.kopts.Meter.Histogram(semconv.SubscribeMessageDurationSeconds, "endpoint", record.Topic, "topic", record.Topic).Update(te.Seconds())
eventPool.Put(p) eventPool.Put(p)
pc.kopts.Logger.Fatalf(pc.kopts.Context, "[kgo] Unmarshal err not handled wtf?") pc.kopts.Logger.Fatalf(pc.kopts.Context, "[kgo] Unmarshal err not handled wtf?")
sp.Finish()
return return
} }
} }
sp.AddEvent("handler start")
err := pc.handler(p) err := pc.handler(p)
sp.AddEvent("handler stop")
if err == nil { if err == nil {
pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "success").Inc() pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "success").Inc()
} else { } else {
sp.SetStatus(tracer.SpanStatusError, err.Error())
pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "failure").Inc() pc.kopts.Meter.Counter(semconv.SubscribeMessageTotal, "endpoint", record.Topic, "topic", record.Topic, "status", "failure").Inc()
} }
pc.kopts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", record.Topic, "topic", record.Topic).Dec() pc.kopts.Meter.Counter(semconv.SubscribeMessageInflight, "endpoint", record.Topic, "topic", record.Topic).Dec()
@@ -274,7 +285,9 @@ func (pc *consumer) consume() {
} else if err != nil { } else if err != nil {
p.err = err p.err = err
if eh != nil { if eh != nil {
sp.AddEvent("error handler start")
_ = eh(p) _ = eh(p)
sp.AddEvent("error handler stop")
} else { } else {
if pc.kopts.Logger.V(logger.ErrorLevel) { if pc.kopts.Logger.V(logger.ErrorLevel) {
pc.kopts.Logger.Errorf(pc.kopts.Context, "[kgo]: subscriber error: %v", err) pc.kopts.Logger.Errorf(pc.kopts.Context, "[kgo]: subscriber error: %v", err)
@@ -290,8 +303,11 @@ func (pc *consumer) consume() {
} else { } else {
eventPool.Put(p) eventPool.Put(p)
pc.kopts.Logger.Fatalf(pc.kopts.Context, "[kgo] ErrLostMessage wtf?") pc.kopts.Logger.Fatalf(pc.kopts.Context, "[kgo] ErrLostMessage wtf?")
sp.SetStatus(tracer.SpanStatusError, "ErrLostMessage")
sp.Finish()
return return
} }
sp.Finish()
} }
} }
} }

View File

@@ -2,8 +2,6 @@ package kgo
import ( import (
"context" "context"
"net"
"time"
"unicode/utf8" "unicode/utf8"
"github.com/twmb/franz-go/pkg/kgo" "github.com/twmb/franz-go/pkg/kgo"
@@ -18,40 +16,12 @@ type hookTracer struct {
} }
var ( var (
_ kgo.HookBrokerConnect = &hookTracer{} _ kgo.HookProduceRecordBuffered = (*hookTracer)(nil)
_ kgo.HookBrokerDisconnect = &hookTracer{} _ kgo.HookProduceRecordUnbuffered = (*hookTracer)(nil)
_ kgo.HookBrokerRead = &hookTracer{} _ kgo.HookFetchRecordBuffered = (*hookTracer)(nil)
_ kgo.HookBrokerThrottle = &hookTracer{} _ kgo.HookFetchRecordUnbuffered = (*hookTracer)(nil)
_ kgo.HookBrokerWrite = &hookTracer{}
_ kgo.HookFetchBatchRead = &hookTracer{}
_ kgo.HookProduceBatchWritten = &hookTracer{}
_ kgo.HookGroupManageError = &hookTracer{}
) )
func (m *hookTracer) OnGroupManageError(err error) {
}
func (m *hookTracer) OnBrokerConnect(meta kgo.BrokerMetadata, _ time.Duration, _ net.Conn, err error) {
}
func (m *hookTracer) OnBrokerDisconnect(meta kgo.BrokerMetadata, _ net.Conn) {
}
func (m *hookTracer) OnBrokerWrite(meta kgo.BrokerMetadata, _ int16, bytesWritten int, writeWait, timeToWrite time.Duration, err error) {
}
func (m *hookTracer) OnBrokerRead(meta kgo.BrokerMetadata, _ int16, bytesRead int, readWait, timeToRead time.Duration, err error) {
}
func (m *hookTracer) OnBrokerThrottle(meta kgo.BrokerMetadata, throttleInterval time.Duration, _ bool) {
}
func (m *hookTracer) OnProduceBatchWritten(meta kgo.BrokerMetadata, topic string, _ int32, kmetrics kgo.ProduceBatchMetrics) {
}
func (m *hookTracer) OnFetchBatchRead(meta kgo.BrokerMetadata, topic string, _ int32, kmetrics kgo.FetchBatchMetrics) {
}
// OnProduceRecordBuffered starts a new span for the "publish" operation on a // OnProduceRecordBuffered starts a new span for the "publish" operation on a
// buffered record. // buffered record.
// //
@@ -88,17 +58,14 @@ func (m *hookTracer) OnProduceRecordBuffered(r *kgo.Record) {
// It sets attributes with values unset when producing and records any error // It sets attributes with values unset when producing and records any error
// that occurred during the publish operation. // that occurred during the publish operation.
func (m *hookTracer) OnProduceRecordUnbuffered(r *kgo.Record, err error) { func (m *hookTracer) OnProduceRecordUnbuffered(r *kgo.Record, err error) {
span, ok := tracer.SpanFromContext(r.Context) span, _ := tracer.SpanFromContext(r.Context)
if !ok {
return
}
defer span.Finish()
span.AddLabels( span.AddLabels(
semconv.MessagingKafkaDestinationPartition(int(r.Partition)), semconv.MessagingKafkaDestinationPartition(int(r.Partition)),
) )
if err != nil { if err != nil {
span.SetStatus(tracer.SpanStatusError, err.Error()) span.SetStatus(tracer.SpanStatusError, err.Error())
} }
span.Finish()
} }
// OnFetchRecordBuffered starts a new span for the "receive" operation on a // OnFetchRecordBuffered starts a new span for the "receive" operation on a
@@ -143,9 +110,8 @@ func (m *hookTracer) OnFetchRecordBuffered(r *kgo.Record) {
// OnFetchRecordUnbuffered continues and ends the "receive" span for an // OnFetchRecordUnbuffered continues and ends the "receive" span for an
// unbuffered record. // unbuffered record.
func (m *hookTracer) OnFetchRecordUnbuffered(r *kgo.Record, _ bool) { func (m *hookTracer) OnFetchRecordUnbuffered(r *kgo.Record, _ bool) {
if span, ok := tracer.SpanFromContext(r.Context); ok { span, _ := tracer.SpanFromContext(r.Context)
defer span.Finish() span.Finish()
}
} }
// WithProcessSpan starts a new span for the "process" operation on a consumer // WithProcessSpan starts a new span for the "process" operation on a consumer