From 0a8a7bef0a516dd2e502d34d37540d9cb96b807a Mon Sep 17 00:00:00 2001 From: mehrotra234 Date: Thu, 3 Oct 2024 20:06:09 +0530 Subject: [PATCH 01/26] update go mod name for eventhub --- pkg/gofr/datasource/pubsub/eventhub/go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gofr/datasource/pubsub/eventhub/go.mod b/pkg/gofr/datasource/pubsub/eventhub/go.mod index a13d76db3..ddf0a7b95 100644 --- a/pkg/gofr/datasource/pubsub/eventhub/go.mod +++ b/pkg/gofr/datasource/pubsub/eventhub/go.mod @@ -1,4 +1,4 @@ -module gofr.dev/pkg/gofr/datasource/pubsub/azeventhub +module gofr.dev/pkg/gofr/datasource/pubsub/eventhub go 1.22.3 From 91b3fec3b7b9213d2187bad1e86f9697bc32316c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 21:56:30 +0000 Subject: [PATCH 02/26] Bump google.golang.org/protobuf from 1.34.2 to 1.35.1 Bumps google.golang.org/protobuf from 1.34.2 to 1.35.1. --- updated-dependencies: - dependency-name: google.golang.org/protobuf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 05f266d07..75dc21ab5 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( golang.org/x/text v0.18.0 google.golang.org/api v0.199.0 google.golang.org/grpc v1.67.0 - google.golang.org/protobuf v1.34.2 + google.golang.org/protobuf v1.35.1 modernc.org/sqlite v1.33.1 ) diff --git a/go.sum b/go.sum index 3747ec8a1..d403ff19e 100644 --- a/go.sum +++ b/go.sum @@ -380,8 +380,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From 705061a044efb44c7df100df161b98d326a5f2b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 05:00:17 +0000 Subject: [PATCH 03/26] Bump golang.org/x/text from 0.18.0 to 0.19.0 Bumps [golang.org/x/text](https://github.com/golang/text) from 0.18.0 to 0.19.0. - [Release notes](https://github.com/golang/text/releases) - [Commits](https://github.com/golang/text/compare/v0.18.0...v0.19.0) --- updated-dependencies: - dependency-name: golang.org/x/text dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 75dc21ab5..e7779dee6 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 golang.org/x/term v0.24.0 - golang.org/x/text v0.18.0 + golang.org/x/text v0.19.0 google.golang.org/api v0.199.0 google.golang.org/grpc v1.67.0 google.golang.org/protobuf v1.35.1 diff --git a/go.sum b/go.sum index d403ff19e..f4c2bf4e8 100644 --- a/go.sum +++ b/go.sum @@ -328,8 +328,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 48c71da047e6395c77a20dd38e7b8b0a53b61981 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 05:06:05 +0000 Subject: [PATCH 04/26] Bump google.golang.org/grpc from 1.67.0 to 1.67.1 Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.67.0 to 1.67.1. - [Release notes](https://github.com/grpc/grpc-go/releases) - [Commits](https://github.com/grpc/grpc-go/compare/v1.67.0...v1.67.1) --- updated-dependencies: - dependency-name: google.golang.org/grpc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index e7779dee6..dbeed5dca 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( golang.org/x/term v0.24.0 golang.org/x/text v0.19.0 google.golang.org/api v0.199.0 - google.golang.org/grpc v1.67.0 + google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 modernc.org/sqlite v1.33.1 ) diff --git a/go.sum b/go.sum index f4c2bf4e8..7bd53ac7f 100644 --- a/go.sum +++ b/go.sum @@ -369,8 +369,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw= -google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From ef45a13a9a28366144372844d07a93af8166d63e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 05:51:19 +0000 Subject: [PATCH 05/26] Bump golang.org/x/term from 0.24.0 to 0.25.0 Bumps [golang.org/x/term](https://github.com/golang/term) from 0.24.0 to 0.25.0. - [Commits](https://github.com/golang/term/compare/v0.24.0...v0.25.0) --- updated-dependencies: - dependency-name: golang.org/x/term dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index dbeed5dca..a72222387 100644 --- a/go.mod +++ b/go.mod @@ -37,7 +37,7 @@ require ( go.uber.org/mock v0.4.0 golang.org/x/oauth2 v0.23.0 golang.org/x/sync v0.8.0 - golang.org/x/term v0.24.0 + golang.org/x/term v0.25.0 golang.org/x/text v0.19.0 google.golang.org/api v0.199.0 google.golang.org/grpc v1.67.1 @@ -90,7 +90,7 @@ require ( go.opentelemetry.io/proto/otlp v1.3.1 // indirect golang.org/x/crypto v0.27.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/sys v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/time v0.6.0 // indirect google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect diff --git a/go.sum b/go.sum index 7bd53ac7f..e22cf2652 100644 --- a/go.sum +++ b/go.sum @@ -312,15 +312,15 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= From cedde5ed35ec61ceb7b7091913ee5f93d0f8d8e9 Mon Sep 17 00:00:00 2001 From: ARYA SINGH Date: Tue, 8 Oct 2024 20:12:52 +0530 Subject: [PATCH 06/26] fixes:[issue 1000]Refactor parseRange function in cron file --- pkg/gofr/cron.go | 57 +++++++++++---------- pkg/gofr/cron_test.go | 112 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 25 deletions(-) diff --git a/pkg/gofr/cron.go b/pkg/gofr/cron.go index 1b40b20c0..67c507246 100644 --- a/pkg/gofr/cron.go +++ b/pkg/gofr/cron.go @@ -136,7 +136,7 @@ func parseSchedule(s string) (*job, error) { return nil, err } - // day/dayOfWeek combination + // day/dayOfWeek combination mergeDays(j) return j, nil @@ -153,17 +153,17 @@ func mergeDays(j *job) { // parsePart parse individual schedule part from schedule string. func parsePart(s string, minValue, maxValue int) (map[int]struct{}, error) { - // wildcard pattern + // wildcard pattern if s == "*" { return getDefaultJobField(minValue, maxValue, 1), nil } - // */2 1-59/5 pattern + // */2 1-59/5 pattern if matches := matchN.FindStringSubmatch(s); matches != nil { return parseSteps(s, matches[1], matches[2], minValue, maxValue) } - // 1,2,4 or 1,2,10-15,20,30-45 pattern + // 1,2,4 or 1,2,10-15,20,30-45 pattern return parseRange(s, minValue, maxValue) } @@ -194,39 +194,45 @@ func parseRange(s string, minValue, maxValue int) (map[int]struct{}, error) { r := make(map[int]struct{}) parts := strings.Split(s, ",") - for _, x := range parts { - rng := matchRange.FindStringSubmatch(x) - - if rng == nil { - i, err := strconv.Atoi(x) - if err != nil { - return nil, errParsing{x, s} - } - - if i < minValue || i > maxValue { - return nil, errOutOfRange{i, s, minValue, maxValue} - } + for _, part := range parts { + if err := parseSingleOrRange(part, minValue, maxValue, r); err != nil { + return nil, err + } + } - r[i] = struct{}{} + if len(r) == 0 { + return nil, errParsing{invalidPart: s} + } - continue - } + return r, nil +} +func parseSingleOrRange(part string, minValue, maxValue int, r map[int]struct{}) error { + if rng := matchRange.FindStringSubmatch(part); rng != nil { localMin, _ := strconv.Atoi(rng[1]) localMax, _ := strconv.Atoi(rng[2]) if localMin < minValue || localMax > maxValue { - return nil, errOutOfRange{x, s, minValue, maxValue} + return errOutOfRange{part, part, minValue, maxValue} } - r = getDefaultJobField(localMin, localMax, 1) - } + for i := localMin; i <= localMax; i++ { + r[i] = struct{}{} + } + } else { + i, err := strconv.Atoi(part) + if err != nil { + return errParsing{part, part} + } - if len(r) == 0 { - return nil, errParsing{invalidPart: s} + if i < minValue || i > maxValue { + return errOutOfRange{part, part, minValue, maxValue} + } + + r[i] = struct{}{} } - return r, nil + return nil } func getDefaultJobField(minValue, maxValue, incr int) map[int]struct{} { @@ -332,6 +338,7 @@ func (c *Crontab) AddJob(schedule, jobName string, fn CronFunc) error { var errBadScheduleFormat = errors.New("schedule string must have five components like * * * * *") // errOutOfRange denotes the errors that occur when a range in schedule is out of scope for the particular time unit. + type errOutOfRange struct { rangeVal interface{} input string diff --git a/pkg/gofr/cron_test.go b/pkg/gofr/cron_test.go index 4ff207852..cdcc7b1fe 100644 --- a/pkg/gofr/cron_test.go +++ b/pkg/gofr/cron_test.go @@ -333,3 +333,115 @@ func Test_noopRequest(t *testing.T) { require.NoError(t, noop.Bind(nil)) assert.Nil(t, noop.Params("test")) } +// New tests for parseRange +func TestCron_parseRange(t *testing.T) { + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Valid Range", + input: "1-5", + expected: map[int]struct{}{ + 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, + }, + min: 1, max: 10, + hasError: false, + }, + { + name: "Out of Range", + input: "1-12", + expected: nil, + min: 1, max: 10, + hasError: true, + }, + { + name: "Invalid Input", + input: "a-b", + expected: nil, + min: 1, max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parseRange(test.input, test.min, test.max) + + if (err != nil) != test.hasError { + t.Errorf("Expected error: %v, got: %v", test.hasError, err) + } + + if len(output) != len(test.expected) { + t.Errorf("Expected: %v, got: %v", test.expected, output) + } + }) + } +} + +// Additional tests for parsePart can be added here... +func TestCron_parsePart(t *testing.T) { + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Single Value", + input: "5", + expected: map[int]struct{}{ + 5: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Valid Multiple Values", + input: "1,3,5", + expected: map[int]struct{}{ + 1: {}, 3: {}, 5: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Invalid Value", + input: "15", + expected: nil, + min: 1, + max: 10, + hasError: true, + }, + { + name: "Invalid Format", + input: "1,2,a", + expected: nil, + min: 1, + max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parsePart(test.input, test.min, test.max) + + if (err != nil) != test.hasError { + t.Errorf("Expected error: %v, got: %v", test.hasError, err) + } + + if len(output) != len(test.expected) { + t.Errorf("Expected: %v, got: %v", test.expected, output) + } + }) + } +} \ No newline at end of file From 15700ab99800829f42bdddf9cb74fd1f464c32d2 Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Tue, 8 Oct 2024 21:27:36 +0530 Subject: [PATCH 07/26] Update cron.go --- pkg/gofr/cron.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkg/gofr/cron.go b/pkg/gofr/cron.go index 67c507246..c849b9792 100644 --- a/pkg/gofr/cron.go +++ b/pkg/gofr/cron.go @@ -136,7 +136,7 @@ func parseSchedule(s string) (*job, error) { return nil, err } - // day/dayOfWeek combination + // day/dayOfWeek combination mergeDays(j) return j, nil @@ -153,17 +153,17 @@ func mergeDays(j *job) { // parsePart parse individual schedule part from schedule string. func parsePart(s string, minValue, maxValue int) (map[int]struct{}, error) { - // wildcard pattern + // wildcard pattern if s == "*" { return getDefaultJobField(minValue, maxValue, 1), nil } - // */2 1-59/5 pattern + // */2 1-59/5 pattern if matches := matchN.FindStringSubmatch(s); matches != nil { return parseSteps(s, matches[1], matches[2], minValue, maxValue) } - // 1,2,4 or 1,2,10-15,20,30-45 pattern + // 1,2,4 or 1,2,10-15,20,30-45 pattern return parseRange(s, minValue, maxValue) } @@ -338,7 +338,6 @@ func (c *Crontab) AddJob(schedule, jobName string, fn CronFunc) error { var errBadScheduleFormat = errors.New("schedule string must have five components like * * * * *") // errOutOfRange denotes the errors that occur when a range in schedule is out of scope for the particular time unit. - type errOutOfRange struct { rangeVal interface{} input string From fbfc5914adbaa72fa0a765a86d9d91664429462e Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Tue, 8 Oct 2024 21:35:47 +0530 Subject: [PATCH 08/26] Update cron_test.go --- pkg/gofr/cron_test.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/pkg/gofr/cron_test.go b/pkg/gofr/cron_test.go index cdcc7b1fe..7dcf27be8 100644 --- a/pkg/gofr/cron_test.go +++ b/pkg/gofr/cron_test.go @@ -333,8 +333,9 @@ func Test_noopRequest(t *testing.T) { require.NoError(t, noop.Bind(nil)) assert.Nil(t, noop.Params("test")) } -// New tests for parseRange + func TestCron_parseRange(t *testing.T) { + tests := []struct { name string input string @@ -371,19 +372,17 @@ func TestCron_parseRange(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { output, err := parseRange(test.input, test.min, test.max) - - if (err != nil) != test.hasError { - t.Errorf("Expected error: %v, got: %v", test.hasError, err) - } - - if len(output) != len(test.expected) { - t.Errorf("Expected: %v, got: %v", test.expected, output) + if test.hasError { + assert.Error(t, err) + } else { + assert.NoError(t, err) } + assert.Len(t, output, len(test.expected)) + assert.Equal(t, test.expected, output) }) } } -// Additional tests for parsePart can be added here... func TestCron_parsePart(t *testing.T) { tests := []struct { name string @@ -431,17 +430,18 @@ func TestCron_parsePart(t *testing.T) { }, } - for _, test := range tests { + for i, test := range tests { t.Run(test.name, func(t *testing.T) { output, err := parsePart(test.input, test.min, test.max) - if (err != nil) != test.hasError { - t.Errorf("Expected error: %v, got: %v", test.hasError, err) + if test.hasError { + assert.Error(t, err, "TEST[%d] - Expected error but got none", i) + } else { + assert.NoError(t, err, "TEST[%d] - Expected no error but got: %v", i, err) } - if len(output) != len(test.expected) { - t.Errorf("Expected: %v, got: %v", test.expected, output) - } + assert.Len(t, output, len(test.expected), "TEST[%d] - Expected length: %v, got: %v", i, len(test.expected), len(output)) + assert.Equal(t, test.expected, output, "TEST[%d] - Expected: %v, got: %v", i, test.expected, output) }) } -} \ No newline at end of file +} From c0faca6a1543d547078dfae3f791136424529a85 Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:11:48 +0530 Subject: [PATCH 09/26] Update cron_test.go --- pkg/gofr/cron_test.go | 173 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 167 insertions(+), 6 deletions(-) diff --git a/pkg/gofr/cron_test.go b/pkg/gofr/cron_test.go index 7dcf27be8..828a35180 100644 --- a/pkg/gofr/cron_test.go +++ b/pkg/gofr/cron_test.go @@ -335,7 +335,6 @@ func Test_noopRequest(t *testing.T) { } func TestCron_parseRange(t *testing.T) { - tests := []struct { name string input string @@ -373,16 +372,178 @@ func TestCron_parseRange(t *testing.T) { t.Run(test.name, func(t *testing.T) { output, err := parseRange(test.input, test.min, test.max) if test.hasError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } + assert.Len(t, output, len(test.expected)) + assert.Equal(t, test.expected, output) }) } } +func TestCron_parseRange_BoundaryValues(t *testing.T) { + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Lower Boundary", + input: "1-1", + expected: map[int]struct{}{ + 1: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Upper Boundary", + input: "10-10", + expected: map[int]struct{}{ + 10: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parseRange(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + assert.Equal(t, test.expected, output, "Expected: %v, got: %v", test.expected, output) + }) + } +} + +func TestCron_parsePart_InputFormats(t *testing.T) { + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Valid Input with Multiple Values", + input: "1,5,7", + expected: map[int]struct{}{ + 1: {}, 5: {}, 7: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Invalid Input Format", + input: "1,a,3", + expected: nil, + min: 1, + max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parsePart(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + assert.Equal(t, test.expected, output) + }) + } +} + +func TestCron_parseRange_ErrorHandling(t *testing.T) { + tests := []struct { + name string + input string + min int + max int + hasError bool + }{ + { + name: "Empty String Input", + input: "", + min: 1, + max: 10, + hasError: true, + }, + { + name: "Out of Range Input", + input: "15-20", + min: 1, + max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := parseRange(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err, "Expected an error for input: %s", test.input) + } else { + require.NoError(t, err) + } + }) + } +} + +func TestCron_parseRange_SuccessCases(t *testing.T) { + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + }{ + { + name: "Full Range", + input: "1-10", + expected: map[int]struct{}{ + 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, + }, + min: 1, max: 10, + }, + { + name: "Partial Range", + input: "5-7", + expected: map[int]struct{}{ + 5: {}, 6: {}, 7: {}, + }, + min: 1, max: 10, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parseRange(test.input, test.min, test.max) + require.NoError(t, err) + + assert.Equal(t, test.expected, output) + }) + } +} + func TestCron_parsePart(t *testing.T) { tests := []struct { name string @@ -433,14 +594,14 @@ func TestCron_parsePart(t *testing.T) { for i, test := range tests { t.Run(test.name, func(t *testing.T) { output, err := parsePart(test.input, test.min, test.max) - if test.hasError { - assert.Error(t, err, "TEST[%d] - Expected error but got none", i) + require.Error(t, err, "TEST[%d] - Expected error but got none", i) } else { - assert.NoError(t, err, "TEST[%d] - Expected no error but got: %v", i, err) + require.NoError(t, err, "TEST[%d] - Expected no error but got: %v", i, err) } assert.Len(t, output, len(test.expected), "TEST[%d] - Expected length: %v, got: %v", i, len(test.expected), len(output)) + assert.Equal(t, test.expected, output, "TEST[%d] - Expected: %v, got: %v", i, test.expected, output) }) } From 71cf78cc469aca80243362379dca36ea0a93cd08 Mon Sep 17 00:00:00 2001 From: Arya Pratap Singh <75311742+ARYPROGRAMMER@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:16:38 +0530 Subject: [PATCH 10/26] Update cron_test.go --- pkg/gofr/cron_test.go | 304 +++++++++++++++++++++--------------------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/pkg/gofr/cron_test.go b/pkg/gofr/cron_test.go index 828a35180..e0e237287 100644 --- a/pkg/gofr/cron_test.go +++ b/pkg/gofr/cron_test.go @@ -363,7 +363,7 @@ func TestCron_parseRange(t *testing.T) { name: "Invalid Input", input: "a-b", expected: nil, - min: 1, max: 10, + min: 1, max: 10, hasError: true, }, } @@ -376,172 +376,172 @@ func TestCron_parseRange(t *testing.T) { } else { require.NoError(t, err) } - + assert.Len(t, output, len(test.expected)) - + assert.Equal(t, test.expected, output) }) } } func TestCron_parseRange_BoundaryValues(t *testing.T) { - tests := []struct { - name string - input string - expected map[int]struct{} - min int - max int - hasError bool - }{ - { - name: "Lower Boundary", - input: "1-1", - expected: map[int]struct{}{ - 1: {}, - }, - min: 1, - max: 10, - hasError: false, - }, - { - name: "Upper Boundary", - input: "10-10", - expected: map[int]struct{}{ - 10: {}, - }, - min: 1, - max: 10, - hasError: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - output, err := parseRange(test.input, test.min, test.max) - if test.hasError { - require.Error(t, err) - } else { - require.NoError(t, err) - } - - assert.Equal(t, test.expected, output, "Expected: %v, got: %v", test.expected, output) - }) - } + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Lower Boundary", + input: "1-1", + expected: map[int]struct{}{ + 1: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Upper Boundary", + input: "10-10", + expected: map[int]struct{}{ + 10: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parseRange(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + assert.Equal(t, test.expected, output, "Expected: %v, got: %v", test.expected, output) + }) + } } func TestCron_parsePart_InputFormats(t *testing.T) { - tests := []struct { - name string - input string - expected map[int]struct{} - min int - max int - hasError bool - }{ - { - name: "Valid Input with Multiple Values", - input: "1,5,7", - expected: map[int]struct{}{ - 1: {}, 5: {}, 7: {}, - }, - min: 1, - max: 10, - hasError: false, - }, - { - name: "Invalid Input Format", - input: "1,a,3", - expected: nil, - min: 1, - max: 10, - hasError: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - output, err := parsePart(test.input, test.min, test.max) - if test.hasError { - require.Error(t, err) - } else { - require.NoError(t, err) - } - - assert.Equal(t, test.expected, output) - }) - } + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + hasError bool + }{ + { + name: "Valid Input with Multiple Values", + input: "1,5,7", + expected: map[int]struct{}{ + 1: {}, 5: {}, 7: {}, + }, + min: 1, + max: 10, + hasError: false, + }, + { + name: "Invalid Input Format", + input: "1,a,3", + expected: nil, + min: 1, + max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parsePart(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err) + } else { + require.NoError(t, err) + } + + assert.Equal(t, test.expected, output) + }) + } } func TestCron_parseRange_ErrorHandling(t *testing.T) { - tests := []struct { - name string - input string - min int - max int - hasError bool - }{ - { - name: "Empty String Input", - input: "", - min: 1, - max: 10, - hasError: true, - }, - { - name: "Out of Range Input", - input: "15-20", - min: 1, - max: 10, - hasError: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - _, err := parseRange(test.input, test.min, test.max) - if test.hasError { - require.Error(t, err, "Expected an error for input: %s", test.input) - } else { - require.NoError(t, err) - } - }) - } + tests := []struct { + name string + input string + min int + max int + hasError bool + }{ + { + name: "Empty String Input", + input: "", + min: 1, + max: 10, + hasError: true, + }, + { + name: "Out of Range Input", + input: "15-20", + min: 1, + max: 10, + hasError: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + _, err := parseRange(test.input, test.min, test.max) + if test.hasError { + require.Error(t, err, "Expected an error for input: %s", test.input) + } else { + require.NoError(t, err) + } + }) + } } func TestCron_parseRange_SuccessCases(t *testing.T) { - tests := []struct { - name string - input string - expected map[int]struct{} - min int - max int - }{ - { - name: "Full Range", - input: "1-10", - expected: map[int]struct{}{ - 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, - }, - min: 1, max: 10, - }, - { - name: "Partial Range", - input: "5-7", - expected: map[int]struct{}{ - 5: {}, 6: {}, 7: {}, - }, - min: 1, max: 10, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - output, err := parseRange(test.input, test.min, test.max) - require.NoError(t, err) - - assert.Equal(t, test.expected, output) - }) - } + tests := []struct { + name string + input string + expected map[int]struct{} + min int + max int + }{ + { + name: "Full Range", + input: "1-10", + expected: map[int]struct{}{ + 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {}, 8: {}, 9: {}, 10: {}, + }, + min: 1, max: 10, + }, + { + name: "Partial Range", + input: "5-7", + expected: map[int]struct{}{ + 5: {}, 6: {}, 7: {}, + }, + min: 1, max: 10, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + output, err := parseRange(test.input, test.min, test.max) + require.NoError(t, err) + + assert.Equal(t, test.expected, output) + }) + } } func TestCron_parsePart(t *testing.T) { @@ -601,7 +601,7 @@ func TestCron_parsePart(t *testing.T) { } assert.Len(t, output, len(test.expected), "TEST[%d] - Expected length: %v, got: %v", i, len(test.expected), len(output)) - + assert.Equal(t, test.expected, output, "TEST[%d] - Expected: %v, got: %v", i, test.expected, output) }) } From 0a71a5a91c86312261a1ef7ec04627ce61ad0825 Mon Sep 17 00:00:00 2001 From: sebas Date: Wed, 9 Oct 2024 11:17:55 -0600 Subject: [PATCH 11/26] typo: advanced-guide/dealing-with-sql --- docs/advanced-guide/dealing-with-sql/page.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/advanced-guide/dealing-with-sql/page.md b/docs/advanced-guide/dealing-with-sql/page.md index cf0bd33d6..6b9804038 100644 --- a/docs/advanced-guide/dealing-with-sql/page.md +++ b/docs/advanced-guide/dealing-with-sql/page.md @@ -19,7 +19,7 @@ DB_DIALECT=postgres ``` ## Usage for SQLite -To connect with PostgreSQL, set `DB_DIALECT` to `sqlite` and `DB_NAME` to the name of your DB File. If the DB file already exists then it will be used otherwise a new one will be created. +To connect with SQLite, set `DB_DIALECT` to `sqlite` and `DB_NAME` to the name of your DB File. If the DB file already exists then it will be used otherwise a new one will be created. ```dotenv DB_NAME=test.db @@ -36,4 +36,4 @@ Add the following configs in `.env` file. DB_MAX_IDLE_CONNECTION=5 // Default 2 DB_MAX_OPEN_CONNECTION=5 // Default unlimited ``` -> ##### Check out the example on how to add configuration for SQL in GoFr: [Visit Github](https://github.com/gofr-dev/gofr/blob/main/examples/http-server/configs/.env) \ No newline at end of file +> ##### Check out the example on how to add configuration for SQL in GoFr: [Visit Github](https://github.com/gofr-dev/gofr/blob/main/examples/http-server/configs/.env) From ae8254013bcc4cc1d089b885d184393813d9bf0a Mon Sep 17 00:00:00 2001 From: mehrotra234 Date: Thu, 10 Oct 2024 13:18:55 +0530 Subject: [PATCH 12/26] add instruction to discourage WIP and draft PRs --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f90cfdb29..3b77efb6b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,7 @@ No PR should ever decrease the overall code coverage. * Once your code changes are done along with the testcases, submit a PR to development branch. Please note that all PRs are merged from feature branches to development first. +* PR should be raised only when development is complete and the code is ready for review. This approach helps reduce the number of open pull requests and facilitates a more efficient review process for the team. * All PRs need to be reviewed by at least 2 GoFr developers. They might reach out to you for any clarification. * Thank you for your contribution. :) From 622762640703a3414f818d66041bcfaeddb0181d Mon Sep 17 00:00:00 2001 From: Divya Darshana <98943137+coolwednesday@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:46:20 +0530 Subject: [PATCH 13/26] fixed setting jwt-claims in context (#1096) --- pkg/gofr/http/middleware/oauth.go | 10 ++++-- pkg/gofr/http/middleware/oauth_test.go | 49 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/pkg/gofr/http/middleware/oauth.go b/pkg/gofr/http/middleware/oauth.go index 75344f65e..18d2536ef 100644 --- a/pkg/gofr/http/middleware/oauth.go +++ b/pkg/gofr/http/middleware/oauth.go @@ -21,8 +21,12 @@ var ( errInvalidAuthorizationHeader = errors.New("authorization header format must be Bearer {token}") ) -// JWTClaim represents a custom key used to store JWT claims within the request context. -type JWTClaim string +// authMethod represents a custom type to define the different authentication methods supported. +type authMethod int + +const ( + JWTClaim authMethod = iota // JWTClaim represents the key used to store JWT claims within the request context. +) // PublicKeys stores a map of public keys identified by their key ID (kid). type PublicKeys struct { @@ -130,7 +134,7 @@ func OAuth(key PublicKeyProvider) func(inner http.Handler) http.Handler { return } - ctx := context.WithValue(r.Context(), JWTClaim("JWTClaims"), token.Claims) + ctx := context.WithValue(r.Context(), JWTClaim, token.Claims) *r = *r.Clone(ctx) inner.ServeHTTP(w, r) diff --git a/pkg/gofr/http/middleware/oauth_test.go b/pkg/gofr/http/middleware/oauth_test.go index c4f2582ce..857a72744 100644 --- a/pkg/gofr/http/middleware/oauth_test.go +++ b/pkg/gofr/http/middleware/oauth_test.go @@ -45,6 +45,55 @@ func TestOAuthSuccess(t *testing.T) { resp.Body.Close() } +func TestGetJwtClaims(t *testing.T) { + claims := []byte(`{"aud":"stage.kops.dev","iat":1257894000,"orig":"GOOGLE",` + + `"picture":"https://lh3.googleusercontent.com/a/ACg8ocKJ5DDA4zruzFlsQ9KvL` + + `jHDtbOT_hpVz0hEO8jSl2m7Myk=s96-c","sub":"rakshit.singh@zopsmart.com","sub-id"` + + `:"a6573e1d-abea-4863-acdb-6cf3626a4414","typ":"refresh_token"}`) + + router := mux.NewRouter() + router.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) { + result, err := json.Marshal(r.Context().Value(JWTClaim)) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + _, err = w.Write(result) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + w.WriteHeader(http.StatusOK) + }).Methods(http.MethodGet).Name("/test") + router.Use(OAuth(NewOAuth(OauthConfigs{Provider: &MockProvider{}, RefreshInterval: 10}))) + + server := httptest.NewServer(router) + + req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, server.URL+"/test", http.NoBody) + req.Header.Set("Authorization", "Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6IjAwVFEwdlRpNVB1UnZscUZGY3dCeUc0WjBM"+ + "dGREcUtJX0JWUFRrdnpleEUiLCJ0eXAiOiJKV1QifQ.eyJhdWQiOiJzdGFnZS5rb3BzLmRldiIsImlhdCI6MTI1Nzg5NDAwMCwib3JpZyI6IkdP"+ + "T0dMRSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS9BQ2c4b2NLSjVEREE0enJ1ekZsc1E5S3ZMakhEdG"+ + "JPVF9ocFZ6MGhFTzhqU2wybTdNeWs9czk2LWMiLCJzdWIiOiJyYWtzaGl0LnNpbmdoQHpvcHNtYXJ0LmNvbSIsInN1Yi1pZCI6ImE2NTczZTFkL"+ + "WFiZWEtNDg2My1hY2RiLTZjZjM2MjZhNDQxNCIsInR5cCI6InJlZnJlc2hfdG9rZW4ifQ.NkYSi6KJtGA3js9dcN3UqJWfeJdB88p7cxclrc6"+ + "fxJODlCalsbbwIr3QL4AR9i0ucJjmoTIipCwpdM1IYDjCd-ilf2mTp11Wba31XoH--8YLI9Ju0wbpYhtF3wa00NF1Ijt48ze09IJ6QtE-etm"+ + "AN8T7izsXbPeSrFiN3NVQU87eGxc3bEQhEsV5u3E6j8EdVDv8xbwisETY-N0mDftZp0w8UCkQ7MarOrA5IaXs2MHyCETy5y9QFd4djppH9oFo"+ + "y5-AtEZqzyHKfGMlerjtJp8uOgFso9FycGuO0TFhR4AaZGVZxB072Hu-71tbx7atXp3zmDdkK_jkg5aVepoU_Q") + + client := http.Client{} + + resp, err := client.Do(req) + result := make([]byte, len(claims)) + _, _ = resp.Body.Read(result) + + require.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + assert.Equal(t, claims, result) + + resp.Body.Close() +} + func TestOAuthInvalidTokenFormat(t *testing.T) { router := mux.NewRouter() router.HandleFunc("/test", func(w http.ResponseWriter, _ *http.Request) { From 7942696f9b86cb6cc025f75db375c872bddc492a Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Mon, 7 Oct 2024 21:29:59 +0530 Subject: [PATCH 14/26] handled panic in redis ping --- pkg/gofr/datasource/redis/redis.go | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/pkg/gofr/datasource/redis/redis.go b/pkg/gofr/datasource/redis/redis.go index dba199fd1..f82df4401 100644 --- a/pkg/gofr/datasource/redis/redis.go +++ b/pkg/gofr/datasource/redis/redis.go @@ -48,18 +48,15 @@ func NewClient(c config.Config, logger datasource.Logger, metrics Metrics) *Redi ctx, cancel := context.WithTimeout(context.TODO(), redisPingTimeout) defer cancel() - if err := rc.Ping(ctx).Err(); err != nil { + if err := rc.Ping(ctx).Err(); err == nil { + if err := otel.InstrumentTracing(rc); err != nil { + logger.Errorf("could not add tracing instrumentation, error: %s", err) + } + logger.Logf("connected to redis at %s:%d", redisConfig.HostName, redisConfig.Port) + } else { logger.Errorf("could not connect to redis at '%s:%d', error: %s", redisConfig.HostName, redisConfig.Port, err) - - return &Redis{Client: nil, config: redisConfig, logger: logger} - } - - if err := otel.InstrumentTracing(rc); err != nil { - logger.Errorf("could not add tracing instrumentation, error: %s", err) } - logger.Logf("connected to redis at %s:%d", redisConfig.HostName, redisConfig.Port) - return &Redis{Client: rc, config: redisConfig, logger: logger} } From 0717365a6f1b8ed4c51319ffca730cae339d1d61 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Wed, 9 Oct 2024 20:54:33 +0530 Subject: [PATCH 15/26] Fix assertion in container_test.go for Redis connection --- pkg/gofr/container/container_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gofr/container/container_test.go b/pkg/gofr/container/container_test.go index 64bcaf3fb..f62649afd 100644 --- a/pkg/gofr/container/container_test.go +++ b/pkg/gofr/container/container_test.go @@ -41,7 +41,7 @@ func Test_newContainerDBInitializationFail(t *testing.T) { // container is a pointer, and we need to see if db are not initialized, comparing the container object // will not suffice the purpose of this test require.Error(t, db.DB.Ping(), "TEST, Failed.\ninvalid db connections") - assert.Nil(t, redis.Client, "TEST, Failed.\ninvalid redis connections") + assert.NotNil(t, redis.Client, "TEST, Failed.\ninvalid redis connections") } func Test_newContainerPubSubInitializationFail(t *testing.T) { From ee7f7a7c4c097f233660d334d3f7b6c2061b0da4 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Wed, 9 Oct 2024 21:18:31 +0530 Subject: [PATCH 16/26] GoCI Lint fixes --- pkg/gofr/datasource/redis/redis.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/gofr/datasource/redis/redis.go b/pkg/gofr/datasource/redis/redis.go index f82df4401..ac0893338 100644 --- a/pkg/gofr/datasource/redis/redis.go +++ b/pkg/gofr/datasource/redis/redis.go @@ -49,9 +49,10 @@ func NewClient(c config.Config, logger datasource.Logger, metrics Metrics) *Redi defer cancel() if err := rc.Ping(ctx).Err(); err == nil { - if err := otel.InstrumentTracing(rc); err != nil { + if err = otel.InstrumentTracing(rc); err != nil { logger.Errorf("could not add tracing instrumentation, error: %s", err) } + logger.Logf("connected to redis at %s:%d", redisConfig.HostName, redisConfig.Port) } else { logger.Errorf("could not connect to redis at '%s:%d', error: %s", redisConfig.HostName, redisConfig.Port, err) From 7d3189422ecb723f0ca77748f7102b05abf256fa Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Thu, 10 Oct 2024 20:09:34 +0530 Subject: [PATCH 17/26] testcase fixes --- pkg/gofr/datasource/redis/redis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gofr/datasource/redis/redis_test.go b/pkg/gofr/datasource/redis/redis_test.go index 59c3a642e..5c06a5254 100644 --- a/pkg/gofr/datasource/redis/redis_test.go +++ b/pkg/gofr/datasource/redis/redis_test.go @@ -38,7 +38,7 @@ func Test_NewClient_InvalidPort(t *testing.T) { mockMetrics.EXPECT().RecordHistogram(gomock.Any(), "app_redis_stats", gomock.Any(), "hostname", gomock.Any(), "type", "ping") client := NewClient(mockConfig, mockLogger, mockMetrics) - assert.Nil(t, client.Client, "Test_NewClient_InvalidPort Failed! Expected redis client to be nil") + assert.Not(t, client.Client, "Test_NewClient_InvalidPort Failed! Expected redis client not to be nil") } func TestRedis_QueryLogging(t *testing.T) { From 868a7aa86fa48c172a67f49d8a21e1230ebd5a89 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Thu, 10 Oct 2024 20:38:20 +0530 Subject: [PATCH 18/26] testcase fixes --- pkg/gofr/datasource/redis/redis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gofr/datasource/redis/redis_test.go b/pkg/gofr/datasource/redis/redis_test.go index 5c06a5254..71746eb22 100644 --- a/pkg/gofr/datasource/redis/redis_test.go +++ b/pkg/gofr/datasource/redis/redis_test.go @@ -38,7 +38,7 @@ func Test_NewClient_InvalidPort(t *testing.T) { mockMetrics.EXPECT().RecordHistogram(gomock.Any(), "app_redis_stats", gomock.Any(), "hostname", gomock.Any(), "type", "ping") client := NewClient(mockConfig, mockLogger, mockMetrics) - assert.Not(t, client.Client, "Test_NewClient_InvalidPort Failed! Expected redis client not to be nil") + assert.NotNil(t, client.Client, "Test_NewClient_InvalidPort Failed! Expected redis client not to be nil") } func TestRedis_QueryLogging(t *testing.T) { From 275bf6370ca054916b2830319351cf948380b81a Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Fri, 4 Oct 2024 16:26:10 +0530 Subject: [PATCH 19/26] issue 989 added docker-compose for the http-server example with observability using Jaeger --- examples/http-server/Dockerfile | 15 +- examples/http-server/README.md | 16 +- examples/http-server/docker-compose.yaml | 57 +++ examples/http-server/go.mod | 100 ++++++ examples/http-server/go.sum | 426 +++++++++++++++++++++++ 5 files changed, 597 insertions(+), 17 deletions(-) create mode 100644 examples/http-server/docker-compose.yaml create mode 100644 examples/http-server/go.mod create mode 100644 examples/http-server/go.sum diff --git a/examples/http-server/Dockerfile b/examples/http-server/Dockerfile index 7bf8597bb..c0b6d02dd 100644 --- a/examples/http-server/Dockerfile +++ b/examples/http-server/Dockerfile @@ -1,15 +1,16 @@ -FROM golang:1.22 +# Build stage +FROM golang:1.22 AS build -RUN mkdir /src/ -WORKDIR /src/ +WORKDIR /src COPY . . RUN go get ./... -RUN go build -ldflags "-linkmode external -extldflags -static" -a main.go +RUN go build -ldflags "-linkmode external -extldflags -static" -a -o /app/main main.go -FROM alpine:latest +# Final stage +FROM alpine:3.14 RUN apk add --no-cache tzdata ca-certificates -COPY --from=0 /src/main /main -COPY --from=0 /src/configs /configs +COPY --from=build /app/main /main +COPY --from=build /src/configs /configs EXPOSE 9000 CMD ["/main"] diff --git a/examples/http-server/README.md b/examples/http-server/README.md index d0a458547..9955fa627 100644 --- a/examples/http-server/README.md +++ b/examples/http-server/README.md @@ -4,17 +4,13 @@ This GoFr example demonstrates a simple HTTP server which supports Redis and MyS ### To run the example follow the steps below: -- Run the docker image of Redis +- Run the docker image of the application ```console -docker run --name gofr-redis -p 2002:6379 -d redis:7.0.5 +docker-compose up -d ``` -- Run the docker image of MySQL -```console -docker run --name gofr-mysql -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=test -p 2001:3306 -d mysql:8.0.30 -``` +To test the example, follow these steps: + +1. Open your browser and navigate to `http://localhost:9000/hello`. +2. To view the trace in Jaeger, open `http://localhost:16686`. -- Now run the example -```console -go run main.go -``` diff --git a/examples/http-server/docker-compose.yaml b/examples/http-server/docker-compose.yaml new file mode 100644 index 000000000..dd0e8fa66 --- /dev/null +++ b/examples/http-server/docker-compose.yaml @@ -0,0 +1,57 @@ +version: '3.8' + +services: + gofr-http-server: + build: + context: . + dockerfile: Dockerfile + environment: + - TRACE_EXPORTER=jaeger + - TRACER_URL=jaeger:4317 + - REDIS_HOST=redisdb + - REDIS_PORT=6379 + - DB_HOST=mysqldb + - DB_USER=root + - DB_PASSWORD=password + - DB_NAME=test + - DB_PORT=3306 + - DB_DIALECT=mysql + ports: + - "9000:9000" + depends_on: + - redisdb + - mysqldb + - jaeger + networks: + - gofr-network + + redisdb: + image: redis:7.0.5 + ports: + - "2002:6379" + networks: + - gofr-network + + mysqldb: + image: mysql:8.0.30 + environment: + MYSQL_ROOT_PASSWORD: password + MYSQL_DATABASE: test + ports: + - "2001:3306" + networks: + - gofr-network + + jaeger: + image: jaegertracing/all-in-one:1.41 + environment: + COLLECTOR_OTLP_ENABLED: "true" + ports: + - "16686:16686" + - "4317:4317" + - "4318:4318" + networks: + - gofr-network + +networks: + gofr-network: \ No newline at end of file diff --git a/examples/http-server/go.mod b/examples/http-server/go.mod new file mode 100644 index 000000000..db7574867 --- /dev/null +++ b/examples/http-server/go.mod @@ -0,0 +1,100 @@ +module http-server + +go 1.22 + +require ( + github.com/go-redis/redismock/v9 v9.2.0 + github.com/redis/go-redis/v9 v9.6.1 + github.com/stretchr/testify v1.9.0 + gofr.dev v1.21.0 +) + +require ( + cloud.google.com/go v0.115.1 // indirect + cloud.google.com/go/auth v0.9.3 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.4 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/iam v1.2.0 // indirect + cloud.google.com/go/pubsub v1.42.0 // indirect + filippo.io/edwards25519 v1.1.0 // indirect + github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect + github.com/XSAM/otelsql v0.33.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/eclipse/paho.mqtt.golang v1.5.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v5 v5.2.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/google/s2a-go v0.1.8 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect + github.com/googleapis/gax-go/v2 v2.13.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/websocket v1.5.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect + github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/joho/godotenv v1.5.1 // indirect + github.com/klauspost/compress v1.17.9 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.20.3 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.59.1 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect + github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/segmentio/kafka-go v0.4.47 // indirect + go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 // indirect + go.opentelemetry.io/otel v1.30.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.52.0 // indirect + go.opentelemetry.io/otel/exporters/zipkin v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.30.0 // indirect + go.opentelemetry.io/otel/sdk v1.30.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.30.0 // indirect + go.opentelemetry.io/otel/trace v1.30.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect + go.uber.org/mock v0.4.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.23.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/time v0.6.0 // indirect + google.golang.org/api v0.197.0 // indirect + google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.66.2 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect + modernc.org/libc v1.55.3 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/memory v1.8.0 // indirect + modernc.org/sqlite v1.33.1 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect +) diff --git a/examples/http-server/go.sum b/examples/http-server/go.sum new file mode 100644 index 000000000..3a18947eb --- /dev/null +++ b/examples/http-server/go.sum @@ -0,0 +1,426 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.115.1 h1:Jo0SM9cQnSkYfp44+v+NQXHpcHqlnRJk2qxh6yvxxxQ= +cloud.google.com/go v0.115.1/go.mod h1:DuujITeaufu3gL68/lOFIirVNJwQeyf5UXyi+Wbgknc= +cloud.google.com/go/auth v0.9.3 h1:VOEUIAADkkLtyfr3BLa3R8Ed/j6w1jTBmARx+wb5w5U= +cloud.google.com/go/auth v0.9.3/go.mod h1:7z6VY+7h3KUdRov5F1i8NDP5ZzWKYmEPO842BgCsmTk= +cloud.google.com/go/auth/oauth2adapt v0.2.4 h1:0GWE/FUsXhf6C+jAkWgYm7X9tK8cuEIfy19DBn6B6bY= +cloud.google.com/go/auth/oauth2adapt v0.2.4/go.mod h1:jC/jOpwFP6JBxhB3P5Rr0a9HLMC/Pe3eaL4NmdvqPtc= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/iam v1.2.0 h1:kZKMKVNk/IsSSc/udOb83K0hL/Yh/Gcqpz+oAkoIFN8= +cloud.google.com/go/iam v1.2.0/go.mod h1:zITGuWgsLZxd8OwAlX+eMFgZDXzBm7icj1PVTYG766Q= +cloud.google.com/go/kms v1.19.0 h1:x0OVJDl6UH1BSX4THKlMfdcFWoE4ruh90ZHuilZekrU= +cloud.google.com/go/kms v1.19.0/go.mod h1:e4imokuPJUc17Trz2s6lEXFDt8bgDmvpVynH39bdrHM= +cloud.google.com/go/longrunning v0.6.0 h1:mM1ZmaNsQsnb+5n1DNPeL0KwQd9jQRqSqSDEkBZr+aI= +cloud.google.com/go/longrunning v0.6.0/go.mod h1:uHzSZqW89h7/pasCWNYdUpwGz3PcVWhrWupreVPYLts= +cloud.google.com/go/pubsub v1.42.0 h1:PVTbzorLryFL5ue8esTS2BfehUs0ahyNOY9qcd+HMOs= +cloud.google.com/go/pubsub v1.42.0/go.mod h1:KADJ6s4MbTwhXmse/50SebEhE4SmUwHi48z3/dHar1Y= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= +github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= +github.com/XSAM/otelsql v0.33.0 h1:8ZgVGFMG78Gd7BcCkxZ+lBTybWrnOtQv5sn4sLWb0+w= +github.com/XSAM/otelsql v0.33.0/go.mod h1:TIaqdCA0m+GP0TJ4axwMSLunVfMFsxf1x1UU8MlUvAY= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= +github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis/v2 v2.33.0 h1:uvTF0EDeu9RLnUEG27Db5I68ESoIxTiXbNUiji6lZrA= +github.com/alicebob/miniredis/v2 v2.33.0/go.mod h1:MhP4a3EU7aENRi9aO+tHfTBZicLqQevyi/DJpoj6mi0= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o= +github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw= +github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo= +github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= +github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= +github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= +github.com/googleapis/gax-go/v2 v2.13.0 h1:yitjD5f7jQHhyDsnhKEBU52NdvvdSeGzlAnDPT0hH1s= +github.com/googleapis/gax-go/v2 v2.13.0/go.mod h1:Z/fvTZXF8/uw7Xu5GuslPw+bplx6SS338j1Is2S+B7A= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ= +github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= +github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 h1:EaDatTxkdHG+U3Bk4EUr+DZ7fOGwTfezUiUJMaIcaho= +github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5/go.mod h1:fyalQWdtzDBECAQFBJuQe5bzQ02jGd5Qcbgb97Flm7U= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5 h1:EfpWLLCyXw8PSM2/XNJLjI3Pb27yVE+gIAfeqp8LUCc= +github.com/redis/go-redis/extra/redisotel/v9 v9.0.5/go.mod h1:WZjPDy7VNzn77AAfnAfVjZNvfJTYfPetfZk5yoSTLaQ= +github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= +github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= +github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/segmentio/kafka-go v0.4.47 h1:IqziR4pA3vrZq7YdRxaT3w1/5fvIH5qpCwstUanQQB0= +github.com/segmentio/kafka-go v0.4.47/go.mod h1:HjF6XbOKh0Pjlkr5GVZxt6CsjjwnmhVOfURM5KMd8qg= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= +go.einride.tech/aip v0.67.1 h1:d/4TW92OxXBngkSOwWS2CH5rez869KpKMaN44mdxkFI= +go.einride.tech/aip v0.67.1/go.mod h1:ZGX4/zKw8dcgzdLsrvpOOGxfxI2QSk12SlP7d6c0/XI= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0 h1:sqmsIQ75l6lfZjjpnXXT9DFVtYEDg6CH0/Cn4/3A1Wg= +go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.55.0/go.mod h1:rsg1EO8LXSs2po50PB5CeY/MSVlhghuKBgXlKnqm6ks= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0 h1:ZIg3ZT/aQ7AfKqdwp7ECpOK6vHqquXXuyTjIO8ZdmPs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.55.0/go.mod h1:DQAwmETtZV00skUwgD6+0U89g80NKsJE3DCKeLLPQMI= +go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0= +go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ= +go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0= +go.opentelemetry.io/otel/exporters/zipkin v1.30.0 h1:1uYaSfxiCLdJATlGEtYjQe4jZYfqCjVwxeSTMXe8VF4= +go.opentelemetry.io/otel/exporters/zipkin v1.30.0/go.mod h1:r/4BhMc3kiKxD61wGh9J3NVQ3/cZ45F2NHkQgVnql48= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= +go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM= +go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +gofr.dev v1.21.0 h1:cvOfye5JAXc1RIDDEYkqVVBSUjthu3LwFVA2aioGfvg= +gofr.dev v1.21.0/go.mod h1:PV8vsrqMG/rct++egjqnly/yuteENeAC3zH7ckhNQEY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs= +golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.197.0 h1:x6CwqQLsFiA5JKAiGyGBjc2bNtHtLddhJCE2IKuhhcQ= +google.golang.org/api v0.197.0/go.mod h1:AuOuo20GoQ331nq7DquGHlU6d+2wN2fZ8O0ta60nRNw= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1 h1:BulPr26Jqjnd4eYDVe+YvyR7Yc2vJGkO5/0UxD0/jZU= +google.golang.org/genproto v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:hL97c3SYopEHblzpxRL4lSs523++l8DYxGM1FQiYmb4= +google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed h1:3RgNmBoI9MZhsj3QxC+AP/qQhNwpCLOvYDYYsFrhFt0= +google.golang.org/genproto/googleapis/api v0.0.0-20240827150818-7e3bb234dfed/go.mod h1:OCdP9MfskevB/rbYvHTsXTtKC+3bHWajPdoKgjcYkfo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo= +google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ= +modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= +modernc.org/ccgo/v4 v4.19.2 h1:lwQZgvboKD0jBwdaeVCTouxhxAyN6iawF3STraAal8Y= +modernc.org/ccgo/v4 v4.19.2/go.mod h1:ysS3mxiMV38XGRTTcgo0DQTeTmAO4oCmJl1nX9VFI3s= +modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= +modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= +modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= +modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= +modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= +modernc.org/sqlite v1.33.1 h1:trb6Z3YYoeM9eDL1O8do81kP+0ejv+YzgyFo+Gwy0nM= +modernc.org/sqlite v1.33.1/go.mod h1:pXV2xHxhzXZsgT/RtTFAPY6JJDEvOTcTdwADQCCWD4k= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= From db3c99da5cdb84808d08284fd6fa8fcf425593be Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Sat, 5 Oct 2024 20:47:16 +0530 Subject: [PATCH 20/26] Replaced Jaeger with Gofr Tracing --- examples/http-server/docker-compose.yaml | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/examples/http-server/docker-compose.yaml b/examples/http-server/docker-compose.yaml index dd0e8fa66..8775b4dfe 100644 --- a/examples/http-server/docker-compose.yaml +++ b/examples/http-server/docker-compose.yaml @@ -6,8 +6,8 @@ services: context: . dockerfile: Dockerfile environment: - - TRACE_EXPORTER=jaeger - - TRACER_URL=jaeger:4317 + - TRACE_EXPORTER=gofr + - TRACER_RATIO=0.1 - REDIS_HOST=redisdb - REDIS_PORT=6379 - DB_HOST=mysqldb @@ -21,7 +21,6 @@ services: depends_on: - redisdb - mysqldb - - jaeger networks: - gofr-network @@ -42,16 +41,5 @@ services: networks: - gofr-network - jaeger: - image: jaegertracing/all-in-one:1.41 - environment: - COLLECTOR_OTLP_ENABLED: "true" - ports: - - "16686:16686" - - "4317:4317" - - "4318:4318" - networks: - - gofr-network - networks: gofr-network: \ No newline at end of file From 66a75dbc9c5a7dee4f829580394d4953d700bee2 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Sat, 5 Oct 2024 21:17:23 +0530 Subject: [PATCH 21/26] Added Grafana image --- examples/http-server/docker-compose.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/http-server/docker-compose.yaml b/examples/http-server/docker-compose.yaml index 8775b4dfe..87ac0069b 100644 --- a/examples/http-server/docker-compose.yaml +++ b/examples/http-server/docker-compose.yaml @@ -18,9 +18,12 @@ services: - DB_DIALECT=mysql ports: - "9000:9000" + - "2121:2121" + - "9090:9090" depends_on: - redisdb - mysqldb + - grafana networks: - gofr-network @@ -41,5 +44,15 @@ services: networks: - gofr-network + grafana: + image: grafana/grafana:latest + ports: + - "3000:3000" + environment: + - GF_SECURITY_ADMIN_USER=admin + - GF_SECURITY_ADMIN_PASSWORD=password + networks: + - gofr-network + networks: gofr-network: \ No newline at end of file From a8a4e51d22cf38e44f50a40d64bc319002a1fed4 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Mon, 7 Oct 2024 20:54:26 +0530 Subject: [PATCH 22/26] added Grafana dashboard and prometheus setup --- examples/http-server/docker-compose.yaml | 13 +- .../http-server/prometheus/prometheus.yml | 11 + .../provisioning/dashboards/dashboards.yaml | 11 + .../dashboards/gofr-dashboard/dashboards.json | 4525 +++++++++++++++++ .../provisioning/datasources/datasource.yaml | 9 + 5 files changed, 4568 insertions(+), 1 deletion(-) create mode 100644 examples/http-server/prometheus/prometheus.yml create mode 100644 examples/http-server/provisioning/dashboards/dashboards.yaml create mode 100644 examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json create mode 100644 examples/http-server/provisioning/datasources/datasource.yaml diff --git a/examples/http-server/docker-compose.yaml b/examples/http-server/docker-compose.yaml index 87ac0069b..0815e733d 100644 --- a/examples/http-server/docker-compose.yaml +++ b/examples/http-server/docker-compose.yaml @@ -19,11 +19,11 @@ services: ports: - "9000:9000" - "2121:2121" - - "9090:9090" depends_on: - redisdb - mysqldb - grafana + - prometheus networks: - gofr-network @@ -51,6 +51,17 @@ services: environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=password + volumes: + - ./provisioning:/etc/grafana/provisioning + networks: + - gofr-network + + prometheus: + image: prom/prometheus:latest + ports: + - "9090:9090" + volumes: + - ./prometheus:/etc/prometheus networks: - gofr-network diff --git a/examples/http-server/prometheus/prometheus.yml b/examples/http-server/prometheus/prometheus.yml new file mode 100644 index 000000000..94bda8ff3 --- /dev/null +++ b/examples/http-server/prometheus/prometheus.yml @@ -0,0 +1,11 @@ +global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + metrics_path: '/metrics' + static_configs: + - targets: ['host.docker.internal:2121'] \ No newline at end of file diff --git a/examples/http-server/provisioning/dashboards/dashboards.yaml b/examples/http-server/provisioning/dashboards/dashboards.yaml new file mode 100644 index 000000000..790854327 --- /dev/null +++ b/examples/http-server/provisioning/dashboards/dashboards.yaml @@ -0,0 +1,11 @@ +apiVersion: 1 + +providers: + - name: 'Gofr Dashboard' + orgId: 1 + folder: '' + type: file + disableDeletion: false + updateIntervalSeconds: 10 + options: + path: /etc/grafana/provisioning/dashboards/gofr-dashboard \ No newline at end of file diff --git a/examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json b/examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json new file mode 100644 index 000000000..6f4c51fcd --- /dev/null +++ b/examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json @@ -0,0 +1,4525 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "description": "Gofr Dashboard offers real-time insights into our system's performance, displaying key metrics like response times and error rates. Tailored for DevOps and engineering teams, it pulls data from Prometheus and Kubernetes. Updated regularly, we encourage your feedback to make it even more valuable for your needs.", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 19905, + "graphTooltip": 0, + "id": 3, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 90, + "panels": [], + "title": "App Information", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 7, + "x": 0, + "y": 1 + }, + "id": 87, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "/.*/", + "values": false + }, + "showPercentChange": false, + "textMode": "value", + "wideLayout": true + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "app_info{app_name='$Service'}", + "format": "table", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "App Version", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "app_version" + ] + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 8, + "x": 7, + "y": 1 + }, + "id": 88, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "/.*/", + "values": false + }, + "showPercentChange": false, + "textMode": "value", + "wideLayout": true + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "app_info{app_name='$Service'}", + "format": "table", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Framework Version", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "framework_version" + ] + } + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 9, + "x": 15, + "y": 1 + }, + "id": 93, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "/.*/", + "values": false + }, + "showPercentChange": false, + "textMode": "value", + "wideLayout": true + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "go_info{}", + "format": "table", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Go Version", + "transformations": [ + { + "id": "filterFieldsByName", + "options": { + "include": { + "names": [ + "version" + ], + "pattern": "version" + } + } + } + ], + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 5 + }, + "id": 14, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "System Information", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "# Of GoRoutines", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (pod) (app_go_routines{})", + "format": "time_series", + "hide": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(app_go_routines{})", + "hide": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Go Routines", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Memory (bytes)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (pod) (app_sys_memory_alloc{})", + "format": "time_series", + "hide": false, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(app_sys_memory_alloc{})", + "hide": true, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Memory Utilisation", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "$${DataSource}" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 8, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "$${DataSource}" + }, + "refId": "A" + } + ], + "title": "Inbound Requests", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Time (sec)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 15 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(app_http_response_bucket{}[$__rate_interval])) by (le))", + "legendFormat": " 90", + "range": true, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum(rate(app_http_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "95", + "range": true, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(app_http_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "99", + "range": true, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.999, sum(rate(app_http_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "99.9", + "range": true, + "refId": "99.9" + } + ], + "title": "Response Time SLA", + "transformations": [ + { + "id": "organize", + "options": {} + } + ], + "type": "timeseries" + }, + { + "cards": {}, + "color": { + "cardColor": "#96D98D", + "colorScale": "sqrt", + "colorScheme": "interpolateGreens", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "tsbuckets", + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 15 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 2, + "legend": { + "show": false + }, + "options": { + "calculate": false, + "calculation": {}, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#96D98D", + "mode": "opacity", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": false + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "10.3.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(increase(app_http_response_bucket{}[$__rate_interval])) by (le)", + "format": "heatmap", + "instant": false, + "legendFormat": "{{le}}", + "range": true, + "refId": "A" + } + ], + "title": "Request Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "yAxis": { + "format": "s", + "logBase": 1, + "show": true + }, + "yBucketBound": "auto" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "No of requests", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Path level service dashboard", + "url": "/d/InboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__field.labels.path}&var-method=$${__field.labels.method}&from=$${__from}&to=$${__to}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 23 + }, + "id": 126, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (path, method) (\n increase(app_http_response_count{}[$__rate_interval])\n)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(increase(app_http_response_count{}[$__rate_interval]))", + "hide": true, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Request Count Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Response Count ", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 23 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (status) (\n increase(app_http_response_count{}[$__rate_interval])\n)", + "legendFormat": "{{status}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(increase(app_http_response_count{}[$__rate_interval]))", + "hide": true, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Response Code Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "targetBlank": true, + "title": "Path Level Dashboard", + "url": "/d/InboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__data.fields.Path}&var-method=$${__data.fields.Method}&from=$${__from}&to=$${__to} " + } + ], + "mappings": [ + { + "options": { + "NaN": { + "index": 0, + "text": "N/A" + } + }, + "type": "value" + } + ], + "noValue": "N/A", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "purple", + "value": 80 + } + ] + }, + "unit": "ms", + "unitScale": true + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 31 + }, + "id": 74, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "p99.9" + } + ] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.999, sum(rate(app_http_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "99.9" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(app_http_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(app_http_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.90, sum(rate(app_http_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum(increase(app_http_response_count{}[$__range])) by (le, path,method)", + "format": "table", + "hide": true, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "A" + } + ], + "title": "Route Level SLA", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "status": true + }, + "indexByName": { + "Time": 0, + "Value": 7, + "Value #90": 3, + "Value #95": 4, + "Value #99": 5, + "Value #99.9": 6, + "method": 1, + "path": 2 + }, + "renameByName": { + "Time": "", + "Value": "Count", + "Value #2xx": "Response Code 2xx", + "Value #400": "Response Code 400", + "Value #401": "Response Code 401", + "Value #404": "Response Code 404", + "Value #50": "50%(ms)", + "Value #5xx": "Response Code 5xx", + "Value #90": "p90", + "Value #95": "p95", + "Value #99": "p99", + "Value #99.9": "p99.9", + "Value #A": "Count", + "Value #Total": "Total Count", + "method": "Method", + "path": "Path", + "status": "Status" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "targetBlank": true, + "title": "Path Level Dashboard", + "url": "/d/InboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__data.fields.Path}&var-method=$${__data.fields.Method}&from=$${__from}&to=$${__to} " + } + ], + "mappings": [], + "noValue": "N/A", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "purple", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Path" + }, + "properties": [ + { + "id": "custom.width", + "value": 258 + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 75, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "Method" + } + ] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=\"400\"}[$__range]))", + "format": "table", + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "400" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=\"401\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "401" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=\"403\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "403" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=\"404\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "404" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=~\"5.+\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "5xx" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{status=~\"2.+\"}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "2xx" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_response_count{}[$__range]))", + "format": "table", + "hide": true, + "instant": true, + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "Total" + } + ], + "title": "Route Level Response Code", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "status": true + }, + "indexByName": { + "Time": 0, + "Value #2xx": 3, + "Value #400": 4, + "Value #401": 5, + "Value #403": 6, + "Value #404": 7, + "Value #5xx": 8, + "Value #Total": 9, + "method": 1, + "path": 2 + }, + "renameByName": { + "Time": "", + "Value #2xx": "2xx", + "Value #400": "400", + "Value #401": "401", + "Value #403": "403", + "Value #404": "404", + "Value #50": "50%(ms)", + "Value #5xx": "5xx", + "Value #90": "90%(ms)", + "Value #95": "95%(ms)", + "Value #99": "99%(ms)", + "Value #Total": "Total", + "method": "Method", + "path": "Path", + "status": "Status" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 49 + }, + "id": 20, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "Outbound Requests", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "Outbound request level 99%ile response time", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Time (sec)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Path level drill down ", + "url": "/d/OutboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__field.labels.path}&var-method=$${__field.labels.method}&from=$${__from}&to=$${__to}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 50 + }, + "id": 28, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(app_http_service_response_bucket{}[$__rate_interval])) by (le))", + "legendFormat": "90", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum(rate(app_http_service_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(app_http_service_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "99", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.999, sum(rate(app_http_service_response_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "99.9", + "range": true, + "refId": "D" + } + ], + "title": "Response Time SLA", + "type": "timeseries" + }, + { + "cards": {}, + "color": { + "cardColor": "#96D98D", + "colorScale": "sqrt", + "colorScheme": "interpolateGreens", + "exponent": 0.5, + "mode": "opacity" + }, + "dataFormat": "tsbuckets", + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "scaleDistribution": { + "type": "linear" + } + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 50 + }, + "heatmap": {}, + "hideZeroBuckets": false, + "highlightCards": true, + "id": 94, + "legend": { + "show": false + }, + "options": { + "calculate": false, + "calculation": {}, + "cellGap": 2, + "cellValues": {}, + "color": { + "exponent": 0.5, + "fill": "#96D98D", + "mode": "opacity", + "reverse": false, + "scale": "exponential", + "scheme": "Oranges", + "steps": 128 + }, + "exemplars": { + "color": "rgba(255,0,255,0.7)" + }, + "filterValues": { + "le": 1e-9 + }, + "legend": { + "show": false + }, + "rowsFrame": { + "layout": "auto" + }, + "showValue": "never", + "tooltip": { + "mode": "single", + "showColorScale": false, + "yHistogram": false + }, + "yAxis": { + "axisPlacement": "left", + "reverse": false, + "unit": "s" + } + }, + "pluginVersion": "10.3.3", + "reverseYBuckets": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(increase(app_http_service_response_bucket{}[$__rate_interval])) by (le)", + "format": "heatmap", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Request Latency Distribution", + "tooltip": { + "show": true, + "showHistogram": false + }, + "type": "heatmap", + "xAxis": { + "show": true + }, + "yAxis": { + "format": "s", + "logBase": 1, + "show": true + }, + "yBucketBound": "auto" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "No. of requests", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [ + { + "targetBlank": true, + "title": "Path level Dashboard", + "url": "/d/OutboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__field.labels.path}&var-method=$${__field.labels.method}&from=$${__from}&to=$${__to}" + } + ], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 58 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (path, method) (\n increase(app_http_service_response_count{}[$__rate_interval])\n)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(increase(app_http_service_response_count{}[$__rate_interval]))", + "hide": true, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Request Count over time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Request Count ", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "Value" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 58 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (status) (\n increase(app_http_service_response_count{}[$__rate_interval])\n)", + "legendFormat": "{{status}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(increase(app_http_service_response_count{}[$__rate_interval]))", + "hide": true, + "legendFormat": "sum", + "range": true, + "refId": "B" + } + ], + "title": "Response Code Over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "targetBlank": true, + "title": "Path Level Dashboard", + "url": "/d/OutboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__data.fields.Path}&var-method=$${__data.fields.Method}&from=$${__from}&to=$${__to}" + } + ], + "mappings": [ + { + "options": { + "NaN": { + "index": 0, + "text": "N/A" + } + }, + "type": "value" + } + ], + "noValue": "N/A", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms", + "unitScale": true + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Path" + }, + "properties": [ + { + "id": "custom.width", + "value": 342 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 66 + }, + "id": 77, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(app_http_service_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "instant": true, + "interval": "", + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(app_http_service_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.90, sum(rate(app_http_service_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.999, sum(rate(app_http_service_response_bucket{}[$__range])) by (le, path,method)) * 1000", + "format": "table", + "hide": false, + "instant": true, + "interval": "", + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "99.9" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by (service,method,path) (increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": true, + "instant": true, + "interval": "", + "legendFormat": "{{path}} {{method}}", + "range": false, + "refId": "A" + } + ], + "title": "Route Level SLA", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "le": true, + "status": true + }, + "indexByName": { + "Time": 0, + "Value #90": 3, + "Value #95": 4, + "Value #99": 5, + "Value #99.9": 6, + "method": 1, + "path": 2 + }, + "renameByName": { + "Value #2xx": "Response Code 2xx", + "Value #400": "Response Code 400", + "Value #404": "Response Code 404", + "Value #50": "50%(ms)", + "Value #90": "p90", + "Value #95": "p95", + "Value #99": "p99", + "Value #99.9": "p99.9", + "Value #A": "Count", + "Value #total": "Total Count", + "method": "Method", + "path": "Path", + "status": "Status", + "{status=\"400\"}": "400" + } + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "left", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "links": [ + { + "targetBlank": true, + "title": "Path Level Dashboard", + "url": "/d/OutboundCallsPathLevelDrillDownDashboard/path-level-drill-down-dashboard?orgId=1&var-DataSource=$${DataSource}&var-namespace=$${namespace}&var-service=$${service}&var-path=$${__data.fields.Path}&var-method=$${__data.fields.Method}&from=$${__from}&to=$${__to}" + } + ], + "mappings": [], + "noValue": "N/A", + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "orange" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 74 + }, + "id": 78, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "Path" + } + ] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "instant": true, + "legendFormat": "Verbose", + "range": false, + "refId": "400" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "401" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "404" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "5xx" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "2xx" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method)(increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "403" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(path,method) (increase(app_http_service_response_count{}[$__range]))", + "format": "table", + "hide": true, + "instant": true, + "legendFormat": "", + "range": false, + "refId": "Total" + } + ], + "title": "Route Level Response Code", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "status": true + }, + "indexByName": { + "Time": 0, + "Value #2xx": 3, + "Value #400": 4, + "Value #401": 5, + "Value #403": 6, + "Value #404": 7, + "Value #5xx": 8, + "Value #A": 9, + "method": 1, + "path": 2 + }, + "renameByName": { + "Value #2xx": "2xx", + "Value #400": "400", + "Value #401": "401", + "Value #403": "403", + "Value #404": "404", + "Value #50": "50%(ms)", + "Value #5xx": "5xx", + "Value #90": "90%(ms)", + "Value #95": "95%(ms)", + "Value #99": "99%(ms)", + "Value #A": "Total", + "Value #total": "Total", + "method": "Method", + "path": "Path", + "status": "Status", + "{status=\"400\"}": "400" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 82 + }, + "id": 30, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "SQL Database", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Time (sec)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 83 + }, + "id": 34, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(app_sql_stats_bucket{}[$__rate_interval])) by (le))", + "legendFormat": "p90", + "range": true, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum(rate(app_sql_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p95", + "range": true, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(app_sql_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p99", + "range": true, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.999, sum(rate(app_sql_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p99.9", + "range": true, + "refId": "99.9" + } + ], + "title": "Response Time SLA", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "No. of query ", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 83 + }, + "id": 32, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (type) (rate(app_sql_stats_count{}[$__rate_interval]))", + "legendFormat": "{{type}} - {{database}}", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum(rate(app_sql_stats_count{}[$__rate_interval]))", + "hide": true, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Query Count over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineStyle": { + "fill": "solid" + }, + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 92 + }, + "id": 58, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "app_sql_inUse_connections{}", + "hide": false, + "legendFormat": "InUse", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "app_sql_open_connections{}", + "hide": false, + "legendFormat": "Open", + "range": true, + "refId": "C" + } + ], + "title": "Connection Count", + "transformations": [], + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [ + { + "options": { + "NaN": { + "index": 0, + "text": "N/A" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "ms", + "unitScale": true + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 100 + }, + "id": 95, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.90, sum(rate(app_sql_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(app_sql_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(app_sql_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.999, sum(rate(app_sql_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "99.9" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(type)(increase(app_sql_stats_count{}[$__range]))", + "format": "table", + "hide": true, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Query Type Level SLA", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": {}, + "renameByName": { + "Value #90": "p90", + "Value #95": "p95", + "Value #99": "p99", + "Value #99.9": "p99.9", + "Value #A": "Total", + "Value #B": "p90", + "Value #C": "p99", + "Value #D": "p99.9", + "Value #E": "Count", + "type": "Type" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 106 + }, + "id": 42, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "Redis", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "Time (sec)", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 107 + }, + "id": 36, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.90, sum(rate(app_redis_stats_bucket{}[$__rate_interval])) by (le))", + "legendFormat": "p90", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.95, sum(rate(app_redis_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p95", + "range": true, + "refId": "B" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.99, sum(rate(app_redis_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p99", + "range": true, + "refId": "C" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "histogram_quantile(0.999, sum(rate(app_redis_stats_bucket{}[$__rate_interval])) by (le))", + "hide": false, + "legendFormat": "p99.9", + "range": true, + "refId": "D" + } + ], + "title": "Response Time SLA", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "No. of query ", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 107 + }, + "id": 46, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum by (type) (rate(app_redis_stats_bucket{}[$__rate_interval]))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "expr": "sum (rate(app_redis_stats_bucket{}[$__rate_interval]))", + "hide": true, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Query Count over Time", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Count" + }, + "properties": [ + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 5, + "w": 24, + "x": 0, + "y": 115 + }, + "id": 107, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": false, + "displayName": "Type" + } + ] + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.90, sum(rate(app_redis_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "90" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.95, sum(rate(app_redis_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "95" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.99, sum(rate(app_redis_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "99" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "histogram_quantile(0.999, sum(rate(app_redis_stats_bucket{}[$__range])) by (le,type))", + "format": "table", + "hide": false, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "99.9" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "sum by(type)(increase(app_redis_stats_count{}[$__range]))", + "format": "table", + "hide": true, + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Query Type Level SLA", + "transformations": [ + { + "id": "merge", + "options": {} + }, + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": {}, + "renameByName": { + "Value #90": "p90", + "Value #95": "p95", + "Value #99": "p99", + "Value #99.9": "p99.9", + "Value #A": "Total", + "Value #B": "p90", + "Value #C": "p99", + "Value #D": "p99.9", + "Value #E": "Count", + "type": "Type" + } + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 120 + }, + "id": 60, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "PubSub Consumer", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 121 + }, + "id": 114, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [], + "fields": "/.*/", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "app_pubsub_subscribe_total_count_total{}", + "format": "table", + "instant": true, + "range": false, + "refId": "A" + } + ], + "title": "Topics", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true, + "__name__": true, + "consumerGroup": true, + "container": true, + "endpoint": true, + "instance": true, + "job": true, + "namespace": true, + "otel_scope_name": true, + "otel_scope_version": true, + "pod": true, + "prometheus": true, + "prometheus_replica": true, + "service": true + }, + "includeByName": {}, + "indexByName": { + "Time": 1, + "Value": 13, + "__name__": 2, + "consumerGroup": 3, + "container": 4, + "endpoint": 5, + "instance": 6, + "job": 7, + "namespace": 8, + "pod": 9, + "prometheus": 10, + "prometheus_replica": 11, + "service": 12, + "topic": 0 + }, + "renameByName": {} + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 125 + }, + "id": 62, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (increase(app_pubsub_subscribe_total_count_total{}[$__rate_interval]))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum (increase(app_pubsub_subscribe_total_count_total{}[$__rate_interval]))", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Consumption Over Time (Receive)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 135 + }, + "id": 120, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (increase(app_pubsub_subscribe_success_count_total[$__rate_interval]))", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum (increase(app_pubsub_subscribe_success_count_total{}[$__rate_interval]))", + "hide": false, + "legendFormat": "__auto", + "range": true, + "refId": "B" + } + ], + "title": "Consumption Over Time (Success)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 135 + }, + "id": 121, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (\n increase(app_pubsub_subscribe_total_count_total{}[$__rate_interval])\n)\n-\nsum by (topic) (\n increase(app_pubsub_subscribe_success_count_total{}[$__rate_interval])\n)", + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum (\n increase(app_pubsub_subscribe_total_count_total{}[$__rate_interval])\n)\n-\nsum (\n increase(app_pubsub_subscribe_success_count_total{}[$__rate_interval])\n)", + "hide": false, + "legendFormat": "Total Failure", + "range": true, + "refId": "B" + } + ], + "title": "Consumption Over Time (Failure)", + "type": "timeseries" + }, + { + "collapsed": false, + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 144 + }, + "id": 48, + "panels": [], + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "refId": "A" + } + ], + "title": "PubSub Publisher", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 145 + }, + "id": 118, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^topic$/", + "values": true + }, + "showPercentChange": false, + "text": {}, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.3", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": false, + "expr": "app_pubsub_publish_total_count_total{}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Topics", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true, + "__name__": true, + "consumerGroup": true, + "container": true, + "endpoint": true, + "instance": true, + "job": true, + "namespace": true, + "pod": true, + "prometheus": true, + "prometheus_replica": true, + "service": true + }, + "indexByName": { + "Time": 1, + "Value": 13, + "__name__": 2, + "consumerGroup": 3, + "container": 4, + "endpoint": 5, + "instance": 6, + "job": 7, + "namespace": 8, + "pod": 9, + "prometheus": 10, + "prometheus_replica": 11, + "service": 12, + "topic": 0 + }, + "renameByName": {} + } + } + ], + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 153 + }, + "id": 64, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (increase(app_pubsub_publish_total_count_total{}[$__rate_interval]))", + "instant": false, + "legendFormat": "{{topic}}({{consumerGroup}})", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum (increase(app_pubsub_publish_total_count_total{}[$__rate_interval]))", + "hide": false, + "instant": false, + "legendFormat": "Total", + "range": true, + "refId": "B" + } + ], + "title": "Publish Over Time (Total)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 163 + }, + "id": 122, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (\n increase(app_pubsub_publish_success_count_total{}[$__rate_interval])\n)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum(\n increase(app_pubsub_publish_success_count_total{}[$__rate_interval])\n)", + "hide": false, + "instant": false, + "legendFormat": "Total Success", + "range": true, + "refId": "B" + } + ], + "title": "Publish Over Time (Success)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "never", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "short", + "unitScale": true + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "{consumerGroup=\"gofr-consumerGroup\", topic=\"tn-subscription\"}" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 163 + }, + "id": 123, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "pluginVersion": "9.2.4", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum by (topic) (\n increase(app_pubsub_publish_total_count_total{}[$__rate_interval])\n)\n-\nsum by (topic) (\n increase(app_pubsub_publish_success_count_total{}[$__rate_interval])\n)", + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A" + }, + { + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "editorMode": "code", + "exemplar": true, + "expr": "sum (\n increase(app_pubsub_publish_total_count_total{}[$__rate_interval])\n)\n-\nsum (\n increase(app_pubsub_publish_success_count_total{}[$__rate_interval])\n)", + "hide": false, + "instant": false, + "legendFormat": "Total Failure", + "range": true, + "refId": "B" + } + ], + "title": "Publish Over Time (Failure)", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [ + "Observability Common" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "prometheus", + "value": "f7d51eca-7c3e-4b91-81a6-00d485fddaba" + }, + "hide": 0, + "includeAll": false, + "label": "Data Source", + "multi": false, + "name": "DataSource", + "options": [], + "query": "prometheus", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "current": { + "selected": true, + "text": "order-service", + "value": "order-service" + }, + "datasource": { + "type": "prometheus", + "uid": "${DataSource}" + }, + "definition": "label_values(app_name)", + "hide": 0, + "includeAll": false, + "label": "", + "multi": false, + "name": "Service", + "options": [], + "query": { + "qryType": 1, + "query": "label_values(app_name)", + "refId": "PrometheusVariableQueryEditor-VariableQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-30m", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "GoFr - Application Services Monitoring", + "uid": "SMDAllServices123", + "version": 7, + "weekStart": "" +} \ No newline at end of file diff --git a/examples/http-server/provisioning/datasources/datasource.yaml b/examples/http-server/provisioning/datasources/datasource.yaml new file mode 100644 index 000000000..f88db84c4 --- /dev/null +++ b/examples/http-server/provisioning/datasources/datasource.yaml @@ -0,0 +1,9 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + editable: true \ No newline at end of file From c767f9c672a532cf13c50a2de6f6f2a5ad533630 Mon Sep 17 00:00:00 2001 From: Vignesh P Date: Thu, 10 Oct 2024 20:34:21 +0530 Subject: [PATCH 23/26] folder structure changes and review changes --- examples/http-server/README.md | 3 ++- examples/http-server/{ => docker}/docker-compose.yaml | 2 +- examples/http-server/{ => docker}/prometheus/prometheus.yml | 0 .../{ => docker}/provisioning/dashboards/dashboards.yaml | 0 .../provisioning/dashboards/gofr-dashboard/dashboards.json | 0 .../{ => docker}/provisioning/datasources/datasource.yaml | 0 6 files changed, 3 insertions(+), 2 deletions(-) rename examples/http-server/{ => docker}/docker-compose.yaml (98%) rename examples/http-server/{ => docker}/prometheus/prometheus.yml (100%) rename examples/http-server/{ => docker}/provisioning/dashboards/dashboards.yaml (100%) rename examples/http-server/{ => docker}/provisioning/dashboards/gofr-dashboard/dashboards.json (100%) rename examples/http-server/{ => docker}/provisioning/datasources/datasource.yaml (100%) diff --git a/examples/http-server/README.md b/examples/http-server/README.md index 9955fa627..176e491e1 100644 --- a/examples/http-server/README.md +++ b/examples/http-server/README.md @@ -12,5 +12,6 @@ docker-compose up -d To test the example, follow these steps: 1. Open your browser and navigate to `http://localhost:9000/hello`. -2. To view the trace in Jaeger, open `http://localhost:16686`. +2. To view the trace Gofr trce, open `https://tracer.gofr.dev` and paste the traceid. +3. To view the Grafana Dashboard open `http://localhost:3000` diff --git a/examples/http-server/docker-compose.yaml b/examples/http-server/docker/docker-compose.yaml similarity index 98% rename from examples/http-server/docker-compose.yaml rename to examples/http-server/docker/docker-compose.yaml index 0815e733d..0cbce4a03 100644 --- a/examples/http-server/docker-compose.yaml +++ b/examples/http-server/docker/docker-compose.yaml @@ -3,7 +3,7 @@ version: '3.8' services: gofr-http-server: build: - context: . + context: ../. dockerfile: Dockerfile environment: - TRACE_EXPORTER=gofr diff --git a/examples/http-server/prometheus/prometheus.yml b/examples/http-server/docker/prometheus/prometheus.yml similarity index 100% rename from examples/http-server/prometheus/prometheus.yml rename to examples/http-server/docker/prometheus/prometheus.yml diff --git a/examples/http-server/provisioning/dashboards/dashboards.yaml b/examples/http-server/docker/provisioning/dashboards/dashboards.yaml similarity index 100% rename from examples/http-server/provisioning/dashboards/dashboards.yaml rename to examples/http-server/docker/provisioning/dashboards/dashboards.yaml diff --git a/examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json b/examples/http-server/docker/provisioning/dashboards/gofr-dashboard/dashboards.json similarity index 100% rename from examples/http-server/provisioning/dashboards/gofr-dashboard/dashboards.json rename to examples/http-server/docker/provisioning/dashboards/gofr-dashboard/dashboards.json diff --git a/examples/http-server/provisioning/datasources/datasource.yaml b/examples/http-server/docker/provisioning/datasources/datasource.yaml similarity index 100% rename from examples/http-server/provisioning/datasources/datasource.yaml rename to examples/http-server/docker/provisioning/datasources/datasource.yaml From 3f35f3726ea0ca8e05b83077608707e299d084c3 Mon Sep 17 00:00:00 2001 From: umang01-hash Date: Mon, 14 Oct 2024 14:37:26 +0530 Subject: [PATCH 24/26] update gofr version --- pkg/gofr/version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/gofr/version/version.go b/pkg/gofr/version/version.go index 4060342d1..6760ffc99 100644 --- a/pkg/gofr/version/version.go +++ b/pkg/gofr/version/version.go @@ -1,3 +1,3 @@ package version -const Framework = "dev" +const Framework = "v1.24.0" From afe1f1d9f5a5e4dfdaa520e1c7edf4d607bf027f Mon Sep 17 00:00:00 2001 From: Umang Mundhra Date: Mon, 14 Oct 2024 15:48:33 +0530 Subject: [PATCH 25/26] Add support for Tracing in Cassandra database (#1074) --- .../injecting-databases-drivers/page.md | 31 +- pkg/gofr/container/container.go | 2 +- pkg/gofr/container/datasources.go | 41 +- pkg/gofr/container/mock_container.go | 4 +- pkg/gofr/container/mock_datasources.go | 700 ++++++++++++++++++ pkg/gofr/datasource/cassandra/cassandra.go | 64 +- .../datasource/cassandra/cassandra_batch.go | 31 +- .../datasource/cassandra/cassandra_test.go | 19 +- pkg/gofr/datasource/cassandra/go.mod | 5 +- pkg/gofr/datasource/cassandra/go.sum | 7 + pkg/gofr/external_db.go | 4 + pkg/gofr/external_db_test.go | 1 + pkg/gofr/migration/cassandra.go | 15 +- pkg/gofr/migration/cassandra_test.go | 11 +- 14 files changed, 880 insertions(+), 55 deletions(-) diff --git a/docs/advanced-guide/injecting-databases-drivers/page.md b/docs/advanced-guide/injecting-databases-drivers/page.md index ed91cfe57..c36ab6bcb 100644 --- a/docs/advanced-guide/injecting-databases-drivers/page.md +++ b/docs/advanced-guide/injecting-databases-drivers/page.md @@ -172,26 +172,25 @@ with Cassandra. Any driver implementation that adheres to this interface can be suits your project's needs. ```go -type Cassandra interface { - Query(dest interface{}, stmt string, values ...any) error +type CassandraWithContext interface { + QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error - Exec(stmt string, values ...any) error - - ExecCAS(dest any, stmt string, values ...any) (bool, error) + ExecWithCtx(ctx context.Context, stmt string, values ...any) error - BatchQuery(stmt string, values ...any) error + ExecCASWithCtx(ctx context.Context, dest any, stmt string, values ...any) (bool, error) - NewBatch(name string, batchType int) error + NewBatchWithCtx(ctx context.Context, name string, batchType int) error - CassandraBatch + Cassandra + CassandraBatchWithContext } -type CassandraBatch interface { - BatchQuery(name, stmt string, values ...any) - - ExecuteBatch(name string) error - - ExecuteBatchCAS(name string, dest ...any) (bool, error) +type CassandraBatchWithContext interface { + BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error + + ExecuteBatchWithCtx(ctx context.Context, name string) error + + ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) } ``` @@ -239,7 +238,7 @@ func main() { return nil, err } - err = c.Cassandra.Exec(`INSERT INTO persons(id, name, age, location) VALUES(?, ?, ?, ?)`, + err = c.Cassandra.ExecWithCtx(c,`INSERT INTO persons(id, name, age, location) VALUES(?, ?, ?, ?)`, person.ID, person.Name, person.Age, person.State) if err != nil { return nil, err @@ -251,7 +250,7 @@ func main() { app.GET("/user", func(c *gofr.Context) (interface{}, error) { persons := make([]Person, 0) - err := c.Cassandra.Query(&persons, `SELECT id, name, age, location FROM persons`) + err := c.Cassandra.QueryWithCtx(c, &persons, `SELECT id, name, age, location FROM persons`) return persons, err }) diff --git a/pkg/gofr/container/container.go b/pkg/gofr/container/container.go index 01f961a41..d7e6cee91 100644 --- a/pkg/gofr/container/container.go +++ b/pkg/gofr/container/container.go @@ -53,7 +53,7 @@ type Container struct { Redis Redis SQL DB - Cassandra Cassandra + Cassandra CassandraWithContext Clickhouse Clickhouse Mongo Mongo Solr Solr diff --git a/pkg/gofr/container/datasources.go b/pkg/gofr/container/datasources.go index a0d66c045..15bf02ad7 100644 --- a/pkg/gofr/container/datasources.go +++ b/pkg/gofr/container/datasources.go @@ -35,7 +35,10 @@ type Redis interface { Close() error } +// Cassandra is an interface representing a cassandra database +// Deprecated: Cassandra interface is deprecated and will be removed in future releases, users must use CassandraWithContext. type Cassandra interface { + // Deprecated: Query method is deprecated and will be removed in future releases, users must use QueryWithCtx. // Query executes the query and binds the result into dest parameter. // Returns error if any error occurs while binding the result. // Can be used to single as well as multiple rows. @@ -64,6 +67,7 @@ type Cassandra interface { // err := c.Query(&users, "SELECT * FROM users") Query(dest any, stmt string, values ...any) error + // Deprecated: Exec method is deprecated and will be removed in future releases, users must use ExecWithCtx. // Exec executes the query without returning any rows. // Return error if any error occurs while executing the query. // Can be used to execute UPDATE or INSERT. @@ -79,6 +83,7 @@ type Cassandra interface { // err := c.Exec("INSERT INTO users VALUES(?, ?)", id, name) Exec(stmt string, values ...any) error + // Deprecated: ExecCAS method is deprecated and will be removed in future releases, users must use ExecCASWithCtx. // ExecCAS executes a lightweight transaction (i.e. an UPDATE or INSERT statement containing an IF clause). // If the transaction fails because the existing values did not match, the previous values will be stored in dest. // Returns true if the query is applied otherwise false. @@ -95,8 +100,8 @@ type Cassandra interface { // applied, err := c.ExecCAS(&user, "INSERT INTO users VALUES(1, 'John Doe') IF NOT EXISTS") ExecCAS(dest any, stmt string, values ...any) (bool, error) + // Deprecated: NewBatch method is deprecated and will be removed in future releases, users must use NewBatchWithCtx. // NewBatch creates a new Cassandra batch with the specified name and batch type. - // // This method initializes a new Cassandra batch operation. It sets up the batch // with the given name and type, allowing you to execute multiple queries in // a single batch operation. The `batchType` determines the type of batch operation @@ -113,6 +118,7 @@ type Cassandra interface { } type CassandraBatch interface { + // Deprecated: BatchQuery method is deprecated and will be removed in future releases, users must use BatchQueryWithCtx. // BatchQuery adds the query to the batch operation // // Example: @@ -130,6 +136,7 @@ type CassandraBatch interface { // c.BatchQuery("INSERT INTO users VALUES(?, ?)", id2, name2) BatchQuery(name, stmt string, values ...any) error + // Deprecated: ExecuteBatch method is deprecated and will be removed in future releases, users must use ExecuteBatchWithCtx. // ExecuteBatch executes a batch operation and returns nil if successful otherwise an error is returned describing the failure. // // Example: @@ -137,6 +144,7 @@ type CassandraBatch interface { // err := c.ExecuteBatch("myBatch") ExecuteBatch(name string) error + // Deprecated: ExecuteBatchCAS method is deprecated and will be removed in future releases, users must use ExecuteBatchCASWithCtx. // ExecuteBatchCAS executes a batch operation and returns true if successful. // Returns true if the query is applied otherwise false. // Returns false and error if any error occur while executing the query. @@ -148,8 +156,37 @@ type CassandraBatch interface { ExecuteBatchCAS(name string, dest ...any) (bool, error) } -type CassandraProvider interface { +type CassandraWithContext interface { + // QueryWithCtx executes the query with a context and binds the result into dest parameter. + // Accepts pointer to struct or slice as dest parameter for single and multiple rows retrieval respectively. + QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error + + // ExecWithCtx executes the query with a context, without returning any rows. + ExecWithCtx(ctx context.Context, stmt string, values ...any) error + + // ExecCASWithCtx executes a lightweight transaction with a context. + ExecCASWithCtx(ctx context.Context, dest any, stmt string, values ...any) (bool, error) + + // NewBatchWithCtx creates a new Cassandra batch with context. + NewBatchWithCtx(ctx context.Context, name string, batchType int) error + Cassandra + CassandraBatchWithContext +} + +type CassandraBatchWithContext interface { + // BatchQueryWithCtx adds the query to the batch operation with a context. + BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error + + // ExecuteBatchWithCtx executes a batch operation with a context. + ExecuteBatchWithCtx(ctx context.Context, name string) error + + // ExecuteBatchCASWithCtx executes a batch operation with context and returns the result. + ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) +} + +type CassandraProvider interface { + CassandraWithContext provider } diff --git a/pkg/gofr/container/mock_container.go b/pkg/gofr/container/mock_container.go index 8875ab594..b868c8ce6 100644 --- a/pkg/gofr/container/mock_container.go +++ b/pkg/gofr/container/mock_container.go @@ -20,7 +20,7 @@ type Mocks struct { Redis *MockRedis SQL *mockSQL Clickhouse *MockClickhouse - Cassandra *MockCassandra + Cassandra *MockCassandraWithContext Mongo *MockMongo KVStore *MockKVStore DGraph *MockDgraph @@ -65,7 +65,7 @@ func NewMockContainer(t *testing.T, options ...options) (*Container, *Mocks) { redisMock := NewMockRedis(ctrl) container.Redis = redisMock - cassandraMock := NewMockCassandra(ctrl) + cassandraMock := NewMockCassandraWithContext(ctrl) container.Cassandra = cassandraMock clickhouseMock := NewMockClickhouse(ctrl) diff --git a/pkg/gofr/container/mock_datasources.go b/pkg/gofr/container/mock_datasources.go index cce0014c2..d68711ea1 100644 --- a/pkg/gofr/container/mock_datasources.go +++ b/pkg/gofr/container/mock_datasources.go @@ -6,6 +6,7 @@ // mockgen -source=datasources.go -destination=mock_datasources.go -package=container // +// Package container is a generated GoMock package. package container import ( @@ -18,6 +19,7 @@ import ( redis "github.com/redis/go-redis/v9" gomock "go.uber.org/mock/gomock" datasource "gofr.dev/pkg/gofr/datasource" + pubsub "gofr.dev/pkg/gofr/datasource/pubsub" sql0 "gofr.dev/pkg/gofr/datasource/sql" ) @@ -7812,6 +7814,423 @@ func (mr *MockCassandraBatchMockRecorder) ExecuteBatchCAS(name any, dest ...any) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCAS", reflect.TypeOf((*MockCassandraBatch)(nil).ExecuteBatchCAS), varargs...) } +// MockCassandraWithContext is a mock of CassandraWithContext interface. +type MockCassandraWithContext struct { + ctrl *gomock.Controller + recorder *MockCassandraWithContextMockRecorder +} + +// MockCassandraWithContextMockRecorder is the mock recorder for MockCassandraWithContext. +type MockCassandraWithContextMockRecorder struct { + mock *MockCassandraWithContext +} + +// NewMockCassandraWithContext creates a new mock instance. +func NewMockCassandraWithContext(ctrl *gomock.Controller) *MockCassandraWithContext { + mock := &MockCassandraWithContext{ctrl: ctrl} + mock.recorder = &MockCassandraWithContextMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCassandraWithContext) EXPECT() *MockCassandraWithContextMockRecorder { + return m.recorder +} + +// BatchQuery mocks base method. +func (m *MockCassandraWithContext) BatchQuery(name, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{name, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BatchQuery", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchQuery indicates an expected call of BatchQuery. +func (mr *MockCassandraWithContextMockRecorder) BatchQuery(name, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{name, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQuery", reflect.TypeOf((*MockCassandraWithContext)(nil).BatchQuery), varargs...) +} + +// BatchQueryWithCtx mocks base method. +func (m *MockCassandraWithContext) BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, name, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BatchQueryWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchQueryWithCtx indicates an expected call of BatchQueryWithCtx. +func (mr *MockCassandraWithContextMockRecorder) BatchQueryWithCtx(ctx, name, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQueryWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).BatchQueryWithCtx), varargs...) +} + +// Exec mocks base method. +func (m *MockCassandraWithContext) Exec(stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Exec", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Exec indicates an expected call of Exec. +func (mr *MockCassandraWithContextMockRecorder) Exec(stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockCassandraWithContext)(nil).Exec), varargs...) +} + +// ExecCAS mocks base method. +func (m *MockCassandraWithContext) ExecCAS(dest any, stmt string, values ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecCAS", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecCAS indicates an expected call of ExecCAS. +func (mr *MockCassandraWithContextMockRecorder) ExecCAS(dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecCAS", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecCAS), varargs...) +} + +// ExecCASWithCtx mocks base method. +func (m *MockCassandraWithContext) ExecCASWithCtx(ctx context.Context, dest any, stmt string, values ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecCASWithCtx", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecCASWithCtx indicates an expected call of ExecCASWithCtx. +func (mr *MockCassandraWithContextMockRecorder) ExecCASWithCtx(ctx, dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecCASWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecCASWithCtx), varargs...) +} + +// ExecWithCtx mocks base method. +func (m *MockCassandraWithContext) ExecWithCtx(ctx context.Context, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecWithCtx indicates an expected call of ExecWithCtx. +func (mr *MockCassandraWithContextMockRecorder) ExecWithCtx(ctx, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecWithCtx), varargs...) +} + +// ExecuteBatch mocks base method. +func (m *MockCassandraWithContext) ExecuteBatch(name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExecuteBatch", name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecuteBatch indicates an expected call of ExecuteBatch. +func (mr *MockCassandraWithContextMockRecorder) ExecuteBatch(name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatch", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecuteBatch), name) +} + +// ExecuteBatchCAS mocks base method. +func (m *MockCassandraWithContext) ExecuteBatchCAS(name string, dest ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{name} + for _, a := range dest { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecuteBatchCAS", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecuteBatchCAS indicates an expected call of ExecuteBatchCAS. +func (mr *MockCassandraWithContextMockRecorder) ExecuteBatchCAS(name any, dest ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{name}, dest...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCAS", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecuteBatchCAS), varargs...) +} + +// ExecuteBatchCASWithCtx mocks base method. +func (m *MockCassandraWithContext) ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, name} + for _, a := range dest { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecuteBatchCASWithCtx", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecuteBatchCASWithCtx indicates an expected call of ExecuteBatchCASWithCtx. +func (mr *MockCassandraWithContextMockRecorder) ExecuteBatchCASWithCtx(ctx, name any, dest ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name}, dest...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCASWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecuteBatchCASWithCtx), varargs...) +} + +// ExecuteBatchWithCtx mocks base method. +func (m *MockCassandraWithContext) ExecuteBatchWithCtx(ctx context.Context, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExecuteBatchWithCtx", ctx, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecuteBatchWithCtx indicates an expected call of ExecuteBatchWithCtx. +func (mr *MockCassandraWithContextMockRecorder) ExecuteBatchWithCtx(ctx, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).ExecuteBatchWithCtx), ctx, name) +} + +// HealthCheck mocks base method. +func (m *MockCassandraWithContext) HealthCheck(arg0 context.Context) (any, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HealthCheck", arg0) + ret0, _ := ret[0].(any) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// HealthCheck indicates an expected call of HealthCheck. +func (mr *MockCassandraWithContextMockRecorder) HealthCheck(arg0 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HealthCheck", reflect.TypeOf((*MockCassandraWithContext)(nil).HealthCheck), arg0) +} + +// NewBatch mocks base method. +func (m *MockCassandraWithContext) NewBatch(name string, batchType int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatch", name, batchType) + ret0, _ := ret[0].(error) + return ret0 +} + +// NewBatch indicates an expected call of NewBatch. +func (mr *MockCassandraWithContextMockRecorder) NewBatch(name, batchType any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatch", reflect.TypeOf((*MockCassandraWithContext)(nil).NewBatch), name, batchType) +} + +// NewBatchWithCtx mocks base method. +func (m *MockCassandraWithContext) NewBatchWithCtx(ctx context.Context, name string, batchType int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatchWithCtx", ctx, name, batchType) + ret0, _ := ret[0].(error) + return ret0 +} + +// NewBatchWithCtx indicates an expected call of NewBatchWithCtx. +func (mr *MockCassandraWithContextMockRecorder) NewBatchWithCtx(ctx, name, batchType any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatchWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).NewBatchWithCtx), ctx, name, batchType) +} + +// Query mocks base method. +func (m *MockCassandraWithContext) Query(dest any, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "Query", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// Query indicates an expected call of Query. +func (mr *MockCassandraWithContextMockRecorder) Query(dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockCassandraWithContext)(nil).Query), varargs...) +} + +// QueryWithCtx mocks base method. +func (m *MockCassandraWithContext) QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "QueryWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// QueryWithCtx indicates an expected call of QueryWithCtx. +func (mr *MockCassandraWithContextMockRecorder) QueryWithCtx(ctx, dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryWithCtx", reflect.TypeOf((*MockCassandraWithContext)(nil).QueryWithCtx), varargs...) +} + +// MockCassandraBatchWithContext is a mock of CassandraBatchWithContext interface. +type MockCassandraBatchWithContext struct { + ctrl *gomock.Controller + recorder *MockCassandraBatchWithContextMockRecorder +} + +// MockCassandraBatchWithContextMockRecorder is the mock recorder for MockCassandraBatchWithContext. +type MockCassandraBatchWithContextMockRecorder struct { + mock *MockCassandraBatchWithContext +} + +// NewMockCassandraBatchWithContext creates a new mock instance. +func NewMockCassandraBatchWithContext(ctrl *gomock.Controller) *MockCassandraBatchWithContext { + mock := &MockCassandraBatchWithContext{ctrl: ctrl} + mock.recorder = &MockCassandraBatchWithContextMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCassandraBatchWithContext) EXPECT() *MockCassandraBatchWithContextMockRecorder { + return m.recorder +} + +// BatchQuery mocks base method. +func (m *MockCassandraBatchWithContext) BatchQuery(name, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{name, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BatchQuery", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchQuery indicates an expected call of BatchQuery. +func (mr *MockCassandraBatchWithContextMockRecorder) BatchQuery(name, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{name, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQuery", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).BatchQuery), varargs...) +} + +// BatchQueryWithCtx mocks base method. +func (m *MockCassandraBatchWithContext) BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, name, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BatchQueryWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchQueryWithCtx indicates an expected call of BatchQueryWithCtx. +func (mr *MockCassandraBatchWithContextMockRecorder) BatchQueryWithCtx(ctx, name, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQueryWithCtx", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).BatchQueryWithCtx), varargs...) +} + +// ExecuteBatch mocks base method. +func (m *MockCassandraBatchWithContext) ExecuteBatch(name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExecuteBatch", name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecuteBatch indicates an expected call of ExecuteBatch. +func (mr *MockCassandraBatchWithContextMockRecorder) ExecuteBatch(name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatch", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).ExecuteBatch), name) +} + +// ExecuteBatchCAS mocks base method. +func (m *MockCassandraBatchWithContext) ExecuteBatchCAS(name string, dest ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{name} + for _, a := range dest { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecuteBatchCAS", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecuteBatchCAS indicates an expected call of ExecuteBatchCAS. +func (mr *MockCassandraBatchWithContextMockRecorder) ExecuteBatchCAS(name any, dest ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{name}, dest...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCAS", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).ExecuteBatchCAS), varargs...) +} + +// ExecuteBatchCASWithCtx mocks base method. +func (m *MockCassandraBatchWithContext) ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, name} + for _, a := range dest { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecuteBatchCASWithCtx", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecuteBatchCASWithCtx indicates an expected call of ExecuteBatchCASWithCtx. +func (mr *MockCassandraBatchWithContextMockRecorder) ExecuteBatchCASWithCtx(ctx, name any, dest ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name}, dest...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCASWithCtx", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).ExecuteBatchCASWithCtx), varargs...) +} + +// ExecuteBatchWithCtx mocks base method. +func (m *MockCassandraBatchWithContext) ExecuteBatchWithCtx(ctx context.Context, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExecuteBatchWithCtx", ctx, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecuteBatchWithCtx indicates an expected call of ExecuteBatchWithCtx. +func (mr *MockCassandraBatchWithContextMockRecorder) ExecuteBatchWithCtx(ctx, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchWithCtx", reflect.TypeOf((*MockCassandraBatchWithContext)(nil).ExecuteBatchWithCtx), ctx, name) +} + // MockCassandraProvider is a mock of CassandraProvider interface. type MockCassandraProvider struct { ctrl *gomock.Controller @@ -7854,6 +8273,25 @@ func (mr *MockCassandraProviderMockRecorder) BatchQuery(name, stmt any, values . return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQuery", reflect.TypeOf((*MockCassandraProvider)(nil).BatchQuery), varargs...) } +// BatchQueryWithCtx mocks base method. +func (m *MockCassandraProvider) BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, name, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "BatchQueryWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// BatchQueryWithCtx indicates an expected call of BatchQueryWithCtx. +func (mr *MockCassandraProviderMockRecorder) BatchQueryWithCtx(ctx, name, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "BatchQueryWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).BatchQueryWithCtx), varargs...) +} + // Connect mocks base method. func (m *MockCassandraProvider) Connect() { m.ctrl.T.Helper() @@ -7905,6 +8343,45 @@ func (mr *MockCassandraProviderMockRecorder) ExecCAS(dest, stmt any, values ...a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecCAS", reflect.TypeOf((*MockCassandraProvider)(nil).ExecCAS), varargs...) } +// ExecCASWithCtx mocks base method. +func (m *MockCassandraProvider) ExecCASWithCtx(ctx context.Context, dest any, stmt string, values ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecCASWithCtx", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecCASWithCtx indicates an expected call of ExecCASWithCtx. +func (mr *MockCassandraProviderMockRecorder) ExecCASWithCtx(ctx, dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecCASWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).ExecCASWithCtx), varargs...) +} + +// ExecWithCtx mocks base method. +func (m *MockCassandraProvider) ExecWithCtx(ctx context.Context, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecWithCtx indicates an expected call of ExecWithCtx. +func (mr *MockCassandraProviderMockRecorder) ExecWithCtx(ctx, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).ExecWithCtx), varargs...) +} + // ExecuteBatch mocks base method. func (m *MockCassandraProvider) ExecuteBatch(name string) error { m.ctrl.T.Helper() @@ -7939,6 +8416,40 @@ func (mr *MockCassandraProviderMockRecorder) ExecuteBatchCAS(name any, dest ...a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCAS", reflect.TypeOf((*MockCassandraProvider)(nil).ExecuteBatchCAS), varargs...) } +// ExecuteBatchCASWithCtx mocks base method. +func (m *MockCassandraProvider) ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) { + m.ctrl.T.Helper() + varargs := []any{ctx, name} + for _, a := range dest { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "ExecuteBatchCASWithCtx", varargs...) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ExecuteBatchCASWithCtx indicates an expected call of ExecuteBatchCASWithCtx. +func (mr *MockCassandraProviderMockRecorder) ExecuteBatchCASWithCtx(ctx, name any, dest ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, name}, dest...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchCASWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).ExecuteBatchCASWithCtx), varargs...) +} + +// ExecuteBatchWithCtx mocks base method. +func (m *MockCassandraProvider) ExecuteBatchWithCtx(ctx context.Context, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ExecuteBatchWithCtx", ctx, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// ExecuteBatchWithCtx indicates an expected call of ExecuteBatchWithCtx. +func (mr *MockCassandraProviderMockRecorder) ExecuteBatchWithCtx(ctx, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ExecuteBatchWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).ExecuteBatchWithCtx), ctx, name) +} + // HealthCheck mocks base method. func (m *MockCassandraProvider) HealthCheck(arg0 context.Context) (any, error) { m.ctrl.T.Helper() @@ -7968,6 +8479,20 @@ func (mr *MockCassandraProviderMockRecorder) NewBatch(name, batchType any) *gomo return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatch", reflect.TypeOf((*MockCassandraProvider)(nil).NewBatch), name, batchType) } +// NewBatchWithCtx mocks base method. +func (m *MockCassandraProvider) NewBatchWithCtx(ctx context.Context, name string, batchType int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "NewBatchWithCtx", ctx, name, batchType) + ret0, _ := ret[0].(error) + return ret0 +} + +// NewBatchWithCtx indicates an expected call of NewBatchWithCtx. +func (mr *MockCassandraProviderMockRecorder) NewBatchWithCtx(ctx, name, batchType any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "NewBatchWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).NewBatchWithCtx), ctx, name, batchType) +} + // Query mocks base method. func (m *MockCassandraProvider) Query(dest any, stmt string, values ...any) error { m.ctrl.T.Helper() @@ -7987,6 +8512,25 @@ func (mr *MockCassandraProviderMockRecorder) Query(dest, stmt any, values ...any return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Query", reflect.TypeOf((*MockCassandraProvider)(nil).Query), varargs...) } +// QueryWithCtx mocks base method. +func (m *MockCassandraProvider) QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error { + m.ctrl.T.Helper() + varargs := []any{ctx, dest, stmt} + for _, a := range values { + varargs = append(varargs, a) + } + ret := m.ctrl.Call(m, "QueryWithCtx", varargs...) + ret0, _ := ret[0].(error) + return ret0 +} + +// QueryWithCtx indicates an expected call of QueryWithCtx. +func (mr *MockCassandraProviderMockRecorder) QueryWithCtx(ctx, dest, stmt any, values ...any) *gomock.Call { + mr.mock.ctrl.T.Helper() + varargs := append([]any{ctx, dest, stmt}, values...) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryWithCtx", reflect.TypeOf((*MockCassandraProvider)(nil).QueryWithCtx), varargs...) +} + // UseLogger mocks base method. func (m *MockCassandraProvider) UseLogger(logger any) { m.ctrl.T.Helper() @@ -9161,6 +9705,162 @@ func (mr *MockKVStoreProviderMockRecorder) UseTracer(tracer any) *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UseTracer", reflect.TypeOf((*MockKVStoreProvider)(nil).UseTracer), tracer) } +// MockPubSubProvider is a mock of PubSubProvider interface. +type MockPubSubProvider struct { + ctrl *gomock.Controller + recorder *MockPubSubProviderMockRecorder +} + +// MockPubSubProviderMockRecorder is the mock recorder for MockPubSubProvider. +type MockPubSubProviderMockRecorder struct { + mock *MockPubSubProvider +} + +// NewMockPubSubProvider creates a new mock instance. +func NewMockPubSubProvider(ctrl *gomock.Controller) *MockPubSubProvider { + mock := &MockPubSubProvider{ctrl: ctrl} + mock.recorder = &MockPubSubProviderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockPubSubProvider) EXPECT() *MockPubSubProviderMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockPubSubProvider) Close() error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Close") + ret0, _ := ret[0].(error) + return ret0 +} + +// Close indicates an expected call of Close. +func (mr *MockPubSubProviderMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockPubSubProvider)(nil).Close)) +} + +// Connect mocks base method. +func (m *MockPubSubProvider) Connect() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Connect") +} + +// Connect indicates an expected call of Connect. +func (mr *MockPubSubProviderMockRecorder) Connect() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connect", reflect.TypeOf((*MockPubSubProvider)(nil).Connect)) +} + +// CreateTopic mocks base method. +func (m *MockPubSubProvider) CreateTopic(context context.Context, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateTopic", context, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateTopic indicates an expected call of CreateTopic. +func (mr *MockPubSubProviderMockRecorder) CreateTopic(context, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTopic", reflect.TypeOf((*MockPubSubProvider)(nil).CreateTopic), context, name) +} + +// DeleteTopic mocks base method. +func (m *MockPubSubProvider) DeleteTopic(context context.Context, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteTopic", context, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteTopic indicates an expected call of DeleteTopic. +func (mr *MockPubSubProviderMockRecorder) DeleteTopic(context, name any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTopic", reflect.TypeOf((*MockPubSubProvider)(nil).DeleteTopic), context, name) +} + +// Health mocks base method. +func (m *MockPubSubProvider) Health() datasource.Health { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Health") + ret0, _ := ret[0].(datasource.Health) + return ret0 +} + +// Health indicates an expected call of Health. +func (mr *MockPubSubProviderMockRecorder) Health() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Health", reflect.TypeOf((*MockPubSubProvider)(nil).Health)) +} + +// Publish mocks base method. +func (m *MockPubSubProvider) Publish(ctx context.Context, topic string, message []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Publish", ctx, topic, message) + ret0, _ := ret[0].(error) + return ret0 +} + +// Publish indicates an expected call of Publish. +func (mr *MockPubSubProviderMockRecorder) Publish(ctx, topic, message any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockPubSubProvider)(nil).Publish), ctx, topic, message) +} + +// Subscribe mocks base method. +func (m *MockPubSubProvider) Subscribe(ctx context.Context, topic string) (*pubsub.Message, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Subscribe", ctx, topic) + ret0, _ := ret[0].(*pubsub.Message) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Subscribe indicates an expected call of Subscribe. +func (mr *MockPubSubProviderMockRecorder) Subscribe(ctx, topic any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Subscribe", reflect.TypeOf((*MockPubSubProvider)(nil).Subscribe), ctx, topic) +} + +// UseLogger mocks base method. +func (m *MockPubSubProvider) UseLogger(logger any) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "UseLogger", logger) +} + +// UseLogger indicates an expected call of UseLogger. +func (mr *MockPubSubProviderMockRecorder) UseLogger(logger any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UseLogger", reflect.TypeOf((*MockPubSubProvider)(nil).UseLogger), logger) +} + +// UseMetrics mocks base method. +func (m *MockPubSubProvider) UseMetrics(metrics any) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "UseMetrics", metrics) +} + +// UseMetrics indicates an expected call of UseMetrics. +func (mr *MockPubSubProviderMockRecorder) UseMetrics(metrics any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UseMetrics", reflect.TypeOf((*MockPubSubProvider)(nil).UseMetrics), metrics) +} + +// UseTracer mocks base method. +func (m *MockPubSubProvider) UseTracer(tracer any) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "UseTracer", tracer) +} + +// UseTracer indicates an expected call of UseTracer. +func (mr *MockPubSubProviderMockRecorder) UseTracer(tracer any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UseTracer", reflect.TypeOf((*MockPubSubProvider)(nil).UseTracer), tracer) +} + // MockSolr is a mock of Solr interface. type MockSolr struct { ctrl *gomock.Controller diff --git a/pkg/gofr/datasource/cassandra/cassandra.go b/pkg/gofr/datasource/cassandra/cassandra.go index 4e37aeb5f..802e9e8f3 100644 --- a/pkg/gofr/datasource/cassandra/cassandra.go +++ b/pkg/gofr/datasource/cassandra/cassandra.go @@ -3,9 +3,11 @@ package cassandra import ( "context" "errors" + "fmt" "reflect" "time" + "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" "github.com/gocql/gocql" @@ -91,16 +93,36 @@ func (c *Client) UseMetrics(metrics interface{}) { } } -// UseTracer sets the tracer for Clickhouse client. +// UseTracer sets the tracer for Cassandra client. func (c *Client) UseTracer(tracer any) { if tracer, ok := tracer.(trace.Tracer); ok { c.tracer = tracer } } -//nolint:exhaustive // We just want to take care of slice and struct in this case. +// Query is the original method without context, preserved for backward compatibility. +// It internally delegates to QueryWithCtx using context.Background() as the default context. func (c *Client) Query(dest any, stmt string, values ...any) error { - defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now()) + return c.QueryWithCtx(context.Background(), dest, stmt, values...) +} + +func (c *Client) Exec(stmt string, values ...any) error { + return c.ExecWithCtx(context.Background(), stmt, values) +} + +func (c *Client) ExecCAS(dest any, stmt string, values ...any) (bool, error) { + return c.ExecCASWithCtx(context.Background(), dest, stmt, values) +} + +func (c *Client) NewBatch(name string, batchType int) error { + return c.NewBatchWithCtx(nil, name, batchType) +} + +//nolint:exhaustive // We just want to take care of slice and struct in this case. +func (c *Client) QueryWithCtx(ctx context.Context, dest any, stmt string, values ...any) error { + _, span := c.addTrace(ctx, "query", stmt) + + defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now(), "query", span) rvo := reflect.ValueOf(dest) if rvo.Kind() != reflect.Ptr { @@ -146,20 +168,24 @@ func (c *Client) Query(dest any, stmt string, values ...any) error { return nil } -func (c *Client) Exec(stmt string, values ...any) error { - defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now()) +func (c *Client) ExecWithCtx(ctx context.Context, stmt string, values ...any) error { + _, span := c.addTrace(ctx, "exec", stmt) + + defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now(), "exec", span) return c.cassandra.session.query(stmt, values...).exec() } //nolint:exhaustive // We just want to take care of slice and struct in this case. -func (c *Client) ExecCAS(dest any, stmt string, values ...any) (bool, error) { +func (c *Client) ExecCASWithCtx(ctx context.Context, dest any, stmt string, values ...any) (bool, error) { var ( applied bool err error ) - defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now()) + _, span := c.addTrace(ctx, "exec-cas", stmt) + + defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now(), "exec-cas", span) rvo := reflect.ValueOf(dest) if rvo.Kind() != reflect.Ptr { @@ -192,7 +218,7 @@ func (c *Client) ExecCAS(dest any, stmt string, values ...any) (bool, error) { return applied, err } -func (c *Client) NewBatch(name string, batchType int) error { +func (c *Client) NewBatchWithCtx(_ context.Context, name string, batchType int) error { switch batchType { case LoggedBatch, UnloggedBatch, CounterBatch: if len(c.cassandra.batches) == 0 { @@ -301,13 +327,18 @@ func (*Client) getColumnsFromColumnsInfo(columns []gocql.ColumnInfo) []string { return cols } -func (c *Client) sendOperationStats(ql *QueryLog, startTime time.Time) { +func (c *Client) sendOperationStats(ql *QueryLog, startTime time.Time, method string, span trace.Span) { duration := time.Since(startTime).Milliseconds() ql.Duration = duration c.logger.Debug(ql) + if span != nil { + defer span.End() + span.SetAttributes(attribute.Int64(fmt.Sprintf("cassandra.%v.duration", method), duration)) + } + c.metrics.RecordHistogram(context.Background(), "app_cassandra_stats", float64(duration), "hostname", c.config.Hosts, "keyspace", c.config.Keyspace) @@ -352,3 +383,18 @@ func (c *Client) HealthCheck(context.Context) (any, error) { return &h, nil } + +func (c *Client) addTrace(ctx context.Context, method, query string) (context.Context, trace.Span) { + if c.tracer != nil { + tracerCtx, span := c.tracer.Start(ctx, fmt.Sprintf("cassandra-%v", method)) + + span.SetAttributes( + attribute.String("cassandra.query", query), + attribute.String("cassandra.keyspace", c.config.Keyspace), + ) + + return tracerCtx, span + } + + return ctx, nil +} diff --git a/pkg/gofr/datasource/cassandra/cassandra_batch.go b/pkg/gofr/datasource/cassandra/cassandra_batch.go index 6d0beac70..8f75feca6 100644 --- a/pkg/gofr/datasource/cassandra/cassandra_batch.go +++ b/pkg/gofr/datasource/cassandra/cassandra_batch.go @@ -1,10 +1,27 @@ package cassandra import ( + "context" "time" ) func (c *Client) BatchQuery(name, stmt string, values ...any) error { + return c.BatchQueryWithCtx(context.Background(), name, stmt, values...) +} + +func (c *Client) ExecuteBatch(name string) error { + return c.ExecuteBatchWithCtx(context.Background(), name) +} + +func (c *Client) ExecuteBatchCAS(name string, dest ...any) (bool, error) { + return c.ExecuteBatchCASWithCtx(context.Background(), name, dest) +} + +func (c *Client) BatchQueryWithCtx(ctx context.Context, name, stmt string, values ...any) error { + _, span := c.addTrace(ctx, "batch-query", stmt) + + defer c.sendOperationStats(&QueryLog{Query: stmt, Keyspace: c.config.Keyspace}, time.Now(), "batch-query", span) + b, ok := c.cassandra.batches[name] if !ok { return errBatchNotInitialised @@ -15,8 +32,11 @@ func (c *Client) BatchQuery(name, stmt string, values ...any) error { return nil } -func (c *Client) ExecuteBatch(name string) error { - defer c.sendOperationStats(&QueryLog{Query: "batch", Keyspace: c.config.Keyspace}, time.Now()) +func (c *Client) ExecuteBatchWithCtx(ctx context.Context, name string) error { + _, span := c.addTrace(ctx, "execute-batch", "batch") + + defer c.sendOperationStats(&QueryLog{Query: "batch", Keyspace: c.config.Keyspace}, time.Now(), "execute-batch", + span) b, ok := c.cassandra.batches[name] if !ok { @@ -26,8 +46,11 @@ func (c *Client) ExecuteBatch(name string) error { return c.cassandra.session.executeBatch(b) } -func (c *Client) ExecuteBatchCAS(name string, dest ...any) (bool, error) { - defer c.sendOperationStats(&QueryLog{Query: "batch", Keyspace: c.config.Keyspace}, time.Now()) +func (c *Client) ExecuteBatchCASWithCtx(ctx context.Context, name string, dest ...any) (bool, error) { + _, span := c.addTrace(ctx, "execute-batch-cas", "batch") + + defer c.sendOperationStats(&QueryLog{Query: "batch", Keyspace: c.config.Keyspace}, time.Now(), "execute-batch-cas", + span) b, ok := c.cassandra.batches[name] if !ok { diff --git a/pkg/gofr/datasource/cassandra/cassandra_test.go b/pkg/gofr/datasource/cassandra/cassandra_test.go index 010470a82..a8f452e80 100644 --- a/pkg/gofr/datasource/cassandra/cassandra_test.go +++ b/pkg/gofr/datasource/cassandra/cassandra_test.go @@ -5,6 +5,8 @@ import ( "errors" "testing" + "go.opentelemetry.io/otel" + "github.com/gocql/gocql" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -47,6 +49,7 @@ func initTest(t *testing.T) (*Client, *mockDependencies) { client := New(config) client.UseLogger(mockLogger) client.UseMetrics(mockMetrics) + client.UseTracer(otel.GetTracerProvider().Tracer("gofr-cassandra")) client.cassandra.session = mockSession client.cassandra.batches = map[string]batch{mockBatchName: mockBatch} @@ -182,11 +185,11 @@ func Test_Exec(t *testing.T) { expErr error }{ {"success case", func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().exec().Return(nil).Times(1) }, nil}, {"failure case", func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().exec().Return(errMock).Times(1) }, errMock}, } @@ -221,27 +224,27 @@ func Test_ExecCAS(t *testing.T) { expErr error }{ {"success case: struct dest, applied true", &mockStruct, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().mapScanCAS(gomock.AssignableToTypeOf(map[string]interface{}{})).Return(true, nil).Times(1) }, true, nil}, {"success case: int dest, applied true", &mockInt, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().scanCAS(gomock.Any()).Return(true, nil).Times(1) }, true, nil}, {"failure case: struct dest, error", &mockStruct, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().mapScanCAS(gomock.AssignableToTypeOf(map[string]interface{}{})).Return(false, errMock).Times(1) }, false, errMock}, {"failure case: int dest, error", &mockInt, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) mockDeps.mockQuery.EXPECT().scanCAS(gomock.Any()).Return(false, errMock).Times(1) }, false, errMock}, {"failure case: dest is not pointer", mockInt, func() {}, false, errDestinationIsNotPointer}, {"failure case: dest is slice", &[]int{}, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) }, false, errUnexpectedSlice{target: "[]*[]int"}}, {"failure case: dest is map", &map[string]interface{}{}, func() { - mockDeps.mockSession.EXPECT().query(query).Return(mockDeps.mockQuery).Times(1) + mockDeps.mockSession.EXPECT().query(query, nil).Return(mockDeps.mockQuery).Times(1) }, false, errUnexpectedMap}, } diff --git a/pkg/gofr/datasource/cassandra/go.mod b/pkg/gofr/datasource/cassandra/go.mod index afad03699..73196a39c 100644 --- a/pkg/gofr/datasource/cassandra/go.mod +++ b/pkg/gofr/datasource/cassandra/go.mod @@ -5,16 +5,19 @@ go 1.22 require ( github.com/gocql/gocql v1.6.0 github.com/stretchr/testify v1.9.0 + go.opentelemetry.io/otel v1.30.0 go.opentelemetry.io/otel/trace v1.30.0 go.uber.org/mock v0.4.0 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - go.opentelemetry.io/otel v1.30.0 // indirect + go.opentelemetry.io/otel/metric v1.30.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/gofr/datasource/cassandra/go.sum b/pkg/gofr/datasource/cassandra/go.sum index 54b3b0ad7..8383ada62 100644 --- a/pkg/gofr/datasource/cassandra/go.sum +++ b/pkg/gofr/datasource/cassandra/go.sum @@ -5,6 +5,11 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/gocql/gocql v1.6.0 h1:IdFdOTbnpbd0pDhl4REKQDM+Q0SzKXQ1Yh+YZZ8T/qU= github.com/gocql/gocql v1.6.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= @@ -26,6 +31,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= diff --git a/pkg/gofr/external_db.go b/pkg/gofr/external_db.go index 0dbfc92d8..3bf71d717 100644 --- a/pkg/gofr/external_db.go +++ b/pkg/gofr/external_db.go @@ -78,6 +78,10 @@ func (a *App) AddCassandra(db container.CassandraProvider) { db.UseLogger(a.Logger()) db.UseMetrics(a.Metrics()) + tracer := otel.GetTracerProvider().Tracer("gofr-cassandra") + + db.UseTracer(tracer) + db.Connect() a.container.Cassandra = db diff --git a/pkg/gofr/external_db_test.go b/pkg/gofr/external_db_test.go index 7018605f9..f60f0b66e 100644 --- a/pkg/gofr/external_db_test.go +++ b/pkg/gofr/external_db_test.go @@ -61,6 +61,7 @@ func TestApp_AddCassandra(t *testing.T) { mock.EXPECT().UseLogger(app.Logger()) mock.EXPECT().UseMetrics(app.Metrics()) + mock.EXPECT().UseTracer(otel.GetTracerProvider().Tracer("gofr-cassandra")) mock.EXPECT().Connect() app.AddCassandra(mock) diff --git a/pkg/gofr/migration/cassandra.go b/pkg/gofr/migration/cassandra.go index e2dd4be0b..30696d6a5 100644 --- a/pkg/gofr/migration/cassandra.go +++ b/pkg/gofr/migration/cassandra.go @@ -1,25 +1,26 @@ package migration import ( + "context" "time" "gofr.dev/pkg/gofr/container" ) type cassandraDS struct { - container.Cassandra + container.CassandraWithContext } type cassandraMigrator struct { - container.Cassandra + container.CassandraWithContext migrator } func (cs cassandraDS) apply(m migrator) migrator { return cassandraMigrator{ - Cassandra: cs.Cassandra, - migrator: m, + CassandraWithContext: cs.CassandraWithContext, + migrator: m, } } @@ -33,7 +34,7 @@ const ( ) func (cs cassandraMigrator) checkAndCreateMigrationTable(c *container.Container) error { - if err := c.Cassandra.Exec(checkAndCreateCassandraMigrationTable); err != nil { + if err := c.Cassandra.ExecWithCtx(context.Background(), checkAndCreateCassandraMigrationTable); err != nil { return err } @@ -45,7 +46,7 @@ func (cs cassandraMigrator) getLastMigration(c *container.Container) int64 { var lastMigrations []int64 - err := c.Cassandra.Query(&lastMigrations, getLastCassandraGoFrMigration) + err := c.Cassandra.QueryWithCtx(context.Background(), &lastMigrations, getLastCassandraGoFrMigration) if err != nil { return 0 } @@ -76,7 +77,7 @@ func (cs cassandraMigrator) beginTransaction(c *container.Container) transaction } func (cs cassandraMigrator) commitMigration(c *container.Container, data transactionData) error { - err := cs.Cassandra.Exec(insertCassandraGoFrMigrationRow, data.MigrationNumber, + err := cs.CassandraWithContext.ExecWithCtx(context.Background(), insertCassandraGoFrMigrationRow, data.MigrationNumber, "UP", data.StartTime, time.Since(data.StartTime).Milliseconds()) if err != nil { return err diff --git a/pkg/gofr/migration/cassandra_test.go b/pkg/gofr/migration/cassandra_test.go index 1ab1844d2..97aff1494 100644 --- a/pkg/gofr/migration/cassandra_test.go +++ b/pkg/gofr/migration/cassandra_test.go @@ -1,6 +1,7 @@ package migration import ( + "context" "database/sql" "testing" "time" @@ -12,7 +13,7 @@ import ( "gofr.dev/pkg/gofr/testutil" ) -func cassandraSetup(t *testing.T) (migrator, *container.MockCassandra, *container.Container) { +func cassandraSetup(t *testing.T) (migrator, *container.MockCassandraWithContext, *container.Container) { t.Helper() mockContainer, mocks := container.NewMockContainer(t) @@ -21,7 +22,7 @@ func cassandraSetup(t *testing.T) (migrator, *container.MockCassandra, *containe ds := Datasource{Cassandra: mockContainer.Cassandra} - cassandraDB := cassandraDS{Cassandra: mockCassandra} + cassandraDB := cassandraDS{CassandraWithContext: mockCassandra} migratorWithCassandra := cassandraDB.apply(&ds) mockContainer.Cassandra = mockCassandra @@ -41,7 +42,7 @@ func Test_CassandraCheckAndCreateMigrationTable(t *testing.T) { } for i, tc := range testCases { - mockCassandra.EXPECT().Exec(checkAndCreateCassandraMigrationTable).Return(tc.err) + mockCassandra.EXPECT().ExecWithCtx(context.Background(), checkAndCreateCassandraMigrationTable).Return(tc.err) err := migratorWithCassandra.checkAndCreateMigrationTable(mockContainer) @@ -64,7 +65,7 @@ func Test_CassandraGetLastMigration(t *testing.T) { var lastMigration []int64 for i, tc := range testCases { - mockCassandra.EXPECT().Query(&lastMigration, getLastCassandraGoFrMigration).Return(tc.err) + mockCassandra.EXPECT().QueryWithCtx(context.Background(), &lastMigration, getLastCassandraGoFrMigration).Return(tc.err) resp := migratorWithCassandra.getLastMigration(mockContainer) @@ -91,7 +92,7 @@ func Test_CassandraCommitMigration(t *testing.T) { } for i, tc := range testCases { - mockCassandra.EXPECT().Exec(insertCassandraGoFrMigrationRow, td.MigrationNumber, + mockCassandra.EXPECT().ExecWithCtx(context.Background(), insertCassandraGoFrMigrationRow, td.MigrationNumber, "UP", td.StartTime, gomock.Any()).Return(tc.err) err := migratorWithCassandra.commitMigration(mockContainer, td) From ba08febffc8ff036e8990c590af885c2c7b35064 Mon Sep 17 00:00:00 2001 From: Aryan Mehrotra <44036979+aryanmehrotra@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:31:31 +0530 Subject: [PATCH 26/26] update gofr version in eventhub (#1105) --- pkg/gofr/datasource/pubsub/eventhub/go.mod | 6 ++---- pkg/gofr/datasource/pubsub/eventhub/go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/gofr/datasource/pubsub/eventhub/go.mod b/pkg/gofr/datasource/pubsub/eventhub/go.mod index ddf0a7b95..3b890b1e6 100644 --- a/pkg/gofr/datasource/pubsub/eventhub/go.mod +++ b/pkg/gofr/datasource/pubsub/eventhub/go.mod @@ -2,15 +2,13 @@ module gofr.dev/pkg/gofr/datasource/pubsub/eventhub go 1.22.3 -replace gofr.dev => ../../../../../../gofr - require ( github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs v1.2.2 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.4.1 github.com/stretchr/testify v1.9.0 go.opentelemetry.io/otel/trace v1.30.0 go.uber.org/mock v0.4.0 - gofr.dev v1.21.0 + gofr.dev v1.23.0 nhooyr.io/websocket v1.8.11 ) @@ -24,6 +22,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect go.opentelemetry.io/otel v1.30.0 // indirect golang.org/x/net v0.29.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/text v0.19.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/pkg/gofr/datasource/pubsub/eventhub/go.sum b/pkg/gofr/datasource/pubsub/eventhub/go.sum index fe0586c39..a6b8cb3a6 100644 --- a/pkg/gofr/datasource/pubsub/eventhub/go.sum +++ b/pkg/gofr/datasource/pubsub/eventhub/go.sum @@ -52,6 +52,8 @@ go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8d go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +gofr.dev v1.23.0 h1:LejSqzoo+X8qKoesETrIaWfJbPNWgeJl2opyNy/WzXc= +gofr.dev v1.23.0/go.mod h1:jldZJGrUKxD6BUEFwdlODcBCGBSvgkVoMy9q15sJm2Q= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= @@ -60,8 +62,8 @@ golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=