Compare commits
	
		
			2 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d830f70157 | |||
| 581fecd8f1 | 
							
								
								
									
										20
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								go.mod
									
									
									
									
									
								
							@@ -1,17 +1,17 @@
 | 
				
			|||||||
module go.unistack.org/micro-broker-kgo/v3
 | 
					module go.unistack.org/micro-broker-kgo/v3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.23.8
 | 
					go 1.24.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
toolchain go1.24.3
 | 
					toolchain go1.24.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/google/uuid v1.6.0
 | 
						github.com/google/uuid v1.6.0
 | 
				
			||||||
	github.com/stretchr/testify v1.10.0
 | 
						github.com/stretchr/testify v1.11.1
 | 
				
			||||||
	github.com/twmb/franz-go v1.19.5
 | 
						github.com/twmb/franz-go v1.19.5
 | 
				
			||||||
	github.com/twmb/franz-go/pkg/kadm v1.16.0
 | 
						github.com/twmb/franz-go/pkg/kadm v1.16.1
 | 
				
			||||||
	github.com/twmb/franz-go/pkg/kmsg v1.11.2
 | 
						github.com/twmb/franz-go/pkg/kmsg v1.11.2
 | 
				
			||||||
	go.opentelemetry.io/otel v1.34.0
 | 
						go.opentelemetry.io/otel v1.38.0
 | 
				
			||||||
	go.unistack.org/micro/v3 v3.11.44
 | 
						go.unistack.org/micro/v3 v3.11.45
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
@@ -23,10 +23,10 @@ require (
 | 
				
			|||||||
	github.com/pierrec/lz4/v4 v4.1.22 // indirect
 | 
						github.com/pierrec/lz4/v4 v4.1.22 // indirect
 | 
				
			||||||
	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 | 
						github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
 | 
				
			||||||
	go.unistack.org/micro-proto/v3 v3.4.1 // indirect
 | 
						go.unistack.org/micro-proto/v3 v3.4.1 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.38.0 // indirect
 | 
						golang.org/x/crypto v0.43.0 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.33.0 // indirect
 | 
						golang.org/x/sys v0.37.0 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 // indirect
 | 
						google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff // indirect
 | 
				
			||||||
	google.golang.org/grpc v1.70.0 // indirect
 | 
						google.golang.org/grpc v1.76.0 // indirect
 | 
				
			||||||
	google.golang.org/protobuf v1.36.5 // indirect
 | 
						google.golang.org/protobuf v1.36.10 // indirect
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										48
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								go.sum
									
									
									
									
									
								
							@@ -7,8 +7,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
 | 
				
			|||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
					github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
				
			||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
					github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
				
			||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 | 
					github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 | 
				
			||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
					github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 | 
				
			||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
					github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
				
			||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
					github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
				
			||||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
 | 
					github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
 | 
				
			||||||
@@ -27,34 +27,34 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
 | 
				
			|||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 | 
					github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 | 
					github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 | 
					github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
 | 
				
			||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 | 
					github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
 | 
				
			||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
					github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
 | 
				
			||||||
github.com/twmb/franz-go v1.19.5 h1:W7+o8D0RsQsedqib71OVlLeZ0zI6CbFra7yTYhZTs5Y=
 | 
					github.com/twmb/franz-go v1.19.5 h1:W7+o8D0RsQsedqib71OVlLeZ0zI6CbFra7yTYhZTs5Y=
 | 
				
			||||||
github.com/twmb/franz-go v1.19.5/go.mod h1:4kFJ5tmbbl7asgwAGVuyG1ZMx0NNpYk7EqflvWfPCpM=
 | 
					github.com/twmb/franz-go v1.19.5/go.mod h1:4kFJ5tmbbl7asgwAGVuyG1ZMx0NNpYk7EqflvWfPCpM=
 | 
				
			||||||
github.com/twmb/franz-go/pkg/kadm v1.16.0 h1:STMs1t5lYR5mR974PSiwNzE5TvsosByTp+rKXLOhAjE=
 | 
					github.com/twmb/franz-go/pkg/kadm v1.16.1 h1:IEkrhTljgLHJ0/hT/InhXGjPdmWfFvxp7o/MR7vJ8cw=
 | 
				
			||||||
github.com/twmb/franz-go/pkg/kadm v1.16.0/go.mod h1:MUdcUtnf9ph4SFBLLA/XxE29rvLhWYLM9Ygb8dfSCvw=
 | 
					github.com/twmb/franz-go/pkg/kadm v1.16.1/go.mod h1:Ue/ye1cc9ipsQFg7udFbbGiFNzQMqiH73fGC2y0rwyc=
 | 
				
			||||||
github.com/twmb/franz-go/pkg/kmsg v1.11.2 h1:hIw75FpwcAjgeyfIGFqivAvwC5uNIOWRGvQgZhH4mhg=
 | 
					github.com/twmb/franz-go/pkg/kmsg v1.11.2 h1:hIw75FpwcAjgeyfIGFqivAvwC5uNIOWRGvQgZhH4mhg=
 | 
				
			||||||
github.com/twmb/franz-go/pkg/kmsg v1.11.2/go.mod h1:CFfkkLysDNmukPYhGzuUcDtf46gQSqCZHMW1T4Z+wDE=
 | 
					github.com/twmb/franz-go/pkg/kmsg v1.11.2/go.mod h1:CFfkkLysDNmukPYhGzuUcDtf46gQSqCZHMW1T4Z+wDE=
 | 
				
			||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
 | 
					go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
 | 
				
			||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
 | 
					go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
 | 
				
			||||||
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
 | 
					go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
 | 
				
			||||||
go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
 | 
					go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
 | 
				
			||||||
go.unistack.org/micro/v3 v3.11.44 h1:A+T8zVcL2vlL66kn/Y4rqhtBybLO829wFEYZJYorDOU=
 | 
					go.unistack.org/micro/v3 v3.11.45 h1:fjTLZYWgsVf9FIMZBxOg8ios2/tmyimnjZrsrxEUeXU=
 | 
				
			||||||
go.unistack.org/micro/v3 v3.11.44/go.mod h1:13EFW2ps3BN9mpYbp9K0oQu/VDjEN6LJ4wwdom7hcXQ=
 | 
					go.unistack.org/micro/v3 v3.11.45/go.mod h1:fDQ8Mu9wubaFP0L8hNQlpzHiEnWN0wbOlawN9HYo0N4=
 | 
				
			||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
 | 
					golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
 | 
				
			||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
 | 
					golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
 | 
				
			||||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
 | 
					golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM=
 | 
				
			||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
 | 
					golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
 | 
				
			||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
 | 
					golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
 | 
				
			||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
					golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
 | 
				
			||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
 | 
					golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
 | 
				
			||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
 | 
					golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99 h1:ZSlhAUqC4r8TPzqLXQ0m3upBNZeF+Y8jQ3c4CR3Ujms=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff h1:A90eA31Wq6HOMIQlLfzFwzqGKBTuaVztYu/g8sn+8Zc=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250224174004-546df14abb99/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20251007200510-49b9836ed3ff/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
 | 
				
			||||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
 | 
					google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
 | 
				
			||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
 | 
					google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
 | 
				
			||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
 | 
					google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
 | 
				
			||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 | 
					google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
					gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										82
									
								
								kgo.go
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								kgo.go
									
									
									
									
									
								
							@@ -6,12 +6,14 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"math/rand/v2"
 | 
						"math/rand/v2"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"sync/atomic"
 | 
						"sync/atomic"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
 | 
						"github.com/twmb/franz-go/pkg/kadm"
 | 
				
			||||||
	"github.com/twmb/franz-go/pkg/kgo"
 | 
						"github.com/twmb/franz-go/pkg/kgo"
 | 
				
			||||||
	"github.com/twmb/franz-go/pkg/kmsg"
 | 
						"github.com/twmb/franz-go/pkg/kmsg"
 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
						"go.unistack.org/micro/v3/broker"
 | 
				
			||||||
@@ -66,7 +68,7 @@ type Broker struct {
 | 
				
			|||||||
	subs  []*Subscriber
 | 
						subs  []*Subscriber
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	opts broker.Options
 | 
						opts broker.Options
 | 
				
			||||||
	sync.RWMutex
 | 
						mu   sync.RWMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init bool
 | 
						init bool
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -184,10 +186,72 @@ func (k *Broker) Connect(ctx context.Context) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	k.Lock()
 | 
						k.mu.Lock()
 | 
				
			||||||
	k.c = c
 | 
						k.c = c
 | 
				
			||||||
	k.connected.Store(1)
 | 
						k.connected.Store(1)
 | 
				
			||||||
	k.Unlock()
 | 
						k.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						exposeLag := false
 | 
				
			||||||
 | 
						if k.opts.Context != nil {
 | 
				
			||||||
 | 
							if v, ok := k.opts.Context.Value(exposeLagKey{}).(bool); ok && v {
 | 
				
			||||||
 | 
								exposeLag = v
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if exposeLag {
 | 
				
			||||||
 | 
							var mu sync.Mutex
 | 
				
			||||||
 | 
							var lastUpdate time.Time
 | 
				
			||||||
 | 
							type pl struct {
 | 
				
			||||||
 | 
								p string
 | 
				
			||||||
 | 
								l float64
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							lag := make(map[string]map[string]pl) // topic => group => partition => lag
 | 
				
			||||||
 | 
							ac := kadm.NewClient(k.c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							updateStats := func() {
 | 
				
			||||||
 | 
								mu.Lock()
 | 
				
			||||||
 | 
								if time.Since(lastUpdate) < DefaultStatsInterval {
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								k.mu.Lock()
 | 
				
			||||||
 | 
								groups := make([]string, 0, len(k.subs))
 | 
				
			||||||
 | 
								for _, g := range k.subs {
 | 
				
			||||||
 | 
									groups = append(groups, g.opts.Group)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								k.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								dgls, err := ac.Lag(ctx, groups...)
 | 
				
			||||||
 | 
								if err != nil || !dgls.Ok() {
 | 
				
			||||||
 | 
									k.opts.Logger.Error(k.opts.Context, "kgo describe group lag error", err)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								for gn, dgl := range dgls {
 | 
				
			||||||
 | 
									for tn, lmap := range dgl.Lag {
 | 
				
			||||||
 | 
										if _, ok := lag[tn]; !ok {
 | 
				
			||||||
 | 
											lag[tn] = make(map[string]pl)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										for p, l := range lmap {
 | 
				
			||||||
 | 
											lag[tn][gn] = pl{p: strconv.Itoa(int(p)), l: float64(l.Lag)}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for tn, dg := range lag {
 | 
				
			||||||
 | 
								for gn, gl := range dg {
 | 
				
			||||||
 | 
									k.opts.Meter.Gauge(semconv.BrokerGroupLag,
 | 
				
			||||||
 | 
										func() float64 { updateStats(); return gl.l },
 | 
				
			||||||
 | 
										"topic", tn,
 | 
				
			||||||
 | 
										"group", gn,
 | 
				
			||||||
 | 
										"partition", gl.p)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -205,8 +269,8 @@ func (k *Broker) Disconnect(ctx context.Context) error {
 | 
				
			|||||||
	ctx, span = k.opts.Tracer.Start(ctx, "Disconnect")
 | 
						ctx, span = k.opts.Tracer.Start(ctx, "Disconnect")
 | 
				
			||||||
	defer span.Finish()
 | 
						defer span.Finish()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	k.Lock()
 | 
						k.mu.Lock()
 | 
				
			||||||
	defer k.Unlock()
 | 
						defer k.mu.Unlock()
 | 
				
			||||||
	select {
 | 
						select {
 | 
				
			||||||
	case <-nctx.Done():
 | 
						case <-nctx.Done():
 | 
				
			||||||
		return nctx.Err()
 | 
							return nctx.Err()
 | 
				
			||||||
@@ -231,8 +295,8 @@ func (k *Broker) Disconnect(ctx context.Context) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (k *Broker) Init(opts ...broker.Option) error {
 | 
					func (k *Broker) Init(opts ...broker.Option) error {
 | 
				
			||||||
	k.Lock()
 | 
						k.mu.Lock()
 | 
				
			||||||
	defer k.Unlock()
 | 
						defer k.mu.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(opts) == 0 && k.init {
 | 
						if len(opts) == 0 && k.init {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -455,9 +519,9 @@ func (k *Broker) Subscribe(ctx context.Context, topic string, handler broker.Han
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	go sub.poll(ctx)
 | 
						go sub.poll(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	k.Lock()
 | 
						k.mu.Lock()
 | 
				
			||||||
	k.subs = append(k.subs, sub)
 | 
						k.subs = append(k.subs, sub)
 | 
				
			||||||
	k.Unlock()
 | 
						k.mu.Unlock()
 | 
				
			||||||
	return sub, nil
 | 
						return sub, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										32
									
								
								meter.go
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								meter.go
									
									
									
									
									
								
							@@ -32,27 +32,27 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	metricBrokerConnects    = "broker_connects_total"
 | 
						metricBrokerConnects    = "micro_broker_connects_total"
 | 
				
			||||||
	metricBrokerDisconnects = "broker_disconnects_total"
 | 
						metricBrokerDisconnects = "micro_broker_disconnects_total"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricBrokerWriteErrors        = "broker_write_errors_total"
 | 
						metricBrokerWriteErrors        = "micro_broker_write_errors_total"
 | 
				
			||||||
	metricBrokerWriteBytes         = "broker_write_bytes_total"
 | 
						metricBrokerWriteBytes         = "micro_broker_write_bytes_total"
 | 
				
			||||||
	metricBrokerWriteWaitLatencies = "broker_write_wait_latencies"
 | 
						metricBrokerWriteWaitLatencies = "micro_broker_write_wait_latencies"
 | 
				
			||||||
	metricBrokerWriteLatencies     = "broker_write_latencies"
 | 
						metricBrokerWriteLatencies     = "micro_broker_write_latencies"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricBrokerReadErrors        = "broker_read_errors_total"
 | 
						metricBrokerReadErrors        = "micro_broker_read_errors_total"
 | 
				
			||||||
	metricBrokerReadBytes         = "broker_read_bytes_total"
 | 
						metricBrokerReadBytes         = "micro_broker_read_bytes_total"
 | 
				
			||||||
	metricBrokerReadWaitLatencies = "broker_read_wait_latencies"
 | 
						metricBrokerReadWaitLatencies = "micro_broker_read_wait_latencies"
 | 
				
			||||||
	metricBrokerReadLatencies     = "broker_read_latencies"
 | 
						metricBrokerReadLatencies     = "micro_broker_read_latencies"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricBrokerThrottleLatencies = "broker_throttle_latencies"
 | 
						metricBrokerThrottleLatencies = "micro_broker_throttle_latencies"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricBrokerProduceBytesCompressed   = "broker_produce_bytes_compressed_total"
 | 
						metricBrokerProduceBytesCompressed   = "micro_broker_produce_bytes_compressed_total"
 | 
				
			||||||
	metricBrokerProduceBytesUncompressed = "broker_produce_bytes_uncompressed_total"
 | 
						metricBrokerProduceBytesUncompressed = "micro_broker_produce_bytes_uncompressed_total"
 | 
				
			||||||
	metricBrokerFetchBytesCompressed     = "broker_consume_bytes_compressed_total"
 | 
						metricBrokerFetchBytesCompressed     = "micro_broker_consume_bytes_compressed_total"
 | 
				
			||||||
	metricBrokerFetchBytesUncompressed   = "broker_consume_bytes_uncompressed_total"
 | 
						metricBrokerFetchBytesUncompressed   = "micro_broker_consume_bytes_uncompressed_total"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	metricBrokerGroupErrors = "broker_group_errors_total"
 | 
						metricBrokerGroupErrors = "micro_broker_group_errors_total"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	labelNode    = "node_id"
 | 
						labelNode    = "node_id"
 | 
				
			||||||
	labelSuccess = "success"
 | 
						labelSuccess = "success"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,7 @@ var (
 | 
				
			|||||||
	DefaultCommitInterval = 5 * time.Second
 | 
						DefaultCommitInterval = 5 * time.Second
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// DefaultStatsInterval specifies how fast check consumer lag
 | 
						// DefaultStatsInterval specifies how fast check consumer lag
 | 
				
			||||||
	DefaultStatsInterval = 5 * time.Second
 | 
						DefaultStatsInterval = 30 * time.Second
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// DefaultSubscribeMaxInflight specifies how much messages keep inflight
 | 
						// DefaultSubscribeMaxInflight specifies how much messages keep inflight
 | 
				
			||||||
	DefaultSubscribeMaxInflight = 100
 | 
						DefaultSubscribeMaxInflight = 100
 | 
				
			||||||
@@ -120,3 +120,10 @@ func PublishPromise(fn func(*kgo.Record, error)) broker.PublishOption {
 | 
				
			|||||||
func ClientPublishPromise(fn func(*kgo.Record, error)) client.PublishOption {
 | 
					func ClientPublishPromise(fn func(*kgo.Record, error)) client.PublishOption {
 | 
				
			||||||
	return client.SetPublishOption(publishPromiseKey{}, fn)
 | 
						return client.SetPublishOption(publishPromiseKey{}, fn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type exposeLagKey struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ExposeLag enabled subscriber lag via [meter.Meter]
 | 
				
			||||||
 | 
					func ExposeLag(b bool) broker.Option {
 | 
				
			||||||
 | 
						return broker.SetOption(exposeLagKey{}, b)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,12 +3,10 @@ package kgo
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"sync/atomic"
 | 
						"sync/atomic"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/twmb/franz-go/pkg/kadm"
 | 
					 | 
				
			||||||
	"github.com/twmb/franz-go/pkg/kgo"
 | 
						"github.com/twmb/franz-go/pkg/kgo"
 | 
				
			||||||
	"github.com/twmb/franz-go/pkg/kmsg"
 | 
						"github.com/twmb/franz-go/pkg/kmsg"
 | 
				
			||||||
	"go.unistack.org/micro/v3/broker"
 | 
						"go.unistack.org/micro/v3/broker"
 | 
				
			||||||
@@ -97,46 +95,13 @@ func (s *Subscriber) Unsubscribe(ctx context.Context) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (s *Subscriber) poll(ctx context.Context) {
 | 
					func (s *Subscriber) poll(ctx context.Context) {
 | 
				
			||||||
	maxInflight := DefaultSubscribeMaxInflight
 | 
						maxInflight := DefaultSubscribeMaxInflight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if s.opts.Context != nil {
 | 
						if s.opts.Context != nil {
 | 
				
			||||||
		if n, ok := s.opts.Context.Value(subscribeMaxInflightKey{}).(int); n > 0 && ok {
 | 
							if n, ok := s.opts.Context.Value(subscribeMaxInflightKey{}).(int); n > 0 && ok {
 | 
				
			||||||
			maxInflight = n
 | 
								maxInflight = n
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
					 | 
				
			||||||
		ac := kadm.NewClient(s.c)
 | 
					 | 
				
			||||||
		ticker := time.NewTicker(DefaultStatsInterval)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for {
 | 
					 | 
				
			||||||
			select {
 | 
					 | 
				
			||||||
			case <-ctx.Done():
 | 
					 | 
				
			||||||
				ticker.Stop()
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			case <-ticker.C:
 | 
					 | 
				
			||||||
				dgls, err := ac.Lag(ctx, s.opts.Group)
 | 
					 | 
				
			||||||
				if err != nil || !dgls.Ok() {
 | 
					 | 
				
			||||||
					continue
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				dgl, ok := dgls[s.opts.Group]
 | 
					 | 
				
			||||||
				if !ok {
 | 
					 | 
				
			||||||
					continue
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				lmap, ok := dgl.Lag[s.topic]
 | 
					 | 
				
			||||||
				if !ok {
 | 
					 | 
				
			||||||
					continue
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				s.Lock()
 | 
					 | 
				
			||||||
				for p, l := range lmap {
 | 
					 | 
				
			||||||
					s.kopts.Meter.Counter(semconv.BrokerGroupLag, "topic", s.topic, "group", s.opts.Group, "partition", strconv.Itoa(int(p))).Set(uint64(l.Lag))
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				s.Unlock()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		select {
 | 
							select {
 | 
				
			||||||
		case <-ctx.Done():
 | 
							case <-ctx.Done():
 | 
				
			||||||
@@ -151,7 +116,11 @@ func (s *Subscriber) poll(ctx context.Context) {
 | 
				
			|||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			fetches.EachError(func(t string, p int32, err error) {
 | 
								fetches.EachError(func(t string, p int32, err error) {
 | 
				
			||||||
 | 
									if kgo.IsRetryableBrokerErr(err) {
 | 
				
			||||||
 | 
										s.kopts.Logger.Error(ctx, fmt.Sprintf("[kgo] fetch topic %s partition %d error", t, p), err)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
					s.kopts.Logger.Fatal(ctx, fmt.Sprintf("[kgo] fetch topic %s partition %d error", t, p), err)
 | 
										s.kopts.Logger.Fatal(ctx, fmt.Sprintf("[kgo] fetch topic %s partition %d error", t, p), err)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			fetches.EachPartition(func(p kgo.FetchTopicPartition) {
 | 
								fetches.EachPartition(func(p kgo.FetchTopicPartition) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user