Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 2 additions & 21 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,6 @@ jobs:
go-version: stable
- uses: actions/checkout@v4
- name: golangci-lint
uses: golangci/golangci-lint-action@v6.5.0
uses: golangci/golangci-lint-action@v9.2.0
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.64.5

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true then the action will use pre-installed Go.
# skip-go-installation: true

# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true
version: v2.11.3
5 changes: 3 additions & 2 deletions .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,9 @@ jobs:
curl -sLO https://github.com/vearutop/gocovdiff/releases/download/v1.4.2/linux_amd64.tar.gz && tar xf linux_amd64.tar.gz && rm linux_amd64.tar.gz
gocovdiff_hash=$(git hash-object ./gocovdiff)
[ "$gocovdiff_hash" == "c37862c73a677e5a9c069470287823ab5bbf0244" ] || (echo "::error::unexpected hash for gocovdiff, possible tampering: $gocovdiff_hash" && exit 1)
git fetch origin master ${{ github.event.pull_request.base.sha }}
REP=$(./gocovdiff -mod github.com/$GITHUB_REPOSITORY -cov unit.coverprofile -gha-annotations gha-unit.txt -delta-cov-file delta-cov-unit.txt -target-delta-cov ${TARGET_DELTA_COV})
# Fetch PR diff from GitHub API.
curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -H "Accept: application/vnd.github.v3.diff" https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }} > pull_request.diff
REP=$(./gocovdiff -diff pull_request.diff -mod github.com/$GITHUB_REPOSITORY -cov unit.coverprofile -gha-annotations gha-unit.txt -delta-cov-file delta-cov-unit.txt -target-delta-cov ${TARGET_DELTA_COV})
echo "${REP}"
cat gha-unit.txt
DIFF=$(test -e unit-base.txt && ./gocovdiff -mod github.com/$GITHUB_REPOSITORY -func-cov unit.txt -func-base-cov unit-base.txt || echo "Missing base coverage file")
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/.vscode
/bench-*.txt
/vendor
/_refs
128 changes: 72 additions & 56 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -1,67 +1,83 @@
# See https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml
# See https://golangci-lint.run/docs/linters/configuration/
version: "2"
run:
tests: true

linters-settings:
errcheck:
check-type-assertions: true
check-blank: true
gocyclo:
min-complexity: 20
dupl:
threshold: 100
misspell:
locale: US
unparam:
check-exported: true
funlen:
lines: 70

linters:
enable-all: true
default: all
disable:
- intrange
- embeddedstructfieldcheck
- nilnil
- noinlineerr
- wsl_v5
- funcorder
- copyloopvar
- lll
- gochecknoglobals
- wrapcheck
- paralleltest
- depguard
- dupword
- errname
- exhaustruct
- forbidigo
- forcetypeassert
- varnamelen
- tagliatelle
- errname
- gochecknoglobals
- intrange
- ireturn
- exhaustruct
- lll
- mnd
- nonamedreturns
- testableexamples
- dupword
- depguard
- paralleltest
- recvcheck
- tagalign
- mnd
- tagliatelle
- testableexamples
- testifylint
- recvcheck

issues:
exclude-use-default: false
exclude-rules:
- linters:
- gosec
text: 'G115: integer overflow conversion'
- linters:
- mnd
- goconst
- noctx
- funlen
- dupl
- unused
- unparam
path: "_test.go"
- linters:
- errcheck # Error checking omitted for brevity.
- gosec
path: "example_"
- linters:
- revive
text: "unused-parameter: parameter"

- varnamelen
- wrapcheck
settings:
dupl:
threshold: 100
errcheck:
check-type-assertions: true
check-blank: true
gocyclo:
min-complexity: 20
misspell:
locale: US
unparam:
check-exported: true
cyclop:
max-complexity: 15
exclusions:
generated: lax
rules:
- linters:
- gosec
- dupl
- funlen
- goconst
- mnd
- noctx
- unparam
- unused
path: _test.go
- linters:
- errcheck
- gosec
path: example_
- linters:
- revive
text: 'unused-parameter: parameter'
paths:
- third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#GOLANGCI_LINT_VERSION := "v1.64.5" # Optional configuration to pinpoint golangci-lint version.
#GOLANGCI_LINT_VERSION := "v2.11.3" # Optional configuration to pinpoint golangci-lint version.

# The head of Makefile determines location of dev-go to include standard targets.
GO ?= go
Expand Down
49 changes: 48 additions & 1 deletion cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
}

if cfg.Backend == nil {
cfg.Backend = cache.NewShardedMapOf[V](func(cfg *cache.Config) {
cfg.Backend = cache.NewShardedMapOf[V](func(cfg *cache.ConfigOf[V]) {

Check notice on line 39 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

5 statement(s) on lines 38:44 are not covered by tests.
cfg.Name = name
cfg.Logger = l.CtxdLogger()
cfg.Stats = l.StatsTracker()
Expand Down Expand Up @@ -66,3 +66,50 @@

return fc
}

// MakeCacheBy creates an instance of failover cache and adds it to cache transfer.
func MakeCacheBy[K comparable, V any](l interface {
StatsTracker() stats.Tracker
CtxdLogger() ctxd.Logger
}, name string, ttl time.Duration, options ...func(cfg *cache.FailoverConfigBy[K, V]),
) *cache.FailoverBy[K, V] {
cfg := cache.FailoverConfigBy[K, V]{}
cfg.Name = name
cfg.Stats = l.StatsTracker()
cfg.Logger = l.CtxdLogger()

for _, option := range options {
option(&cfg)
}

Check notice on line 83 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

6 statement(s) are not covered by tests.

if cfg.Backend == nil {
cfg.Backend = cache.NewShardedMapBy[K, V](func(cfg *cache.ConfigBy[K, V]) {
cfg.Name = name
cfg.Logger = l.CtxdLogger()
cfg.Stats = l.StatsTracker()
cfg.TimeToLive = ttl
})

Check notice on line 91 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

7 statement(s) are not covered by tests.
}

fc := cache.NewFailoverBy[K, V](func(c *cache.FailoverConfigBy[K, V]) {
*c = cfg
})

Check notice on line 96 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

2 statement(s) are not covered by tests.

if l, ok := l.(interface {
CacheTransfer() *cache.HTTPTransfer
}); ok {
if w, ok := cfg.Backend.(cache.WalkDumpRestorer); ok {
l.CacheTransfer().AddCache(name, w)
}

Check notice on line 103 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

4 statement(s) are not covered by tests.
}

if l, ok := l.(interface {
CacheInvalidationIndex() *cache.InvalidationIndex
}); ok {
if d, ok := cfg.Backend.(cache.Deleter); ok {
l.CacheInvalidationIndex().AddCache(name, d)
}

Check notice on line 111 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

4 statement(s) are not covered by tests.
}

return fc

Check notice on line 114 in cache.go

View workflow job for this annotation

GitHub Actions / test (stable)

1 statement(s) are not covered by tests.
}
2 changes: 1 addition & 1 deletion cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
}

// Start loads config and runs application with provided service locator and http router.
func Start(cfg WithBaseConfig, init func(docsMode bool) (*BaseLocator, http.Handler), options ...func(o *StartOptions)) { //nolint:cyclop
func Start(cfg WithBaseConfig, init func(docsMode bool) (*BaseLocator, http.Handler), options ...func(o *StartOptions)) {

Check notice on line 33 in cmd.go

View workflow job for this annotation

GitHub Actions / test (stable)

5 statement(s) on lines 33:39 are not covered by tests.
ver := flag.Bool("version", false, "Print application version and exit.")
docs := flag.Bool("openapi", false, "Print application OpenAPI spec and exit.")
confFile := flag.String("conf", "", "Config file with ENV variables to load.")
Expand Down
4 changes: 4 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"

"github.com/bool64/brick/debug"
"github.com/bool64/brick/telemetry"
"github.com/bool64/zapctxd"
)

Expand All @@ -29,6 +30,9 @@ type BaseConfig struct {
// Debug controls dev tools.
Debug debug.Config `split_words:"true"`

// Telemetry configures OpenTelemetry export.
Telemetry telemetry.Config `split_words:"true"`

// CacheTransferURL is URL to fetch cache from on application start.
CacheTransferURL string `split_words:"true"`
}
Expand Down
4 changes: 2 additions & 2 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func DefaultLoaders(prefix string) []func() error {
//
// In no loaders are provided then vars from .env.template, .env, .env.<ENVIRONMENT>
// files are loaded if available. Use nil or any other source to avoid that.
func Load(prefix string, spec interface{}, loaders ...func() error) error {
func Load(prefix string, spec any, loaders ...func() error) error {
if len(loaders) == 0 {
loaders = DefaultLoaders(prefix)
}
Expand All @@ -94,7 +94,7 @@ func Load(prefix string, spec interface{}, loaders ...func() error) error {
return validate(spec)
}

func validate(spec interface{}) error {
func validate(spec any) error {
specj, err := json.Marshal(spec)
if err != nil {
return fmt.Errorf("json marshal: %w", err)
Expand Down
8 changes: 1 addition & 7 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
package config_test

import (
"os"
"testing"

"github.com/bool64/brick/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestLoad(t *testing.T) {
require.NoError(t, os.Chdir("./__testdata"))

defer func() {
require.NoError(t, os.Chdir(".."))
}()
t.Chdir("./__testdata")

cfg := struct {
Foo string
Expand Down
38 changes: 17 additions & 21 deletions database/observability.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,25 @@
"fmt"
"time"

"contrib.go.opencensus.io/integrations/ocsql"
"github.com/XSAM/otelsql"
"github.com/bool64/ctxd"
"github.com/bool64/dbwrap"
"github.com/bool64/stats"
"go.opencensus.io/trace"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
)

// withTracing instruments database connector with OpenCensus tracing.
func withTracing(dbConnector driver.Connector) driver.Connector {
return ocsql.WrapConnector(dbConnector, tracingOptions()...)
}

// driverNameWithTracing registers database driver name with OpenCensus tracing.
// driverNameWithTracing registers database driver name with OpenTelemetry instrumentation.
func driverNameWithTracing(driverName string) (string, error) {
return ocsql.Register(driverName, tracingOptions()...)
return otelsql.Register(driverName, tracingOptions()...)

Check notice on line 21 in database/observability.go

View workflow job for this annotation

GitHub Actions / test (stable)

1 statement(s) on lines 20:22 are not covered by tests.
}

func tracingOptions() []ocsql.TraceOption {
return []ocsql.TraceOption{
ocsql.WithQuery(true),
ocsql.WithRowsClose(true),
ocsql.WithRowsAffected(true),
ocsql.WithAllowRoot(true),
ocsql.WithDisableErrSkip(true),
func tracingOptions() []otelsql.Option {
return []otelsql.Option{
otelsql.WithTracerProvider(otel.GetTracerProvider()),
otelsql.WithMeterProvider(otel.GetMeterProvider()),
otelsql.WithDisableSkipErrMeasurement(true),

Check notice on line 28 in database/observability.go

View workflow job for this annotation

GitHub Actions / test (stable)

1 statement(s) on lines 24:30 are not covered by tests.
}
}

Expand Down Expand Up @@ -93,10 +88,10 @@
return nil, nil
}

ctx, span := trace.StartSpan(ctx, caller+":"+string(operation))
span.AddAttributes(
trace.StringAttribute("stmt", statement),
trace.StringAttribute("args", fmt.Sprintf("%v", args)),
ctx, span := otel.Tracer("github.com/bool64/brick/database").Start(ctx, caller+":"+string(operation))
span.SetAttributes(
attribute.String("db.statement", statement),
attribute.String("db.args", fmt.Sprintf("%v", args)),
)

statsTracker.Add(ctx, "sql_storage_queries_total", 1, "method", caller)
Expand All @@ -114,7 +109,8 @@
res := " complete"

if err != nil {
span.SetStatus(trace.Status{Message: err.Error()})
span.SetStatus(codes.Error, err.Error())
span.RecordError(err)

res = " failed"
}
Expand Down
Loading
Loading