Merge branch 'master' of github.com:carner/go-redis into expirenx

This commit is contained in:
Elena Kolevska 2023-06-16 12:02:58 +01:00
commit e6add27a69
41 changed files with 636 additions and 286 deletions

41
.github/workflows/doctests.yaml vendored Normal file
View File

@ -0,0 +1,41 @@
name: Documentation Tests
on:
push:
branches: [master, examples]
pull_request:
branches: [master, examples]
permissions:
contents: read
jobs:
doctests:
name: doctests
runs-on: ubuntu-latest
services:
redis-stack:
image: redis/redis-stack-server:latest
options: >-
--health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
ports:
- 6379:6379
strategy:
fail-fast: false
matrix:
go-version: [ "1.18", "1.19", "1.20" ]
steps:
- name: Set up ${{ matrix.go-version }}
uses: actions/setup-go@v4
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v3
- name: Test doc examples
working-directory: ./doctests
run: go test

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
*.rdb
testdata/*
.idea/
.DS_Store

View File

@ -1,3 +1,14 @@
## [9.0.5](https://github.com/redis/go-redis/compare/v9.0.4...v9.0.5) (2023-05-29)
### Features
* Add ACL LOG ([#2536](https://github.com/redis/go-redis/issues/2536)) ([31ba855](https://github.com/redis/go-redis/commit/31ba855ddebc38fbcc69a75d9d4fb769417cf602))
* add field protocol to setupClusterQueryParams ([#2600](https://github.com/redis/go-redis/issues/2600)) ([840c25c](https://github.com/redis/go-redis/commit/840c25cb6f320501886a82a5e75f47b491e46fbe))
* add protocol option ([#2598](https://github.com/redis/go-redis/issues/2598)) ([3917988](https://github.com/redis/go-redis/commit/391798880cfb915c4660f6c3ba63e0c1a459e2af))
## [9.0.4](https://github.com/redis/go-redis/compare/v9.0.3...v9.0.4) (2023-05-01)

View File

@ -62,6 +62,7 @@ type ClusterOptions struct {
OnConnect func(ctx context.Context, cn *Conn) error
Protocol int
Username string
Password string
@ -216,6 +217,7 @@ func setupClusterConn(u *url.URL, host string, o *ClusterOptions) (*ClusterOptio
func setupClusterQueryParams(u *url.URL, o *ClusterOptions) (*ClusterOptions, error) {
q := queryOptions{q: u.Query()}
o.Protocol = q.int("protocol")
o.ClientName = q.string("client_name")
o.MaxRedirects = q.int("max_redirects")
o.ReadOnly = q.bool("read_only")
@ -263,6 +265,7 @@ func (opt *ClusterOptions) clientOptions() *Options {
Dialer: opt.Dialer,
OnConnect: opt.OnConnect,
Protocol: opt.Protocol,
Username: opt.Username,
Password: opt.Password,

View File

@ -583,6 +583,35 @@ var _ = Describe("ClusterClient", func() {
})
}
Describe("ClusterClient PROTO 2", func() {
BeforeEach(func() {
opt = redisClusterOptions()
opt.Protocol = 2
client = cluster.newClusterClient(ctx, opt)
err := client.ForEachMaster(ctx, func(ctx context.Context, master *redis.Client) error {
return master.FlushDB(ctx).Err()
})
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
_ = client.ForEachMaster(ctx, func(ctx context.Context, master *redis.Client) error {
return master.FlushDB(ctx).Err()
})
Expect(client.Close()).NotTo(HaveOccurred())
})
It("should CLUSTER PROTO 2", func() {
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := c.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainElements("proto", int64(2)))
return nil
})
})
})
Describe("ClusterClient", func() {
BeforeEach(func() {
opt = redisClusterOptions()
@ -746,6 +775,15 @@ var _ = Describe("ClusterClient", func() {
})
})
It("should CLUSTER PROTO 3", func() {
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := c.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(HaveKeyWithValue("proto", int64(3)))
return nil
})
})
It("should CLUSTER MYSHARDID", func() {
shardID, err := client.ClusterMyShardID(ctx).Result()
Expect(err).NotTo(HaveOccurred())
@ -1481,6 +1519,10 @@ var _ = Describe("ClusterClient ParseURL", func() {
test: "UseDefault",
url: "redis://localhost:123?conn_max_idle_time=",
o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, ConnMaxIdleTime: 0},
}, {
test: "Protocol",
url: "redis://localhost:123?protocol=2",
o: &redis.ClusterOptions{Addrs: []string{"localhost:123"}, Protocol: 2},
}, {
test: "ClientName",
url: "redis://localhost:123?client_name=cluster_hi",

View File

@ -340,6 +340,8 @@ func (cmd *Cmd) Bool() (bool, error) {
func toBool(val interface{}) (bool, error) {
switch val := val.(type) {
case bool:
return val, nil
case int64:
return val != 0, nil
case string:
@ -2373,7 +2375,7 @@ func readStreamGroups(rd *proto.Reader) ([]XInfoStreamGroup, error) {
}
case "entries-read":
group.EntriesRead, err = rd.ReadInt()
if err != nil {
if err != nil && err != Nil {
return nil, err
}
case "lag":

View File

@ -6331,6 +6331,97 @@ var _ = Describe("Commands", func() {
}
}
}
Expect(res.Groups).To(Equal([]redis.XInfoStreamGroup{
{
Name: "group1",
LastDeliveredID: "3-0",
EntriesRead: 3,
Lag: 0,
PelCount: 3,
Pending: []redis.XInfoStreamGroupPending{
{ID: "1-0", Consumer: "consumer1", DeliveryTime: time.Time{}, DeliveryCount: 1},
{ID: "2-0", Consumer: "consumer1", DeliveryTime: time.Time{}, DeliveryCount: 1},
},
Consumers: []redis.XInfoStreamConsumer{
{
Name: "consumer1",
SeenTime: time.Time{},
ActiveTime: time.Time{},
PelCount: 2,
Pending: []redis.XInfoStreamConsumerPending{
{ID: "1-0", DeliveryTime: time.Time{}, DeliveryCount: 1},
{ID: "2-0", DeliveryTime: time.Time{}, DeliveryCount: 1},
},
},
{
Name: "consumer2",
SeenTime: time.Time{},
ActiveTime: time.Time{},
PelCount: 1,
Pending: []redis.XInfoStreamConsumerPending{
{ID: "3-0", DeliveryTime: time.Time{}, DeliveryCount: 1},
},
},
},
},
{
Name: "group2",
LastDeliveredID: "3-0",
EntriesRead: 3,
Lag: 0,
PelCount: 2,
Pending: []redis.XInfoStreamGroupPending{
{ID: "2-0", Consumer: "consumer1", DeliveryTime: time.Time{}, DeliveryCount: 1},
{ID: "3-0", Consumer: "consumer1", DeliveryTime: time.Time{}, DeliveryCount: 1},
},
Consumers: []redis.XInfoStreamConsumer{
{
Name: "consumer1",
SeenTime: time.Time{},
ActiveTime: time.Time{},
PelCount: 2,
Pending: []redis.XInfoStreamConsumerPending{
{ID: "2-0", DeliveryTime: time.Time{}, DeliveryCount: 1},
{ID: "3-0", DeliveryTime: time.Time{}, DeliveryCount: 1},
},
},
},
},
}))
// entries-read = nil
Expect(client.Del(ctx, "xinfo-stream-full-stream").Err()).NotTo(HaveOccurred())
id, err := client.XAdd(ctx, &redis.XAddArgs{
Stream: "xinfo-stream-full-stream",
ID: "*",
Values: []any{"k1", "v1"},
}).Result()
Expect(err).NotTo(HaveOccurred())
Expect(client.XGroupCreateMkStream(ctx, "xinfo-stream-full-stream", "xinfo-stream-full-group", "0").Err()).NotTo(HaveOccurred())
res, err = client.XInfoStreamFull(ctx, "xinfo-stream-full-stream", 0).Result()
Expect(err).NotTo(HaveOccurred())
Expect(res).To(Equal(&redis.XInfoStreamFull{
Length: 1,
RadixTreeKeys: 1,
RadixTreeNodes: 2,
LastGeneratedID: id,
MaxDeletedEntryID: "0-0",
EntriesAdded: 1,
Entries: []redis.XMessage{{ID: id, Values: map[string]any{"k1": "v1"}}},
Groups: []redis.XInfoStreamGroup{
{
Name: "xinfo-stream-full-group",
LastDeliveredID: "0-0",
EntriesRead: 0,
Lag: 1,
PelCount: 0,
Pending: []redis.XInfoStreamGroupPending{},
Consumers: []redis.XInfoStreamConsumer{},
},
},
RecordedFirstEntryID: id,
}))
})
It("should XINFO GROUPS", func() {

22
doctests/README.md Normal file
View File

@ -0,0 +1,22 @@
# Command examples for redis.io
These examples appear on the [Redis documentation](https://redis.io) site as part of the tabbed examples interface.
## How to add examples
- Create a Go test file with a meaningful name in the current folder.
- Create a single method prefixed with `Example` and write your test in it.
- Determine the id for the example you're creating and add it as the first line of the file: `// EXAMPLE: set_and_get`.
- We're using the [Testable Examples](https://go.dev/blog/examples) feature of Go to test the desired output has been written to stdout.
### Special markup
See https://github.com/redis-stack/redis-stack-website#readme for more details.
## How to test the examples
- Start a Redis server locally on port 6379
- CD into the `doctests` directory
- Run `go test` to test all examples in the directory.
- Run `go test filename.go` to test a single file

View File

@ -0,0 +1,47 @@
// EXAMPLE: lpush_and_lrange
// HIDE_START
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleLPushLRange() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
// HIDE_END
// REMOVE_START
errFlush := rdb.FlushDB(ctx).Err() // Clear the database before each test
if errFlush != nil {
panic(errFlush)
}
// REMOVE_END
listSize, err := rdb.LPush(ctx, "my_bikes", "bike:1", "bike:2").Result()
if err != nil {
panic(err)
}
fmt.Println(listSize)
value, err := rdb.LRange(ctx, "my_bikes", 0, -1).Result()
if err != nil {
panic(err)
}
fmt.Println(value)
// HIDE_START
// Output: 2
// [bike:2 bike:1]
}
// HIDE_END

47
doctests/set_get_test.go Normal file
View File

@ -0,0 +1,47 @@
// EXAMPLE: set_and_get
// HIDE_START
package example_commands_test
import (
"context"
"fmt"
"github.com/redis/go-redis/v9"
)
func ExampleSetGet() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password docs
DB: 0, // use default DB
})
// HIDE_END
// REMOVE_START
errFlush := rdb.FlushDB(ctx).Err() // Clear the database before each test
if errFlush != nil {
panic(errFlush)
}
// REMOVE_END
err := rdb.Set(ctx, "bike:1", "Process 134", 0).Err()
if err != nil {
panic(err)
}
fmt.Println("OK")
value, err := rdb.Get(ctx, "bike:1").Result()
if err != nil {
panic(err)
}
fmt.Printf("The name of the bike is %s", value)
// HIDE_START
// Output: OK
// The name of the bike is Process 134
}
// HIDE_END

View File

@ -5,7 +5,7 @@ go 1.18
replace github.com/redis/go-redis/v9 => ../..
require (
github.com/redis/go-redis/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.5
go.uber.org/zap v1.24.0
)

View File

@ -4,7 +4,7 @@ go 1.18
replace github.com/redis/go-redis/v9 => ../..
require github.com/redis/go-redis/v9 v9.0.4
require github.com/redis/go-redis/v9 v9.0.5
require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect

View File

@ -4,7 +4,7 @@ go 1.18
replace github.com/redis/go-redis/v9 => ../..
require github.com/redis/go-redis/v9 v9.0.4
require github.com/redis/go-redis/v9 v9.0.5
require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect

View File

@ -1,53 +0,0 @@
# See https://prometheus.io/docs/alerting/latest/configuration/ for details.
global:
# The smarthost and SMTP sender used for mail notifications.
smtp_smarthost: 'mailhog:1025'
smtp_from: 'alertmanager@example.com'
smtp_require_tls: false
receivers:
- name: 'team-X'
email_configs:
- to: 'some-receiver@example.com'
send_resolved: true
# The root route on which each incoming alert enters.
route:
# The labels by which incoming alerts are grouped together. For example,
# multiple alerts coming in for cluster=A and alertname=LatencyHigh would
# be batched into a single group.
group_by: ['alertname', 'cluster', 'service']
# When a new group of alerts is created by an incoming alert, wait at
# least 'group_wait' to send the initial notification.
# This way ensures that you get multiple alerts for the same group that start
# firing shortly after another are batched together on the first
# notification.
group_wait: 30s
# When the first notification was sent, wait 'group_interval' to send a batch
# of new alerts that started firing for that group.
group_interval: 5m
# If an alert has successfully been sent, wait 'repeat_interval' to
# resend them.
repeat_interval: 3h
# A default receiver
receiver: team-X
# All the above attributes are inherited by all child routes and can
# overwritten on each.
# The child route trees.
routes:
# This route matches error alerts created from spans or logs.
- matchers:
- alert_kind="error"
group_interval: 24h
receiver: team-X
# The directory from which notification templates are read.
templates:
- '/etc/alertmanager/template/*.tmpl'

View File

@ -1,22 +1,18 @@
[sources.syslog_logs]
type = "demo_logs"
format = "syslog"
interval = 0.1
[sources.apache_common_logs]
type = "demo_logs"
format = "apache_common"
interval = 0.1
[sources.apache_error_logs]
type = "demo_logs"
format = "apache_error"
interval = 0.1
[sources.json_logs]
type = "demo_logs"
format = "json"
interval = 0.1
# Parse Syslog logs
# See the Vector Remap Language reference for more info: https://vrl.dev

View File

@ -2,7 +2,7 @@ version: '3'
services:
clickhouse:
image: clickhouse/clickhouse-server:22.7
image: clickhouse/clickhouse-server:22.10
restart: on-failure
environment:
CLICKHOUSE_DB: uptrace
@ -12,17 +12,34 @@ services:
timeout: 1s
retries: 30
volumes:
- ch_data:/var/lib/clickhouse
- ch_data1:/var/lib/clickhouse
ports:
- '8123:8123'
- '9000:9000'
postgres:
image: postgres:15-alpine
restart: on-failure
environment:
PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_USER: uptrace
POSTGRES_PASSWORD: uptrace
POSTGRES_DB: uptrace
healthcheck:
test: ['CMD-SHELL', 'pg_isready']
interval: 1s
timeout: 1s
retries: 30
volumes:
- 'pg_data1:/var/lib/postgresql/data/pgdata'
ports:
- '5432:5432'
uptrace:
image: 'uptrace/uptrace:1.3.0'
image: 'uptrace/uptrace:1.4.7'
#image: 'uptrace/uptrace-dev:latest'
restart: on-failure
volumes:
- uptrace_data:/var/lib/uptrace
- ./uptrace.yml:/etc/uptrace/uptrace.yml
#environment:
# - DEBUG=2
@ -33,7 +50,7 @@ services:
clickhouse:
condition: service_healthy
otel-collector:
otelcol:
image: otel/opentelemetry-collector-contrib:0.58.0
restart: on-failure
volumes:
@ -43,22 +60,10 @@ services:
- '4318:4318'
vector:
image: timberio/vector:0.24.X-alpine
image: timberio/vector:0.28.X-alpine
volumes:
- ./config/vector.toml:/etc/vector/vector.toml:ro
alertmanager:
image: prom/alertmanager:v0.24.0
restart: on-failure
volumes:
- ./config/alertmanager.yml:/etc/alertmanager/config.yml
- alertmanager_data:/alertmanager
ports:
- 9093:9093
command:
- '--config.file=/etc/alertmanager/config.yml'
- '--storage.path=/alertmanager'
mailhog:
image: mailhog/mailhog:v1.0.1
restart: on-failure
@ -73,6 +78,5 @@ services:
image: redis
volumes:
uptrace_data:
ch_data:
alertmanager_data:
ch_data1:
pg_data1:

View File

@ -9,10 +9,10 @@ replace github.com/redis/go-redis/extra/redisotel/v9 => ../../extra/redisotel
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../../extra/rediscmd
require (
github.com/redis/go-redis/extra/redisotel/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.4
github.com/uptrace/uptrace-go v1.15.0
go.opentelemetry.io/otel v1.15.0
github.com/redis/go-redis/extra/redisotel/v9 v9.0.5
github.com/redis/go-redis/v9 v9.0.5
github.com/uptrace/uptrace-go v1.16.0
go.opentelemetry.io/otel v1.16.0
)
require (
@ -23,23 +23,23 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.15.2 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.4 // indirect
go.opentelemetry.io/contrib/instrumentation/runtime v0.41.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.38.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.15.0 // indirect
go.opentelemetry.io/otel/metric v0.38.0 // indirect
go.opentelemetry.io/otel/sdk v1.15.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.38.0 // indirect
go.opentelemetry.io/otel/trace v1.15.0 // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5 // indirect
go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 // indirect
go.opentelemetry.io/otel/metric v1.16.0 // indirect
go.opentelemetry.io/otel/sdk v1.16.0 // indirect
go.opentelemetry.io/otel/sdk/metric v0.39.0 // indirect
go.opentelemetry.io/otel/trace v1.16.0 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
)

View File

@ -156,9 +156,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/uptrace/uptrace-go v1.15.0 h1:0rUzl6me8GfrCjlR8/ymwlWAnZbNLY8mmAtC5ucQHFA=
github.com/uptrace/uptrace-go v1.15.0/go.mod h1:nPXTUXEaKhVMlUZNJonusNXGglumm+F3s3RO7UJ8sz0=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/uptrace/uptrace-go v1.16.0 h1:yB9vt1hBYYoXWExNx0okubLOjd339d7lH+/5o+Lp+MY=
github.com/uptrace/uptrace-go v1.16.0/go.mod h1:Ssc5wLpoL+9V0qkT5FtrIiru9SY4xb7q1UVLjSpxpCg=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -167,30 +167,30 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/contrib/instrumentation/runtime v0.41.0 h1:536lQ8kbSVZvjuPt+8E/ix3oo0lHiSgh0bKJQ0N7Snc=
go.opentelemetry.io/contrib/instrumentation/runtime v0.41.0/go.mod h1:75MnsWofuhVyQ0rN98KkPn1RF5lFcYIwHy2DMHl9Tfk=
go.opentelemetry.io/otel v1.15.0 h1:NIl24d4eiLJPM0vKn4HjLYM+UZf6gSfi9Z+NmCxkWbk=
go.opentelemetry.io/otel v1.15.0/go.mod h1:qfwLEbWhLPk5gyWrne4XnF0lC8wtywbuJbgfAE3zbek=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.0 h1:ZSdnH1x5Gm/eUFNQquwSt4/LMCOqS6KPlI9qaTKx5Ho=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.0/go.mod h1:uOTV75+LOzV+ODmL8ahRLWkFA3eQcSC2aAsbxIu4duk=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.38.0 h1:yrZB4yN5wfL3xYtpr7sToqg+d7we6JmmQKVUhwEiSCU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.38.0/go.mod h1:QF3fAQsmF6UrxpgUelM4wxUkyBlyVoyj1Oi3BQ6/TuI=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.38.0 h1:VbOU5gwBVxCdavUhJrpvyMwrg3B0CvEwroh8IpBnuW4=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.38.0/go.mod h1:hg4ivadJqcdaFEUdPeuw7fdi06SHWD0tFE/T3j/8tq4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.0 h1:rk5I7PaOk5NGQHfHR2Rz6MgdA8AYQSHwsigFsOxEC1c=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.0/go.mod h1:pvkFJxNUXyJ5i8u6m8NIcqkoOf/65VM2mSyBbBJfeVQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.0 h1:rHD0vfQbtki6/FnsMzTpAOgdv+Ku+T6R47MZXmgelf8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.0/go.mod h1:RPagkaZrpwD+rSwQjzos6rBLsHOvenOqufCj4/7I46E=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.15.0 h1:asTjhnG46zZSrrLHjrDJznK4lRS4Hjb0iwzU2jidyOA=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.15.0/go.mod h1:rqaqVhQv4wLN9xUy3JFCgDiltfgtQUFkJywQfm4OwhU=
go.opentelemetry.io/otel/metric v0.38.0 h1:vv/Nv/44S3GzMMmeUhaesBKsAenE6xLkTVWL+zuv30w=
go.opentelemetry.io/otel/metric v0.38.0/go.mod h1:uAtxN5hl8aXh5irD8afBtSwQU5Zjg64WWSz6KheZxBg=
go.opentelemetry.io/otel/sdk v1.15.0 h1:jZTCkRRd08nxD6w7rIaZeDNGZGGQstH3SfLQ3ZsKICk=
go.opentelemetry.io/otel/sdk v1.15.0/go.mod h1:XDEMrYWzJ4YlC17i6Luih2lwDw2j6G0PkUfr1ZqE+rQ=
go.opentelemetry.io/otel/sdk/metric v0.38.0 h1:c/6/VZihe+5ink8ERufY1/o1QtnoON+k1YonZF2jYR4=
go.opentelemetry.io/otel/sdk/metric v0.38.0/go.mod h1:tqrguFLaGJ3i+uyG67bzxJgsG6Y2bL6HmAn9V/cVRRo=
go.opentelemetry.io/otel/trace v1.15.0 h1:5Fwje4O2ooOxkfyqI/kJwxWotggDLix4BSAvpE1wlpo=
go.opentelemetry.io/otel/trace v1.15.0/go.mod h1:CUsmE2Ht1CRkvE8OsMESvraoZrrcgD1J2W8GV1ev0Y4=
go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0 h1:EbmAUG9hEAMXyfWEasIt2kmh/WmXUznUksChApTgBGc=
go.opentelemetry.io/contrib/instrumentation/runtime v0.42.0/go.mod h1:rD9feqRYP24P14t5kmhNMqsqm1jvKmpx2H2rKVw52V8=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0 h1:f6BwB2OACc3FCbYVznctQ9V6KK7Vq6CjmYXJ7DeSs4E=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.39.0/go.mod h1:UqL5mZ3qs6XYhDnZaW1Ps4upD+PX6LipH40AoeuIlwU=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0 h1:rm+Fizi7lTM2UefJ1TO347fSRcwmIsUAaZmYmIGBRAo=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.39.0/go.mod h1:sWFbI3jJ+6JdjOVepA5blpv/TJ20Hw+26561iMbWcwU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 h1:+XWJd3jf75RXJq29mxbuXhCXFDG3S3R4vBUeSI2P7tE=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0/go.mod h1:hqgzBPTf4yONMFgdZvL/bK42R/iinTyVQtiWihs3SZc=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI=
go.opentelemetry.io/otel/sdk/metric v0.39.0/go.mod h1:piDIRgjcK7u0HCL5pCA4e74qpK/jk3NiUoAHATVAmiI=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
@ -257,8 +257,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -301,8 +301,8 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -430,8 +430,8 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
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=

View File

@ -29,6 +29,16 @@ ch:
# Maximum query execution time.
max_execution_time: 30s
##
## PostgreSQL db that is used to store metadata such us metric names, dashboards, alerts,
## and so on.
##
pg:
addr: postgres:5432
user: uptrace
password: uptrace
database: uptrace
##
## A list of pre-configured projects. Each project is fully isolated.
##
@ -95,82 +105,17 @@ metrics_from_spans:
where: span.is_event
##
## Alerting rules for monitoring metrics.
##
## See https://uptrace.dev/get/alerting.html for details.
##
alerting:
rules:
- name: Network errors
metrics:
- system.network.errors as $net_errors
query:
- $net_errors > 0 group by host.name
# for the last 5 minutes
for: 5m
annotations:
summary: '{{ $labels.host_name }} has high number of net errors: {{ $values.net_errors }}'
- name: Filesystem usage >= 90%
metrics:
- system.filesystem.usage as $fs_usage
query:
- group by host.name
- group by device
- where device !~ "loop"
- $fs_usage{state="used"} / $fs_usage >= 0.9
for: 5m
annotations:
summary: '{{ $labels.host_name }} has high FS usage: {{ $values.fs_usage }}'
- name: Uptrace is dropping spans
metrics:
- uptrace.projects.spans as $spans
query:
- $spans{type=dropped} > 0
for: 1m
annotations:
summary: 'Uptrace has dropped {{ $values.spans }} spans'
- name: Always firing (for fun and testing)
metrics:
- process.runtime.go.goroutines as $goroutines
query:
- $goroutines >= 0 group by host.name
for: 1m
annotations:
summary: '{{ $labels.host_name }} has high number of goroutines: {{ $values.goroutines }}'
# Create alerts from error logs and span events.
create_alerts_from_spans:
enabled: true
labels:
alert_kind: error
##
## AlertManager client configuration.
## See https://uptrace.dev/get/alerting.html for details.
##
## Note that this is NOT an AlertManager config and you need to configure AlertManager separately.
## See https://prometheus.io/docs/alerting/latest/configuration/ for details.
##
alertmanager_client:
# AlertManager API endpoints that Uptrace uses to manage alerts.
urls:
- 'http://alertmanager:9093/api/v2/alerts'
##
## To require authentication, uncomment the following section.
## To require authentication, uncomment one of the following sections.
##
auth:
# users:
# - username: uptrace
# password: uptrace
# - username: admin
# password: admin
users:
- name: Anonymous
email: uptrace@localhost
password: uptrace
notify_by_email: true
# # Cloudflare user provider: uses Cloudflare Zero Trust Access (Identity)
# # See https://developers.cloudflare.com/cloudflare-one/identity/ for more info.
# Cloudflare Zero Trust Access (Identity)
# See https://developers.cloudflare.com/cloudflare-one/identity/ for more info.
# cloudflare:
# # The base URL of the Cloudflare Zero Trust team.
# - team_url: https://myteam.cloudflareaccess.com
@ -178,8 +123,8 @@ auth:
# # You can retrieve this from the Cloudflare Zero Trust 'Access' Dashboard.
# audience: bea6df23b944e4a0cd178609ba1bb64dc98dfe1f66ae7b918e563f6cf28b37e0
# # OpenID Connect (Single Sign-On)
# oidc:
# OpenID Connect (Single Sign-On)
oidc:
# # The ID is used in API endpoints, for example, in redirect URL
# # `http://<uptrace-host>/api/v1/sso/<oidc-id>/callback`.
# - id: keycloak
@ -196,9 +141,6 @@ auth:
# # Defaults to 'profile'. 'openid' is requested by default and need not be specified.
# scopes:
# - profile
# # The OIDC UserInfo claim to use as the user's username.
# # Defaults to 'preferred_username'.
# claim: preferred_username
##
## Various options to tweak ClickHouse schema.
@ -248,6 +190,8 @@ listen:
site:
# Overrides public URL for Vue-powered UI in case you put Uptrace behind a proxy.
#addr: 'https://uptrace.mydomain.com'
# The base path for the Vue-powered UI in case you serve Uptrace UI behind a sub path.
path: '/'
##
## Spans processing options.
@ -277,19 +221,6 @@ metrics:
# The number of measures to insert in a single query.
#batch_size: 10000
##
## SQLite/PostgreSQL db that is used to store metadata such us metric names, dashboards, alerts,
## and so on.
##
db:
# Either sqlite or postgres.
driver: sqlite
# Database connection string.
#
# Uptrace automatically creates SQLite database file in the current working directory.
# Make sure the directory is writable by Uptrace process.
dsn: 'file:uptrace.sqlite3?_pragma=foreign_keys(1)&_pragma=busy_timeout(1000)'
##
## uptrace-go client configuration.
## Uptrace sends internal telemetry here. Defaults to listen.grpc.addr.
@ -301,6 +232,18 @@ uptrace_go:
# key_file: config/tls/uptrace.key
# insecure_skip_verify: true
##
## SMTP settings to send emails.
## https://uptrace.dev/get/alerting.html
##
smtp_mailer:
enabled: true
host: mailhog
port: 1025
username: mailhog
password: mailhog
from: 'uptrace@localhost'
##
## Logging configuration.
##

View File

@ -4,7 +4,7 @@ go 1.18
replace github.com/redis/go-redis/v9 => ../..
require github.com/redis/go-redis/v9 v9.0.4
require github.com/redis/go-redis/v9 v9.0.5
require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect

View File

@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..
require (
github.com/davecgh/go-spew v1.1.1
github.com/redis/go-redis/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.5
)
require (

View File

@ -8,7 +8,7 @@ replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd
require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.4
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5
github.com/redis/go-redis/v9 v9.0.5
go.opencensus.io v0.24.0
)

View File

@ -7,5 +7,5 @@ replace github.com/redis/go-redis/v9 => ../..
require (
github.com/bsm/ginkgo/v2 v2.7.0
github.com/bsm/gomega v1.26.0
github.com/redis/go-redis/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.5
)

View File

@ -4,7 +4,6 @@ import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/global"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
"go.opentelemetry.io/otel/trace"
)
@ -56,7 +55,7 @@ func newConfig(opts ...baseOption) *config {
attrs: []attribute.KeyValue{},
tp: otel.GetTracerProvider(),
mp: global.MeterProvider(),
mp: otel.GetMeterProvider(),
dbStmtEnabled: true,
}

View File

@ -7,12 +7,12 @@ replace github.com/redis/go-redis/v9 => ../..
replace github.com/redis/go-redis/extra/rediscmd/v9 => ../rediscmd
require (
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.4
go.opentelemetry.io/otel v1.15.0
go.opentelemetry.io/otel/metric v0.38.0
go.opentelemetry.io/otel/sdk v1.15.0
go.opentelemetry.io/otel/trace v1.15.0
github.com/redis/go-redis/extra/rediscmd/v9 v9.0.5
github.com/redis/go-redis/v9 v9.0.5
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/metric v1.16.0
go.opentelemetry.io/otel/sdk v1.16.0
go.opentelemetry.io/otel/trace v1.16.0
)
require (
@ -20,5 +20,5 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/sys v0.8.0 // indirect
)

View File

@ -14,15 +14,15 @@ 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/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
go.opentelemetry.io/otel v1.15.0 h1:NIl24d4eiLJPM0vKn4HjLYM+UZf6gSfi9Z+NmCxkWbk=
go.opentelemetry.io/otel v1.15.0/go.mod h1:qfwLEbWhLPk5gyWrne4XnF0lC8wtywbuJbgfAE3zbek=
go.opentelemetry.io/otel/metric v0.38.0 h1:vv/Nv/44S3GzMMmeUhaesBKsAenE6xLkTVWL+zuv30w=
go.opentelemetry.io/otel/metric v0.38.0/go.mod h1:uAtxN5hl8aXh5irD8afBtSwQU5Zjg64WWSz6KheZxBg=
go.opentelemetry.io/otel/sdk v1.15.0 h1:jZTCkRRd08nxD6w7rIaZeDNGZGGQstH3SfLQ3ZsKICk=
go.opentelemetry.io/otel/sdk v1.15.0/go.mod h1:XDEMrYWzJ4YlC17i6Luih2lwDw2j6G0PkUfr1ZqE+rQ=
go.opentelemetry.io/otel/trace v1.15.0 h1:5Fwje4O2ooOxkfyqI/kJwxWotggDLix4BSAvpE1wlpo=
go.opentelemetry.io/otel/trace v1.15.0/go.mod h1:CUsmE2Ht1CRkvE8OsMESvraoZrrcgD1J2W8GV1ev0Y4=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s=
go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4=
go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo=
go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4=
go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE=
go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4=
go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs=
go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -10,7 +10,6 @@ import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/instrument"
)
// InstrumentMetrics starts reporting OpenTelemetry Metrics.
@ -89,7 +88,7 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
idleMax, err := conf.meter.Int64ObservableUpDownCounter(
"db.client.connections.idle.max",
instrument.WithDescription("The maximum number of idle open connections allowed"),
metric.WithDescription("The maximum number of idle open connections allowed"),
)
if err != nil {
return err
@ -97,7 +96,7 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
idleMin, err := conf.meter.Int64ObservableUpDownCounter(
"db.client.connections.idle.min",
instrument.WithDescription("The minimum number of idle open connections allowed"),
metric.WithDescription("The minimum number of idle open connections allowed"),
)
if err != nil {
return err
@ -105,7 +104,7 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
connsMax, err := conf.meter.Int64ObservableUpDownCounter(
"db.client.connections.max",
instrument.WithDescription("The maximum number of open connections allowed"),
metric.WithDescription("The maximum number of open connections allowed"),
)
if err != nil {
return err
@ -113,7 +112,7 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
usage, err := conf.meter.Int64ObservableUpDownCounter(
"db.client.connections.usage",
instrument.WithDescription("The number of connections that are currently in state described by the state attribute"),
metric.WithDescription("The number of connections that are currently in state described by the state attribute"),
)
if err != nil {
return err
@ -121,7 +120,7 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
timeouts, err := conf.meter.Int64ObservableUpDownCounter(
"db.client.connections.timeouts",
instrument.WithDescription("The number of connection timeouts that have occurred trying to obtain a connection from the pool"),
metric.WithDescription("The number of connection timeouts that have occurred trying to obtain a connection from the pool"),
)
if err != nil {
return err
@ -155,8 +154,8 @@ func reportPoolStats(rdb *redis.Client, conf *config) error {
func addMetricsHook(rdb *redis.Client, conf *config) error {
createTime, err := conf.meter.Float64Histogram(
"db.client.connections.create_time",
instrument.WithDescription("The time it took to create a new connection."),
instrument.WithUnit("ms"),
metric.WithDescription("The time it took to create a new connection."),
metric.WithUnit("ms"),
)
if err != nil {
return err
@ -164,8 +163,8 @@ func addMetricsHook(rdb *redis.Client, conf *config) error {
useTime, err := conf.meter.Float64Histogram(
"db.client.connections.use_time",
instrument.WithDescription("The time between borrowing a connection and returning it to the pool."),
instrument.WithUnit("ms"),
metric.WithDescription("The time between borrowing a connection and returning it to the pool."),
metric.WithUnit("ms"),
)
if err != nil {
return err
@ -180,8 +179,8 @@ func addMetricsHook(rdb *redis.Client, conf *config) error {
}
type metricsHook struct {
createTime instrument.Float64Histogram
useTime instrument.Float64Histogram
createTime metric.Float64Histogram
useTime metric.Float64Histogram
attrs []attribute.KeyValue
}

View File

@ -6,7 +6,7 @@ replace github.com/redis/go-redis/v9 => ../..
require (
github.com/prometheus/client_golang v1.14.0
github.com/redis/go-redis/v9 v9.0.4
github.com/redis/go-redis/v9 v9.0.5
)
require (

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/redis/go-redis/v9
go 1.18
require (
github.com/bsm/ginkgo/v2 v2.7.0
github.com/bsm/ginkgo/v2 v2.9.5
github.com/bsm/gomega v1.26.0
github.com/cespare/xxhash/v2 v2.2.0
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f

4
go.sum
View File

@ -1,5 +1,5 @@
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=

View File

@ -45,6 +45,9 @@ type Options struct {
// Hook that is called when new connection is established.
OnConnect func(ctx context.Context, cn *Conn) error
// Protocol 2 or 3. Use the version to negotiate RESP version with redis-server.
// Default is 3.
Protocol int
// Use the specified Username to authenticate the current connection
// with one of the connections defined in the ACL list when connecting
// to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
@ -437,6 +440,7 @@ func setupConnParams(u *url.URL, o *Options) (*Options, error) {
o.DB = db
}
o.Protocol = q.int("protocol")
o.ClientName = q.string("client_name")
o.MaxRetries = q.int("max_retries")
o.MinRetryBackoff = q.duration("min_retry_backoff")

View File

@ -62,6 +62,9 @@ func TestParseURL(t *testing.T) {
}, {
url: "redis://localhost:123/?db=2&client_name=hi", // client name
o: &Options{Addr: "localhost:123", DB: 2, ClientName: "hi"},
}, {
url: "redis://localhost:123/?db=2&protocol=2", // RESP Protocol
o: &Options{Addr: "localhost:123", DB: 2, Protocol: 2},
}, {
url: "unix:///tmp/redis.sock",
o: &Options{Addr: "/tmp/redis.sock"},

View File

@ -1,6 +1,6 @@
{
"name": "redis",
"version": "9.0.4",
"version": "9.0.5",
"main": "index.js",
"repository": "git@github.com:redis/go-redis.git",
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",

View File

@ -279,10 +279,15 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
conn := newConn(c.opt, connPool)
var auth bool
protocol := c.opt.Protocol
// By default, use RESP3 in current version.
if protocol < 2 {
protocol = 3
}
// for redis-server versions that do not support the HELLO command,
// RESP2 will continue to be used.
if err := conn.Hello(ctx, 3, username, password, "").Err(); err == nil {
if err := conn.Hello(ctx, protocol, username, password, "").Err(); err == nil {
auth = true
} else if !isRedisError(err) {
// When the server responds with the RESP protocol and the result is not a normal

View File

@ -185,6 +185,33 @@ var _ = Describe("Client", func() {
Expect(val).Should(ContainSubstring("name=hi"))
})
It("should client PROTO 2", func() {
opt := redisOptions()
opt.Protocol = 2
db := redis.NewClient(opt)
defer func() {
Expect(db.Close()).NotTo(HaveOccurred())
}()
val, err := db.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainElements("proto", int64(2)))
})
It("should client PROTO 3", func() {
opt := redisOptions()
db := redis.NewClient(opt)
defer func() {
Expect(db.Close()).NotTo(HaveOccurred())
}()
val, err := db.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(HaveKeyWithValue("proto", int64(3)))
})
It("processes custom commands", func() {
cmd := redis.NewCmd(ctx, "PING")
_ = client.Process(ctx, cmd)

View File

@ -12,7 +12,7 @@ import (
"time"
"github.com/cespare/xxhash/v2"
rendezvous "github.com/dgryski/go-rendezvous" //nolint
"github.com/dgryski/go-rendezvous" //nolint
"github.com/redis/go-redis/v9/internal"
"github.com/redis/go-redis/v9/internal/hashtag"
@ -70,6 +70,7 @@ type RingOptions struct {
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
OnConnect func(ctx context.Context, cn *Conn) error
Protocol int
Username string
Password string
DB int
@ -136,6 +137,7 @@ func (opt *RingOptions) clientOptions() *Options {
Dialer: opt.Dialer,
OnConnect: opt.OnConnect,
Protocol: opt.Protocol,
Username: opt.Username,
Password: opt.Password,
DB: opt.DB,

View File

@ -15,6 +15,37 @@ import (
"github.com/redis/go-redis/v9"
)
var _ = Describe("Redis Ring PROTO 2", func() {
const heartbeat = 100 * time.Millisecond
var ring *redis.Ring
BeforeEach(func() {
opt := redisRingOptions()
opt.Protocol = 2
opt.HeartbeatFrequency = heartbeat
ring = redis.NewRing(opt)
err := ring.ForEachShard(ctx, func(ctx context.Context, cl *redis.Client) error {
return cl.FlushDB(ctx).Err()
})
Expect(err).NotTo(HaveOccurred())
})
AfterEach(func() {
Expect(ring.Close()).NotTo(HaveOccurred())
})
It("should ring PROTO 2", func() {
_ = ring.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := c.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainElements("proto", int64(2)))
return nil
})
})
})
var _ = Describe("Redis Ring", func() {
const heartbeat = 100 * time.Millisecond
@ -65,6 +96,15 @@ var _ = Describe("Redis Ring", func() {
})
})
It("should ring PROTO 3", func() {
_ = ring.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := c.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(HaveKeyWithValue("proto", int64(3)))
return nil
})
})
It("distributes keys", func() {
setRingKeys()

View File

@ -54,6 +54,7 @@ type FailoverOptions struct {
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
OnConnect func(ctx context.Context, cn *Conn) error
Protocol int
Username string
Password string
DB int
@ -88,6 +89,7 @@ func (opt *FailoverOptions) clientOptions() *Options {
OnConnect: opt.OnConnect,
DB: opt.DB,
Protocol: opt.Protocol,
Username: opt.Username,
Password: opt.Password,
@ -151,6 +153,7 @@ func (opt *FailoverOptions) clusterOptions() *ClusterOptions {
Dialer: opt.Dialer,
OnConnect: opt.OnConnect,
Protocol: opt.Protocol,
Username: opt.Username,
Password: opt.Password,

View File

@ -10,6 +10,30 @@ import (
"github.com/redis/go-redis/v9"
)
var _ = Describe("Sentinel PROTO 2", func() {
var client *redis.Client
BeforeEach(func() {
client = redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: sentinelName,
SentinelAddrs: sentinelAddrs,
MaxRetries: -1,
Protocol: 2,
})
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
})
AfterEach(func() {
_ = client.Close()
})
It("should sentinel client PROTO 2", func() {
val, err := client.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainElements("proto", int64(2)))
})
})
var _ = Describe("Sentinel", func() {
var client *redis.Client
var master *redis.Client
@ -134,6 +158,40 @@ var _ = Describe("Sentinel", func() {
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainSubstring("name=sentinel_hi"))
})
It("should sentinel client PROTO 3", func() {
val, err := client.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(HaveKeyWithValue("proto", int64(3)))
})
})
var _ = Describe("NewFailoverClusterClient PROTO 2", func() {
var client *redis.ClusterClient
BeforeEach(func() {
client = redis.NewFailoverClusterClient(&redis.FailoverOptions{
MasterName: sentinelName,
SentinelAddrs: sentinelAddrs,
Protocol: 2,
RouteRandomly: true,
})
Expect(client.FlushDB(ctx).Err()).NotTo(HaveOccurred())
})
AfterEach(func() {
_ = client.Close()
})
It("should sentinel cluster PROTO 2", func() {
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := client.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(ContainElements("proto", int64(2)))
return nil
})
})
})
var _ = Describe("NewFailoverClusterClient", func() {
@ -237,6 +295,15 @@ var _ = Describe("NewFailoverClusterClient", func() {
return nil
})
})
It("should sentinel cluster PROTO 3", func() {
_ = client.ForEachShard(ctx, func(ctx context.Context, c *redis.Client) error {
val, err := client.Do(ctx, "HELLO").Result()
Expect(err).NotTo(HaveOccurred())
Expect(val).Should(HaveKeyWithValue("proto", int64(3)))
return nil
})
})
})
var _ = Describe("SentinelAclAuth", func() {

View File

@ -26,6 +26,7 @@ type UniversalOptions struct {
Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
OnConnect func(ctx context.Context, cn *Conn) error
Protocol int
Username string
Password string
SentinelUsername string
@ -77,6 +78,7 @@ func (o *UniversalOptions) Cluster() *ClusterOptions {
Dialer: o.Dialer,
OnConnect: o.OnConnect,
Protocol: o.Protocol,
Username: o.Username,
Password: o.Password,
@ -122,6 +124,7 @@ func (o *UniversalOptions) Failover() *FailoverOptions {
OnConnect: o.OnConnect,
DB: o.DB,
Protocol: o.Protocol,
Username: o.Username,
Password: o.Password,
SentinelUsername: o.SentinelUsername,
@ -162,6 +165,7 @@ func (o *UniversalOptions) Simple() *Options {
OnConnect: o.OnConnect,
DB: o.DB,
Protocol: o.Protocol,
Username: o.Username,
Password: o.Password,

View File

@ -2,5 +2,5 @@ package redis
// Version is the current release version.
func Version() string {
return "9.0.4"
return "9.0.5"
}