Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenTelemetry migration #685

Merged
merged 96 commits into from
Jun 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
cd0d0f6
OpenTelemetry migration
mantzas Apr 5, 2024
80aa9da
Opentelemetry migration
mantzas Apr 5, 2024
678b2aa
Opentelemetry migration
mantzas Apr 5, 2024
adc283b
Opentelemetry migration
mantzas Apr 6, 2024
2a085ac
Opentelemetry migration
mantzas Apr 6, 2024
3798f67
Opentelemetry migration
mantzas Apr 6, 2024
64a5b27
Opentelemetry migration
mantzas Apr 6, 2024
0f5fc8b
Opentelemetry migration
mantzas Apr 7, 2024
855b92b
Improve struct layout
mantzas Apr 27, 2024
341020d
Update observability package to include methods for setting up and sh…
mantzas Apr 28, 2024
b299425
Update OpenTelemetry semantic conventions to v1.25.0
mantzas Apr 28, 2024
eae31fa
Update OpenTelemetry configuration and observability package
mantzas Apr 30, 2024
f75cb2d
Update OpenTelemetry configuration and observability package
mantzas May 4, 2024
c9c6c35
Update OpenTelemetry configuration to include detailed debug verbosity
mantzas May 4, 2024
9c05ef5
chore: Update OpenTelemetry configuration and observability package
mantzas May 4, 2024
46d9e5c
chore: Update OpenTelemetry configuration and observability package
mantzas May 4, 2024
c566a65
Use default grpc exporter
mantzas May 4, 2024
139f598
chore: Remove unused container_name property in docker-compose.yml
mantzas May 4, 2024
2591a37
chore: Add example-service and example-client targets to Makefile
mantzas May 4, 2024
32c556a
chore: Update logging package to use structured logging with slog
mantzas May 4, 2024
72255ed
chore: Update logging package to use structured logging with slog
mantzas May 4, 2024
c7875c6
chore: Update docker-compose configuration for tempo and otelcol
mantzas May 4, 2024
e2c177a
chore: Update OpenTelemetry configuration and observability package
mantzas May 4, 2024
4550b6f
chore: Update OpenTelemetry configuration and observability package
mantzas May 4, 2024
5e5f5cc
chore: Update AWS SQS message sending in client/main.go
mantzas May 4, 2024
13b3fd5
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 4, 2024
7cc0722
Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 4, 2024
6d280c9
Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 4, 2024
8b564b3
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 4, 2024
f9c29d0
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 4, 2024
1b9a178
chore: Update SQS and SNS client packages with OpenTelemetry instrume…
mantzas May 4, 2024
89ca1e2
chore: Remove jaeger tracing after everything has been set up
mantzas May 9, 2024
8169302
chore: Update SQS and SNS client packages with OpenTelemetry instrume…
mantzas May 12, 2024
27e8334
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 12, 2024
e56365e
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 12, 2024
ad24c00
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 12, 2024
84ef31f
chore: Update elasticsearch client with tracing capabilities
mantzas May 28, 2024
e727024
chore: Update dependencies to latest versions
mantzas May 28, 2024
79b2b34
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 29, 2024
91de5ec
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 29, 2024
2816cf9
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas May 29, 2024
bd82a57
chore: Update SQL package imports and remove unused code
mantzas May 29, 2024
1a9d37b
refactor: Update Redis client to use go-redis/v9 package
mantzas May 29, 2024
233f761
chore: Fix metric collection in integration_test.go
mantzas May 30, 2024
919e86d
chore: Introduce tracing capabilities in integration_test.go
mantzas May 30, 2024
deb19fd
chore: Update package imports for integration tests
mantzas May 30, 2024
b6f236c
chore: Update package imports for integration tests
mantzas Jun 1, 2024
00aaf58
chore: Update package imports for integration tests
mantzas Jun 1, 2024
2ae123e
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas Jun 1, 2024
c47e25a
chore: Update AMQP package import to use rabbitmq/amqp091-go
mantzas Jun 1, 2024
2483aa5
chore: Update package imports for integration tests
mantzas Jun 1, 2024
1b06295
chore: Update package imports for integration tests
mantzas Jun 2, 2024
a74dcbe
chore: Update package imports for integration tests
mantzas Jun 4, 2024
201cb1a
chore: Refactor observePublish function signature
mantzas Jun 4, 2024
d949d84
chore: Increase timeout for integration tests to 300s
mantzas Jun 4, 2024
1dfdf8a
chore: Update OpenTelemetry setup in example client code
mantzas Jun 5, 2024
05b0963
Added example client span
mantzas Jun 5, 2024
6ffd461
chore: Update CI workflow to enable insecure OTLP exporter for e2e tests
mantzas Jun 5, 2024
3556b4c
chore: Update package imports for integration tests
mantzas Jun 5, 2024
453f255
chore: Update package imports for integration tests
mantzas Jun 5, 2024
108252b
chore: Update package imports for integration tests
mantzas Jun 6, 2024
c11319e
chore: Update package imports for integration tests
mantzas Jun 7, 2024
1568271
chore: Update OpenTelemetry setup in example client code
mantzas Jun 7, 2024
08083d1
chore: Update cache package imports for integration tests
mantzas Jun 8, 2024
b5b19a6
Minor changes
mantzas Jun 8, 2024
78e4f3e
chore: Update package imports for integration tests
mantzas Jun 9, 2024
deba51e
chore: Update OpenTelemetry setup and add manual metric reader for te…
mantzas Jun 9, 2024
08277cb
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 9, 2024
851e081
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 9, 2024
69d1019
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 9, 2024
046c456
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 9, 2024
ea315b8
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 10, 2024
0693324
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 10, 2024
8247fe0
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 10, 2024
b04db03
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 10, 2024
c8b7410
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 10, 2024
7d66e0e
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 12, 2024
cb8ec49
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 12, 2024
34bcfed
chore: Refactor AMQP metric observation to include message state attr…
mantzas Jun 12, 2024
258009c
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 12, 2024
4398bc0
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 13, 2024
4f890ca
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 22, 2024
5652a0b
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 13, 2024
1c1ff7c
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 23, 2024
316a911
chore: Update go.mod dependencies
mantzas Jun 23, 2024
0f713da
chore: Remove unused files and directories
mantzas Jun 23, 2024
bab177b
chore: Remove unused code and TODOs
mantzas Jun 23, 2024
904833b
chore: Update go.mod dependencies and vendor/modules.txt
mantzas Jun 23, 2024
9aea482
chore: Remove TODO and unused code in middleware_test.go file
mantzas Jun 23, 2024
c2642a0
chore: Remove unused code and update dependencies
mantzas Jun 24, 2024
323e5b7
chore: Refactor OpenTelemetry setup and metric collection in integrat…
mantzas Jun 24, 2024
c47308c
Refactor metric initialization in various packages
mantzas Jun 24, 2024
45dce2e
Refactor retry package and remove TODO for introducing metrics
mantzas Jun 24, 2024
0cfa91a
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 24, 2024
aaf3891
Refactor OpenTelemetry setup and metric collection in integration tests
mantzas Jun 24, 2024
7ec78bd
Refactor assertMetrics function in cache_test.go
mantzas Jun 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,23 @@ jobs:
run: |
sleep 30
make ci

- name: Codecov
uses: codecov/codecov-action@v4
with:
fail_ci_if_error: true # optional (default = false)
files: ./coverage.txt
name: codecov-umbrella # optional
token: ${{ secrets.CODECOV_TOKEN }} # required

- name: e2e
run: |
go build -o service ./service/
nohup ./service/service &
go run client/main.go
working-directory: ./examples
env:
OTEL_EXPORTER_OTLP_INSECURE : true

- name: Stop dependencies
run: make deps-stop
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ coverage.txt
/cmd/patron/patron

# tmp folder used in examples for storing logging, binaries and pids
examples/tmp/
examples/tmp/
docker-compose/tempo-data/
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,16 @@ linters:
disable-all: true
enable:
- gofmt
- gosimple
- gosec
- unparam
- goconst
- prealloc
- stylecheck
- unconvert
- unused
- staticcheck
- ineffassign
- gosec
- tparallel
- whitespace
Expand Down
33 changes: 13 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
DOCKER = docker
LINT_IMAGE = golangci/golangci-lint:v1.59.0

default: test

test: fmtcheck
go test ./... -cover -race -timeout 60s

testint: fmtcheck deps-start
go test ./... -race -cover -tags=integration -timeout 120s -count=1
testint: fmtcheck
go test ./... -race -cover -tags=integration -timeout 300s -count=1

cover: fmtcheck
go test ./... -coverpkg=./... -coverprofile=coverage.txt -tags=integration -covermode=atomic && \
go tool cover -func=coverage.txt && \
rm coverage.txt

ci:
go test ./... -race -cover -mod=vendor -coverprofile=coverage.txt -covermode=atomic -tags=integration && \
mv coverage.txt coverage.txt.tmp && \
cat coverage.txt.tmp | grep -v "/cmd/patron/" > coverage.txt
ci: fmtcheck
go test `go list ./... | grep -v -e 'examples' -e 'encoding/protobuf/test'` -race -cover -coverprofile=coverage.txt -covermode=atomic -tags=integration

fmt:
go fmt ./...
Expand All @@ -25,19 +18,19 @@ fmtcheck:
@sh -c "'$(CURDIR)/script/gofmtcheck.sh'"

lint: fmtcheck
$(DOCKER) run --env=GOFLAGS=-mod=vendor --rm -v $(CURDIR):/app -w /app golangci/golangci-lint:v1.57.2 golangci-lint -v run
docker run --env=GOFLAGS=-mod=vendor --rm -v $(CURDIR):/app -w /app $(LINT_IMAGE) golangci-lint -v run

deeplint: fmtcheck
$(DOCKER) run --env=GOFLAGS=-mod=vendor --rm -v $(CURDIR):/app -w /app golangci/golangci-lint:v1.57.2 golangci-lint run --exclude-use-default=false --enable-all -D dupl --build-tags integration
docker run --env=GOFLAGS=-mod=vendor --rm -v $(CURDIR):/app -w /app $(LINT_IMAGE) golangci-lint run --exclude-use-default=false --enable-all -D dupl --build-tags integration

modsync: fmtcheck
go mod tidy && go mod vendor
example-service:
OTEL_EXPORTER_OTLP_INSECURE="true" go run examples/service/*.go

examples:
$(MAKE) -C examples
example-client:
OTEL_EXPORTER_OTLP_INSECURE="true" go run examples/client/main.go

deps-start:
docker-compose up -d && sleep 10
docker-compose up -d

deps-stop:
docker-compose down
Expand All @@ -47,4 +40,4 @@ deps-stop:
# under parallel conditions.
.NOTPARALLEL:

.PHONY: default test testint cover coverci fmt fmtcheck lint deeplint ci modsync deps-start deps-stop
.PHONY: default test testint cover coverci fmt fmtcheck lint deeplint ci modsync deps-start deps-stop example-service example-client
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Patron is a framework for creating microservices, originally created by Sotiris

`Patron` is french for `template` or `pattern`, but it means also `boss` which we found out later (no pun intended).

The entry point of the framework is the `Service`. The `Service` uses `Components` to handle the processing of sync and async requests. The `Service` starts by default an `HTTP Component` which hosts the `/debug`, `/alive`, `/ready` and `/metrics` endpoints. Any other endpoints will be added to the default `HTTP Component` as `Routes`. Alongside `Routes` one can specify middleware functions to be applied ordered to all routes as `MiddlewareFunc`. The service sets up by default logging with `slog`, tracing and metrics with [Jaeger](https://www.jaegertracing.io/) and [prometheus](https://prometheus.io/).
The entry point of the framework is the `Service`. The `Service` uses `Components` to handle the processing of sync and async requests. The `Service` starts by default an `HTTP Component` which hosts the `/debug`, `/alive`, `/ready` and `/metrics` endpoints. Any other endpoints will be added to the default `HTTP Component` as `Routes`. Alongside `Routes` one can specify middleware functions to be applied ordered to all routes as `MiddlewareFunc`. The service sets up by default logging with `slog`, tracing and metrics with [OpenTelemetry](https://opentelemetry.io).

`Patron` provides abstractions for the following functionality of the framework:

Expand Down
31 changes: 23 additions & 8 deletions cache/lru/lru.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,44 @@ import (
"context"

"github.com/beatlabs/patron/cache"
"github.com/hashicorp/golang-lru"
lru "github.com/hashicorp/golang-lru"
"go.opentelemetry.io/otel/attribute"
)

var _ cache.Cache = &Cache{}
var (
_ cache.Cache = &Cache{}
lruAttribute = attribute.String("cache.type", "lru")
)

// Cache encapsulates a thread-safe fixed size LRU cache.
type Cache struct {
cache *lru.Cache
cache *lru.Cache
useCaseAttribute attribute.KeyValue
}

// New returns a new LRU cache that can hold 'size' number of keys at a time.
func New(size int) (*Cache, error) {
cache, err := lru.New(size)
func New(size int, useCase string) (*Cache, error) {
cache.SetupMetricsOnce()
chc, err := lru.New(size)
if err != nil {
return nil, err
}
return &Cache{cache: cache}, nil

return &Cache{
cache: chc,
useCaseAttribute: cache.UseCaseAttribute(useCase),
}, nil
}

// Get executes a lookup and returns whether a key exists in the cache along with its value.
func (c *Cache) Get(_ context.Context, key string) (interface{}, bool, error) {
func (c *Cache) Get(ctx context.Context, key string) (interface{}, bool, error) {
value, ok := c.cache.Get(key)
return value, ok, nil
if !ok {
cache.ObserveMiss(ctx, lruAttribute, c.useCaseAttribute)
return nil, false, nil
}
cache.ObserveHit(ctx, lruAttribute, c.useCaseAttribute)
return value, true, nil
}

// Purge evicts all keys present in the cache.
Expand Down
6 changes: 3 additions & 3 deletions cache/lru/lru_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import (
func TestNew(t *testing.T) {
tests := []struct {
name string
err string
size int
wantErr bool
err string
}{
{name: "negative size", size: -1, wantErr: true, err: "must provide a positive size"},
{name: "zero size", size: 0, wantErr: true, err: "must provide a positive size"},
Expand All @@ -21,7 +21,7 @@ func TestNew(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c, err := New(tt.size)
c, err := New(tt.size, "test")
if tt.wantErr {
assert.Nil(t, c)
assert.EqualError(t, err, tt.err)
Expand All @@ -34,7 +34,7 @@ func TestNew(t *testing.T) {
}

func TestCacheOperations(t *testing.T) {
c, err := New(10)
c, err := New(10, "test")
assert.NotNil(t, c)
assert.NoError(t, err)

Expand Down
43 changes: 43 additions & 0 deletions cache/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package cache

import (
"context"
"sync"

patronmetric "github.com/beatlabs/patron/observability/metric"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/metric"
)

const packageName = "cache"

var (
cashHitAttribute = attribute.String("cache.status", "hit")
cashMissAttribute = attribute.String("cache.status", "miss")
cacheCounter metric.Int64Counter
cacheOnce sync.Once
)

// SetupMetricsOnce initializes the cache counter.
func SetupMetricsOnce() {
cacheOnce.Do(func() {
cacheCounter = patronmetric.Int64Counter(packageName, "cache.counter", "Number of cache calls.", "1")
})
}

// UseCaseAttribute returns an attribute.KeyValue with the use case.
func UseCaseAttribute(useCase string) attribute.KeyValue {
return attribute.String("cache.use_case", useCase)
}

// ObserveHit increments the cache hit counter.
func ObserveHit(ctx context.Context, attrs ...attribute.KeyValue) {
attrs = append(attrs, cashHitAttribute)
cacheCounter.Add(ctx, 1, metric.WithAttributes(attrs...))
}

// ObserveMiss increments the cache miss counter.
func ObserveMiss(ctx context.Context, attrs ...attribute.KeyValue) {
attrs = append(attrs, cashMissAttribute)
cacheCounter.Add(ctx, 1, metric.WithAttributes(attrs...))
}
48 changes: 48 additions & 0 deletions cache/metric_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package cache

import (
"context"
"log"
"testing"

"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
metricsdk "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/metric/metricdata"
)

func TestUseCaseAttribute(t *testing.T) {
assert.Equal(t, attribute.String("cache.use_case", "test"), UseCaseAttribute("test"))
}

func TestSetupAndUseMetrics(t *testing.T) {
SetupMetricsOnce()

read := metricsdk.NewManualReader()
provider := metricsdk.NewMeterProvider(metricsdk.WithReader(read))
defer func() {
err := provider.Shutdown(context.Background())
if err != nil {
log.Fatal(err)
}
}()

otel.SetMeterProvider(provider)

assert.NotNil(t, cacheCounter)

ObserveHit(context.Background(), attribute.String("test", "test"))

collectedMetrics := &metricdata.ResourceMetrics{}
assert.NoError(t, read.Collect(context.Background(), collectedMetrics))

assert.Equal(t, 1, len(collectedMetrics.ScopeMetrics))

ObserveMiss(context.Background(), attribute.String("test", "test"))

collectedMetrics = &metricdata.ResourceMetrics{}
assert.NoError(t, read.Collect(context.Background(), collectedMetrics))

assert.Equal(t, 1, len(collectedMetrics.ScopeMetrics))
}
8 changes: 2 additions & 6 deletions cache/redis/integration_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//go:build integration
// +build integration

package redis

Expand All @@ -8,6 +7,7 @@ import (
"testing"
"time"

"github.com/redis/go-redis/v9"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand All @@ -17,11 +17,7 @@ const (
)

func TestCache(t *testing.T) {
cache, err := New(Options{
Addr: dsn,
Password: "", // no password set
DB: 0, // use default DB
})
cache, err := New(&redis.Options{Addr: dsn}, "test")
require.NoError(t, err)

key1 := "key1"
Expand Down
30 changes: 21 additions & 9 deletions cache/redis/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,46 @@
"time"

"github.com/beatlabs/patron/cache"
"github.com/beatlabs/patron/client/redis"
patronredis "github.com/beatlabs/patron/client/redis"
"github.com/redis/go-redis/v9"
"go.opentelemetry.io/otel/attribute"
)

var _ cache.TTLCache = &Cache{}
var (
_ cache.TTLCache = &Cache{}
redisAttribute = attribute.String("cache.type", "redis")
)

// Cache encapsulates a Redis-based caching mechanism.
type Cache struct {
rdb redis.Client
rdb *redis.Client
useCaseAttribute attribute.KeyValue
}

// Options exposes the struct from go-redis package.
type Options redis.Options

// New creates a cache returns a new Redis client that will be used as the cache store.
func New(opt Options) (*Cache, error) {
redisDB := redis.New(redis.Options(opt))
return &Cache{rdb: redisDB}, nil
func New(opt *redis.Options, useCase string) (*Cache, error) {
cache.SetupMetricsOnce()
redisDB, err := patronredis.New(opt)
if err != nil {
return nil, err

Check warning on line 31 in cache/redis/redis.go

View check run for this annotation

Codecov / codecov/patch

cache/redis/redis.go#L31

Added line #L31 was not covered by tests
}
return &Cache{
rdb: redisDB,
useCaseAttribute: cache.UseCaseAttribute(useCase),
}, nil
}

// Get executes a lookup and returns whether a key exists in the cache along with its value.
func (c *Cache) Get(ctx context.Context, key string) (interface{}, bool, error) {
res, err := c.rdb.Do(ctx, "get", key).Result()
if err != nil {
if errors.Is(err, redis.Nil) { // cache miss
cache.ObserveMiss(ctx, redisAttribute, c.useCaseAttribute)
return nil, false, nil
}
return nil, false, err
}
cache.ObserveHit(ctx, redisAttribute, c.useCaseAttribute)
return res, true, nil
}

Expand Down
Loading