19 Commits

Author SHA1 Message Date
ec35542119 cleanup depreacted ifaces
All checks were successful
lint / lint (pull_request) Successful in 1m38s
test / test (pull_request) Successful in 3m9s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-18 15:43:04 +03:00
600db7c67e cleanup deprecated
All checks were successful
lint / lint (pull_request) Successful in 2m15s
test / test (pull_request) Successful in 3m39s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-02 23:37:55 +03:00
fdebb257ae remove logger
Some checks failed
lint / lint (pull_request) Failing after 1m32s
test / test (pull_request) Successful in 3m29s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2025-01-02 23:18:13 +03:00
1b68606bce update go.mod
All checks were successful
test / test (push) Successful in 12m28s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-12 01:56:31 +03:00
8b18fecc89 add .gitea
All checks were successful
test / test (push) Successful in 55s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-12-12 00:52:15 +03:00
3b6167f7da update for latest micro logger changes
Some checks failed
codeql / analyze (go) (push) Failing after 41s
build / test (push) Failing after 4m54s
build / lint (push) Successful in 9m29s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-10-14 15:22:14 +03:00
7ac873c62f update deps, minimise memory allocations
Some checks failed
build / test (push) Failing after 8s
build / lint (push) Failing after 7s
codeql / analyze (go) (push) Failing after 10s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-09-20 18:17:16 +03:00
44256cd62f fixup tracing
Some checks failed
build / test (push) Failing after 1m49s
codeql / analyze (go) (push) Failing after 1m43s
build / lint (push) Successful in 9m16s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-05-06 08:56:16 +03:00
0dfee57dd4 fixup tracing
Some checks failed
codeql / analyze (go) (push) Failing after 1m41s
build / test (push) Failing after 1m46s
build / lint (push) Successful in 9m18s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-04-14 23:24:44 +03:00
6499c64759 update for latest logger changes
Some checks failed
codeql / analyze (go) (push) Failing after 1m48s
build / lint (push) Successful in 16m41s
build / test (push) Failing after 23m4s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-04-11 02:04:15 +03:00
87785d978a update for latest micro and requestid changes
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2024-04-11 01:55:55 +03:00
df45b9e0bb fix label names
Some checks failed
build / test (push) Failing after 1m28s
build / lint (push) Failing after 2m40s
codeql / analyze (go) (push) Failing after 3m8s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-09-05 07:08:53 +03:00
b31e3e7ffa Merge pull request 'tracing updates' (#79) from updates into v3
Some checks failed
build / test (push) Failing after 1m28s
build / lint (push) Failing after 2m44s
codeql / analyze (go) (push) Failing after 3m20s
Reviewed-on: #79
2023-09-01 14:40:50 +03:00
0e8e4d6e55 Merge branch 'v3' into updates
Some checks failed
autoapprove / autoapprove (pull_request) Failing after 1m25s
automerge / automerge (pull_request) Failing after 5s
codeql / analyze (go) (pull_request) Failing after 3m11s
dependabot-automerge / automerge (pull_request) Has been skipped
prbuild / test (pull_request) Failing after 1m28s
prbuild / lint (pull_request) Failing after 2m43s
2023-09-01 14:40:36 +03:00
34c80e29bc tracing updates
Some checks failed
autoapprove / autoapprove (pull_request) Failing after 1m26s
automerge / automerge (pull_request) Failing after 4s
codeql / analyze (go) (pull_request) Failing after 3m11s
dependabot-automerge / automerge (pull_request) Has been skipped
prbuild / test (pull_request) Failing after 1m29s
prbuild / lint (pull_request) Failing after 2m33s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-09-01 14:32:27 +03:00
974a911bfa Обновить go.mod
Some checks failed
build / test (push) Failing after 1m27s
build / lint (push) Failing after 2m34s
codeql / analyze (go) (push) Failing after 3m11s
2023-09-01 00:26:30 +03:00
cde783029d Merge pull request 'fixup metrics and tracing' (#78) from fixup into v3
Some checks failed
build / test (push) Failing after 1m27s
build / lint (push) Failing after 2m29s
codeql / analyze (go) (push) Failing after 3m3s
Reviewed-on: #78
2023-09-01 00:21:58 +03:00
927218921e fixup metrics and tracing
Some checks failed
autoapprove / autoapprove (pull_request) Failing after 1m26s
automerge / automerge (pull_request) Failing after 4s
codeql / analyze (go) (pull_request) Failing after 3m16s
dependabot-automerge / automerge (pull_request) Has been skipped
prbuild / test (pull_request) Failing after 1m29s
prbuild / lint (pull_request) Failing after 2m36s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-09-01 00:21:08 +03:00
4b3ba3f76a fixup v3
Some checks failed
build / test (push) Failing after 1m28s
build / lint (push) Failing after 2m41s
codeql / analyze (go) (push) Failing after 2m31s
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2023-08-29 01:30:27 +03:00
30 changed files with 3553 additions and 19760 deletions

View File

@@ -1,6 +1,6 @@
--- ---
name: Bug report name: Bug report
about: For reporting bugs in go-micro about: For reporting bugs in micro
title: "[BUG]" title: "[BUG]"
labels: '' labels: ''
assignees: '' assignees: ''
@@ -16,9 +16,3 @@ assignees: ''
**How to reproduce the bug:** **How to reproduce the bug:**
If possible, please include a minimal code snippet here. If possible, please include a minimal code snippet here.
**Environment:**
Go Version: please paste `go version` output here
```
please paste `go env` output here
```

View File

@@ -1,6 +1,6 @@
--- ---
name: Feature request / Enhancement name: Feature request / Enhancement
about: If you have a need not served by go-micro about: If you have a need not served by micro
title: "[FEATURE]" title: "[FEATURE]"
labels: '' labels: ''
assignees: '' assignees: ''
@@ -14,4 +14,4 @@ A clear and concise description of what the problem is. Ex. I'm always frustrate
A clear and concise description of what you want to happen. A clear and concise description of what you want to happen.
**Additional context** **Additional context**
Add any other context or screenshots about the feature request here. Add any other context or screenshots about the feature request here.

View File

@@ -0,0 +1,8 @@
---
name: Question
about: Ask a question about micro
title: ''
labels: ''
assignees: ''
---

28
.gitea/autoapprove.yml Normal file
View File

@@ -0,0 +1,28 @@
name: "autoapprove"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
workflow_run:
workflows: ["prbuild"]
types:
- completed
permissions:
pull-requests: write
contents: write
jobs:
autoapprove:
runs-on: ubuntu-latest
steps:
- name: approve
run: [ "curl -o tea https://dl.gitea.com/tea/main/tea-main-linux-amd64",
"chmod +x ./tea",
"./tea login add --name unistack --token ${{ secrets.GITHUB_TOKEN }} --url https://git.unistack.org",
"./tea pr --repo ${{ github.event.repository.name }}"
]
if: github.actor == 'vtolstov'
id: approve
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -0,0 +1,29 @@
name: lint
on:
pull_request:
types: [opened, reopened, synchronize]
branches:
- master
- v3
- v4
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup deps
run: go get -v ./...
- name: run lint
uses: https://github.com/golangci/golangci-lint-action@v6
with:
version: 'latest'

View File

@@ -0,0 +1,34 @@
name: test
on:
pull_request:
types: [opened, reopened, synchronize]
branches:
- master
- v3
- v4
push:
branches:
- master
- v3
- v4
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup deps
run: go get -v ./...
- name: run test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...

View File

@@ -0,0 +1,53 @@
name: test
on:
pull_request:
types: [opened, reopened, synchronize]
branches:
- master
- v3
- v4
push:
branches:
- master
- v3
- v4
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v4
with:
filter: 'blob:none'
- name: checkout tests
uses: actions/checkout@v4
with:
ref: master
filter: 'blob:none'
repository: unistack-org/micro-tests
path: micro-tests
- name: setup go
uses: actions/setup-go@v5
with:
cache-dependency-path: "**/*.sum"
go-version: 'stable'
- name: setup go work
env:
GOWORK: /workspace/${{ github.repository_owner }}/go.work
run: |
go work init
go work use .
go work use micro-tests
- name: setup deps
env:
GOWORK: /workspace/${{ github.repository_owner }}/go.work
run: go get -v ./...
- name: run tests
env:
INTEGRATION_TESTS: yes
GOWORK: /workspace/${{ github.repository_owner }}/go.work
run: |
cd micro-tests
go test -mod readonly -v ./... || true

View File

@@ -1,14 +0,0 @@
---
name: Question
about: Ask a question about go-micro
title: ''
labels: ''
assignees: ''
---
Before asking, please check if your question has already been answered:
1. Check the documentation - https://micro.mu/docs/
2. Check the examples and plugins - https://github.com/micro/examples & https://github.com/micro/go-plugins
3. Search existing issues

View File

@@ -1,19 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
# Maintain dependencies for Golang
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "daily"

View File

@@ -1,20 +0,0 @@
name: "autoapprove"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
autoapprove:
runs-on: ubuntu-latest
steps:
- name: approve
uses: hmarr/auto-approve-action@v3
if: github.actor == 'vtolstov' || github.actor == 'dependabot[bot]'
id: approve
with:
github-token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,21 +0,0 @@
name: "automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'vtolstov'
steps:
- name: merge
id: merge
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@@ -1,47 +0,0 @@
name: build
on:
push:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: checkout
uses: actions/checkout@v3
- name: cache
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
continue-on-error: true
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.30
# 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

View File

@@ -1,78 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "codeql"
on:
workflow_run:
workflows: ["prbuild"]
types:
- completed
push:
branches: [ master, v3 ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master, v3 ]
schedule:
- cron: '34 1 * * 0'
jobs:
analyze:
name: analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: checkout
uses: actions/checkout@v3
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
# Initializes the CodeQL tools for scanning.
- name: init
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: analyze
uses: github/codeql-action/analyze@v2

View File

@@ -1,27 +0,0 @@
name: "dependabot-automerge"
on:
pull_request_target:
types: [assigned, opened, synchronize, reopened]
permissions:
pull-requests: write
contents: write
jobs:
automerge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- name: metadata
id: metadata
uses: dependabot/fetch-metadata@v1.3.6
with:
github-token: "${{ secrets.TOKEN }}"
- name: merge
id: merge
if: ${{contains(steps.metadata.outputs.dependency-names, 'go.unistack.org')}}
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{github.event.pull_request.html_url}}
GITHUB_TOKEN: ${{secrets.TOKEN}}

View File

@@ -1,47 +0,0 @@
name: prbuild
on:
pull_request:
branches:
- master
- v3
jobs:
test:
name: test
runs-on: ubuntu-latest
steps:
- name: setup
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: checkout
uses: actions/checkout@v3
- name: cache
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-go-
- name: deps
run: go get -v -t -d ./...
- name: test
env:
INTEGRATION_TESTS: yes
run: go test -mod readonly -v ./...
lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: lint
uses: golangci/golangci-lint-action@v3.4.0
continue-on-error: true
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.30
# 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

View File

@@ -54,8 +54,6 @@ func Connect(cfg *PostgresConfig) (*sqlx.DB, error) {
sql.Register("micro-wrapper-sql", wrapper.NewWrapper(&sqlite.Driver{}, sql.Register("micro-wrapper-sql", wrapper.NewWrapper(&sqlite.Driver{},
wrapper.DatabaseHost("localhost"), wrapper.DatabaseHost("localhost"),
wrapper.DatabaseName("mydb"), wrapper.DatabaseName("mydb"),
wrapper.LoggerLevel(logger.DebugLevel),
wrapper.LoggerEnabled(true),
)) ))
wdb, err := sql.Open("micro-wrapper-sql", dsn) wdb, err := sql.Open("micro-wrapper-sql", dsn)

View File

@@ -4,6 +4,7 @@ import (
"database/sql/driver" "database/sql/driver"
"errors" "errors"
"fmt" "fmt"
"runtime"
) )
//go:generate sh -c "go run gen.go > wrap_gen.go" //go:generate sh -c "go run gen.go > wrap_gen.go"
@@ -31,7 +32,20 @@ func namedValueToLabels(named []driver.NamedValue) []interface{} {
} else { } else {
name = fmt.Sprintf("$%d", param.Ordinal) name = fmt.Sprintf("$%d", param.Ordinal)
} }
largs = append(largs, fmt.Sprintf("%s=%s", name, param.Value)) largs = append(largs, fmt.Sprintf("%s=%v", name, param.Value))
} }
return largs return largs
} }
// getCallerName get the name of the function A where A() -> B() -> GetFunctionCallerName()
func getCallerName() string {
pc, _, _, ok := runtime.Caller(3)
details := runtime.FuncForPC(pc)
var callerName string
if ok && details != nil {
callerName = details.Name()
} else {
callerName = labelUnknown
}
return callerName
}

220
conn.go
View File

@@ -6,7 +6,8 @@ import (
"fmt" "fmt"
"time" "time"
"go.unistack.org/micro/v4/tracer" requestid "go.unistack.org/micro-wrapper-requestid/v3"
"go.unistack.org/micro/v3/tracer"
) )
var ( var (
@@ -15,9 +16,7 @@ var (
_ driver.ConnPrepareContext = (*wrapperConn)(nil) _ driver.ConnPrepareContext = (*wrapperConn)(nil)
_ driver.Pinger = (*wrapperConn)(nil) _ driver.Pinger = (*wrapperConn)(nil)
_ driver.Validator = (*wrapperConn)(nil) _ driver.Validator = (*wrapperConn)(nil)
_ driver.Queryer = (*wrapperConn)(nil)
_ driver.QueryerContext = (*wrapperConn)(nil) _ driver.QueryerContext = (*wrapperConn)(nil)
_ driver.Execer = (*wrapperConn)(nil)
_ driver.ExecerContext = (*wrapperConn)(nil) _ driver.ExecerContext = (*wrapperConn)(nil)
// _ driver.Connector // _ driver.Connector
// _ driver.Driver // _ driver.Driver
@@ -31,7 +30,7 @@ type wrapperConn struct {
conn driver.Conn conn driver.Conn
opts Options opts Options
ctx context.Context ctx context.Context
span tracer.Span // span tracer.Span
} }
// Close implements driver.Conn Close // Close implements driver.Conn Close
@@ -42,7 +41,7 @@ func (w *wrapperConn) Close() error {
} else { } else {
ctx = context.Background() ctx = context.Background()
} }
_ = ctx
labels := []string{labelMethod, "Close"} labels := []string{labelMethod, "Close"}
ts := time.Now() ts := time.Now()
err := w.conn.Close() err := w.conn.Close()
@@ -56,10 +55,6 @@ func (w *wrapperConn) Close() error {
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Close", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return err return err
} }
@@ -81,30 +76,24 @@ func (w *wrapperConn) Begin() (driver.Tx, error) {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Begin", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return nil, err return nil, err
} }
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Begin", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return &wrapperTx{tx: tx, opts: w.opts, ctx: ctx}, nil return &wrapperTx{tx: tx, opts: w.opts, ctx: ctx}, nil
} }
// BeginTx implements driver.ConnBeginTx BeginTx // BeginTx implements driver.ConnBeginTx BeginTx
func (w *wrapperConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) { func (w *wrapperConn) BeginTx(ctx context.Context, opts driver.TxOptions) (driver.Tx, error) {
nctx, span := w.opts.Tracer.Start(ctx, "Transaction")
span.AddLabels("method", "BeginTx")
name := getQueryName(ctx) name := getQueryName(ctx)
if name != "" { nctx, span := w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
span.AddLabels("query", name) span.AddLabels("db.method", "BeginTx")
} else { span.AddLabels("db.statement", name)
name = labelUnknown if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
} }
labels := []string{labelMethod, "BeginTx", labelQuery, name} labels := []string{labelMethod, "BeginTx", labelQuery, name}
@@ -121,17 +110,12 @@ func (w *wrapperConn) BeginTx(ctx context.Context, opts driver.TxOptions) (drive
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "BeginTx", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return nil, err return nil, err
} }
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "BeginTx", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return &wrapperTx{tx: tx, opts: w.opts, ctx: ctx, span: span}, nil return &wrapperTx{tx: tx, opts: w.opts, ctx: ctx, span: span}, nil
} }
@@ -143,8 +127,8 @@ func (w *wrapperConn) Prepare(query string) (driver.Stmt, error) {
} else { } else {
ctx = context.Background() ctx = context.Background()
} }
_ = ctx
labels := []string{labelMethod, "Prepare", labelQuery, labelUnknown} labels := []string{labelMethod, "Prepare", labelQuery, getCallerName()}
ts := time.Now() ts := time.Now()
stmt, err := w.conn.Prepare(query) stmt, err := w.conn.Prepare(query)
td := time.Since(ts) td := time.Since(ts)
@@ -154,19 +138,12 @@ func (w *wrapperConn) Prepare(query string) (driver.Stmt, error) {
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Prepare", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return nil, err return nil, err
} }
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Prepare", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return wrapStmt(stmt, query, w.opts), nil return wrapStmt(stmt, query, w.opts), nil
} }
@@ -174,19 +151,18 @@ func (w *wrapperConn) Prepare(query string) (driver.Stmt, error) {
func (w *wrapperConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) { func (w *wrapperConn) PrepareContext(ctx context.Context, query string) (driver.Stmt, error) {
var nctx context.Context var nctx context.Context
var span tracer.Span var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "PrepareContext")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "PrepareContext")
}
span.AddLabels("method", "PrepareContext")
name := getQueryName(ctx)
if name != "" {
span.AddLabels("query", name)
} else {
name = labelUnknown
}
name := getQueryName(ctx)
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} else {
nctx, span = w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
}
span.AddLabels("db.method", "PrepareContext")
span.AddLabels("db.statement", name)
if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
}
labels := []string{labelMethod, "PrepareContext", labelQuery, name} labels := []string{labelMethod, "PrepareContext", labelQuery, name}
conn, ok := w.conn.(driver.ConnPrepareContext) conn, ok := w.conn.(driver.ConnPrepareContext)
if !ok { if !ok {
@@ -201,79 +177,38 @@ func (w *wrapperConn) PrepareContext(ctx context.Context, query string) (driver.
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "PrepareContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return nil, err return nil, err
} }
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "PrepareContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return wrapStmt(stmt, query, w.opts), nil return wrapStmt(stmt, query, w.opts), nil
} }
// Exec implements driver.Execer Exec
func (w *wrapperConn) Exec(query string, args []driver.Value) (driver.Result, error) {
var ctx context.Context
if w.ctx != nil {
ctx = w.ctx
} else {
ctx = context.Background()
}
labels := []string{labelMethod, "Exec", labelQuery, labelUnknown}
// nolint:staticcheck
conn, ok := w.conn.(driver.Execer)
if !ok {
return nil, driver.ErrSkip
}
ts := time.Now()
res, err := conn.Exec(query, args)
td := time.Since(ts)
te := td.Seconds()
if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
} else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
}
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Exec", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return res, err
}
// Exec implements driver.StmtExecContext ExecContext // Exec implements driver.StmtExecContext ExecContext
func (w *wrapperConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) { func (w *wrapperConn) ExecContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Result, error) {
var nctx context.Context var nctx context.Context
var span tracer.Span var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "ExecContext")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "ExecContext")
}
span.AddLabels("method", "ExecContext")
name := getQueryName(ctx) name := getQueryName(ctx)
if name != "" { if w.ctx != nil {
span.AddLabels("query", name) nctx, span = w.opts.Tracer.Start(w.ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} else { } else {
name = labelUnknown nctx, span = w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
}
span.AddLabels("db.method", "ExecContext")
span.AddLabels("db.statement", name)
if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
} }
defer span.Finish() defer span.Finish()
if len(args) > 0 { if len(args) > 0 {
span.AddLabels("args", fmt.Sprintf("%v", namedValueToLabels(args))) span.AddLabels("db.args", fmt.Sprintf("%v", namedValueToLabels(args)))
} }
labels := []string{labelMethod, "ExecContext", labelQuery, name} labels := []string{labelMethod, "ExecContext", labelQuery, name}
fmt.Printf("EXECCONTETX args %#+v\n", args)
conn, ok := w.conn.(driver.ExecerContext) conn, ok := w.conn.(driver.ExecerContext)
if !ok { if !ok {
@@ -287,17 +222,13 @@ func (w *wrapperConn) ExecContext(ctx context.Context, query string, args []driv
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "ExecContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return res, err return res, err
} }
@@ -315,26 +246,14 @@ func (w *wrapperConn) Ping(ctx context.Context) error {
return pc.Close() return pc.Close()
} }
var nctx context.Context
var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "Ping")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "Ping")
}
defer span.Finish()
labels := []string{labelMethod, "Ping"} labels := []string{labelMethod, "Ping"}
ts := time.Now() ts := time.Now()
err := conn.Ping(nctx) err := conn.Ping(ctx)
td := time.Since(ts) td := time.Since(ts)
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) // span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Ping", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return err return err
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
@@ -345,57 +264,56 @@ func (w *wrapperConn) Ping(ctx context.Context) error {
return nil return nil
} }
// Query implements driver.Queryer Query // Ping implements driver.Pinger PingContext
func (w *wrapperConn) Query(query string, args []driver.Value) (driver.Rows, error) { func (w *wrapperConn) PingContext(ctx context.Context) error {
var ctx context.Context conn, ok := w.conn.(driver.Pinger)
if w.ctx != nil {
ctx = w.ctx
} else {
ctx = context.Background()
}
// nolint:staticcheck
conn, ok := w.conn.(driver.Queryer)
if !ok { if !ok {
return nil, driver.ErrSkip // fallback path to check db alive
pc, err := w.d.Open(w.dname)
if err != nil {
return err
}
return pc.Close()
} }
labels := []string{labelMethod, "Query", labelQuery, labelUnknown} labels := []string{labelMethod, "Ping"}
ts := time.Now() ts := time.Now()
rows, err := conn.Query(query, args) err := conn.Ping(ctx)
td := time.Since(ts) td := time.Since(ts)
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
// span.SetStatus(tracer.SpanStatusError, err.Error())
return err
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Query", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel) return nil
}
return rows, err
} }
// QueryContext implements Driver.QueryerContext QueryContext // QueryContext implements Driver.QueryerContext QueryContext
func (w *wrapperConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) { func (w *wrapperConn) QueryContext(ctx context.Context, query string, args []driver.NamedValue) (driver.Rows, error) {
var nctx context.Context var nctx context.Context
var span tracer.Span var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "QueryContext")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "QueryContext")
}
span.AddLabels("method", "QueryContext")
name := getQueryName(ctx) name := getQueryName(ctx)
if name != "" { if w.ctx != nil {
span.AddLabels("query", name) nctx, span = w.opts.Tracer.Start(w.ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} else { } else {
name = labelUnknown nctx, span = w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
}
span.AddLabels("db.method", "QueryContext")
span.AddLabels("db.statement", name)
if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
} }
defer span.Finish() defer span.Finish()
if len(args) > 0 { if len(args) > 0 {
span.AddLabels("args", fmt.Sprintf("%v", namedValueToLabels(args))) span.AddLabels("db.args", fmt.Sprintf("%v", namedValueToLabels(args)))
} }
labels := []string{labelMethod, "QueryContext", labelQuery, name} labels := []string{labelMethod, "QueryContext", labelQuery, name}
conn, ok := w.conn.(driver.QueryerContext) conn, ok := w.conn.(driver.QueryerContext)
@@ -409,16 +327,12 @@ func (w *wrapperConn) QueryContext(ctx context.Context, query string, args []dri
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "QueryContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel)
}
return rows, err return rows, err
} }

2
doc.go
View File

@@ -1,2 +1,2 @@
// package wrapper provides SQL driver wrapper with micro tracing, logging, metering capabilities // package wrapper provides SQL driver wrapper with micro tracing and metering capabilities
package wrapper package wrapper

View File

@@ -11,29 +11,22 @@ var (
// _ driver.Connector = (*wrapperDriver)(nil) // _ driver.Connector = (*wrapperDriver)(nil)
) )
/*
type conn interface { type conn interface {
driver.Pinger driver.Pinger
driver.Execer
driver.ExecerContext driver.ExecerContext
driver.Queryer
driver.QueryerContext driver.QueryerContext
driver.Conn driver.Conn
driver.ConnPrepareContext driver.ConnPrepareContext
driver.ConnBeginTx driver.ConnBeginTx
} }
*/
// wrapperDriver defines a wrapper for driver.Driver // wrapperDriver defines a wrapper for driver.Driver
type wrapperDriver struct { type wrapperDriver struct {
driver driver.Driver
connector driver.Connector
opts Options
ctx context.Context
}
type wrapperConnector struct {
driver driver.Driver driver driver.Driver
name string
opts Options opts Options
ctx context.Context
} }
// NewWrapper creates and returns a new SQL driver with passed capabilities // NewWrapper creates and returns a new SQL driver with passed capabilities
@@ -41,17 +34,26 @@ func NewWrapper(d driver.Driver, opts ...Option) driver.Driver {
return &wrapperDriver{driver: d, opts: NewOptions(opts...), ctx: context.Background()} return &wrapperDriver{driver: d, opts: NewOptions(opts...), ctx: context.Background()}
} }
/* type wrappedConnector struct {
connector driver.Connector
// name string
opts Options
ctx context.Context
}
func NewWrapperConnector(c driver.Connector, opts ...Option) driver.Connector {
return &wrappedConnector{connector: c, opts: NewOptions(opts...), ctx: context.Background()}
}
// Connect implements driver.Driver Connect // Connect implements driver.Driver Connect
func (w *wrapperConnector) Connect(ctx context.Context) (driver.Conn, error) { func (w *wrappedConnector) Connect(ctx context.Context) (driver.Conn, error) {
return w.driver.Connect(ctx) return w.connector.Connect(ctx)
} }
// Driver implements driver.Driver Driver // Driver implements driver.Driver Driver
func (w *wrapperConnector) Driver() driver.Driver { func (w *wrappedConnector) Driver() driver.Driver {
return w.driver return w.connector.Driver()
} }
*/
/* /*
// Connect implements driver.Driver OpenConnector // Connect implements driver.Driver OpenConnector
@@ -76,10 +78,12 @@ func (w *wrapperDriver) Open(name string) (driver.Conn, error) {
ts := time.Now() ts := time.Now()
c, err := w.driver.Open(name) c, err := w.driver.Open(name)
td := time.Since(ts) td := time.Since(ts)
/*
if w.opts.LoggerEnabled { if w.opts.LoggerEnabled {
w.opts.Logger.Fields(w.opts.LoggerObserver(w.ctx, "Open", labelUnknown, td, err)...).Log(w.ctx, w.opts.LoggerLevel) w.opts.Logger.Log(w.ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(w.ctx, "Open", getCallerName(), td, err)...)
} }
*/
_ = td
if err != nil { if err != nil {
return nil, err return nil, err
} }

19
gen.go
View File

@@ -14,11 +14,9 @@ import (
var connIfaces = []string{ var connIfaces = []string{
"driver.ConnBeginTx", "driver.ConnBeginTx",
"driver.ConnPrepareContext", "driver.ConnPrepareContext",
"driver.Execer",
"driver.ExecerContext", "driver.ExecerContext",
"driver.NamedValueChecker", "driver.NamedValueChecker",
"driver.Pinger", "driver.Pinger",
"driver.Queryer",
"driver.QueryerContext", "driver.QueryerContext",
"driver.SessionResetter", "driver.SessionResetter",
"driver.Validator", "driver.Validator",
@@ -27,7 +25,6 @@ var connIfaces = []string{
var stmtIfaces = []string{ var stmtIfaces = []string{
"driver.StmtExecContext", "driver.StmtExecContext",
"driver.StmtQueryContext", "driver.StmtQueryContext",
"driver.ColumnConverter",
"driver.NamedValueChecker", "driver.NamedValueChecker",
} }
@@ -66,7 +63,7 @@ func main() {
continue continue
} }
h := getHash(ifaces) h := getHash(ifaces)
b.WriteString(fmt.Sprintf("\tif v, ok := dc.(wrapConn%04d_%s); ok {\n", n, h)) b.WriteString(fmt.Sprintf("\tif _, ok := dc.(wrapConn%04d_%s); ok {\n", n, h))
b.WriteString("\treturn struct {\n") b.WriteString("\treturn struct {\n")
b.WriteString("\t\tdriver.Conn\n") b.WriteString("\t\tdriver.Conn\n")
b.WriteString(fmt.Sprintf("\t\t\t%s", strings.Join(ifaces, "\n\t\t\t"))) b.WriteString(fmt.Sprintf("\t\t\t%s", strings.Join(ifaces, "\n\t\t\t")))
@@ -74,14 +71,14 @@ func main() {
for idx := range ifaces { for idx := range ifaces {
if idx > 0 { if idx > 0 {
b.WriteString(", ") b.WriteString(", ")
b.WriteString("v") b.WriteString("c")
} else if idx == 0 { } else if idx == 0 {
b.WriteString("c") b.WriteString("c")
} else { } else {
b.WriteString("v") b.WriteString("c")
} }
} }
b.WriteString(", v}\n") b.WriteString(", c}\n")
b.WriteString("}\n\n") b.WriteString("}\n\n")
} }
b.WriteString("return c\n") b.WriteString("return c\n")
@@ -112,7 +109,7 @@ func main() {
continue continue
} }
h := getHash(ifaces) h := getHash(ifaces)
b.WriteString(fmt.Sprintf("\tif v, ok := stmt.(wrapStmt%04d_%s); ok {\n", n, h)) b.WriteString(fmt.Sprintf("\tif _, ok := stmt.(wrapStmt%04d_%s); ok {\n", n, h))
b.WriteString("\treturn struct {\n") b.WriteString("\treturn struct {\n")
b.WriteString("\t\tdriver.Stmt\n") b.WriteString("\t\tdriver.Stmt\n")
b.WriteString(fmt.Sprintf("\t\t\t%s", strings.Join(ifaces, "\n\t\t\t"))) b.WriteString(fmt.Sprintf("\t\t\t%s", strings.Join(ifaces, "\n\t\t\t")))
@@ -120,14 +117,14 @@ func main() {
for idx := range ifaces { for idx := range ifaces {
if idx > 0 { if idx > 0 {
b.WriteString(", ") b.WriteString(", ")
b.WriteString("v") b.WriteString("c")
} else if idx == 0 { } else if idx == 0 {
b.WriteString("c") b.WriteString("c")
} else { } else {
b.WriteString("v") b.WriteString("c")
} }
} }
b.WriteString(", v}\n") b.WriteString(", c}\n")
b.WriteString("}\n\n") b.WriteString("}\n\n")
} }
b.WriteString("return c\n") b.WriteString("return c\n")

20
go.mod
View File

@@ -1,5 +1,19 @@
module go.unistack.org/micro-wrapper-sql/v4 module go.unistack.org/micro-wrapper-sql/v3
go 1.19 go 1.22
require go.unistack.org/micro/v4 v4.0.3 toolchain go1.23.2
require (
go.unistack.org/micro-wrapper-requestid/v3 v3.9.3
go.unistack.org/micro/v3 v3.11.14
)
require (
go.unistack.org/micro-proto/v3 v3.4.1 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect
google.golang.org/grpc v1.69.2 // indirect
google.golang.org/protobuf v1.36.1 // indirect
)

24
go.sum
View File

@@ -1,2 +1,22 @@
go.unistack.org/micro/v4 v4.0.3 h1:AFr21ua3IrkuxH26kNYVrs7Kpsrm+4aylE/PfjLdCWM= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
go.unistack.org/micro/v4 v4.0.3/go.mod h1:+wBa98rSf+mRXb/MuSVFPXtDrqN0k8rzPQiC8wRCwCo= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
go.unistack.org/micro-wrapper-requestid/v3 v3.9.3 h1:KQS4nZhQ7S08xjMbpkXwQBhydfCC8YcHuORkoUDeAqI=
go.unistack.org/micro-wrapper-requestid/v3 v3.9.3/go.mod h1:cqgjdSSASTnOLjvwndP9bi0b8DbuoKbDII884R5puwU=
go.unistack.org/micro/v3 v3.11.14 h1:3e9T30Ih9cvqZTCD8inG1qsBWRk4x5ZinWuTiDFM4CE=
go.unistack.org/micro/v3 v3.11.14/go.mod h1:k++F5Ej4LIy3XnOW/oj3P7B97wp2t9yLSlqtUzMpatM=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576 h1:8ZmaLZE4XWrtU3MyClkYqqtl6Oegr3235h7jxsDyqCY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20241209162323-e6fa225c2576/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
google.golang.org/grpc v1.68.1 h1:oI5oTa11+ng8r8XMMN7jAOmWfPZWbYpCFaMUTACxkM0=
google.golang.org/grpc v1.68.1/go.mod h1:+q1XYFJjShcqn0QZHvCyeR4CXPA+llXIeUIfIe00waw=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=

View File

@@ -2,50 +2,34 @@ package wrapper
import ( import (
"context" "context"
"fmt"
"time" "time"
"go.unistack.org/micro/v4/logger" "go.unistack.org/micro/v3/logger"
"go.unistack.org/micro/v4/meter" "go.unistack.org/micro/v3/meter"
"go.unistack.org/micro/v4/tracer" "go.unistack.org/micro/v3/tracer"
) )
var ( // DefaultMeterStatsInterval holds default stats interval
// DefaultMeterStatsInterval holds default stats interval var DefaultMeterStatsInterval = 5 * time.Second
DefaultMeterStatsInterval = 5 * time.Second
// DefaultMeterMetricPrefix holds default metric prefix
DefaultMeterMetricPrefix = "micro_sql_"
// DefaultLoggerObserver used to prepare labels for logger
DefaultLoggerObserver = func(ctx context.Context, method string, query string, td time.Duration, err error) []interface{} {
labels := []interface{}{"method", method, "took", fmt.Sprintf("%v", td)}
if err != nil {
labels = append(labels, "error", err.Error())
}
if query != labelUnknown {
labels = append(labels, "query", query)
}
return labels
}
)
var ( var (
MaxOpenConnections = "max_open_connections" MaxOpenConnections = "micro_sql_max_open_conn"
OpenConnections = "open_connections" OpenConnections = "micro_sql_open_conn"
InuseConnections = "inuse_connections" InuseConnections = "micro_sql_inuse_conn"
IdleConnections = "idle_connections" IdleConnections = "micro_sql_idle_conn"
WaitConnections = "wait_connections" WaitConnections = "micro_sql_waited_conn"
BlockedSeconds = "blocked_seconds" BlockedSeconds = "micro_sql_blocked_seconds"
MaxIdleClosed = "max_idle_closed" MaxIdleClosed = "micro_sql_max_idle_closed"
MaxIdletimeClosed = "max_idletime_closed" MaxIdletimeClosed = "micro_sql_closed_max_idle"
MaxLifetimeClosed = "max_lifetime_closed" MaxLifetimeClosed = "micro_sql_closed_max_lifetime"
meterRequestTotal = "request_total" meterRequestTotal = "micro_sql_request_total"
meterRequestLatencyMicroseconds = "request_latency_microseconds" meterRequestLatencyMicroseconds = "micro_sql_latency_microseconds"
meterRequestDurationSeconds = "request_duration_seconds" meterRequestDurationSeconds = "micro_sql_request_duration_seconds"
labelUnknown = "unknown" labelUnknown = "unknown"
labelQuery = "query" labelQuery = "db_statement"
labelMethod = "method" labelMethod = "db_method"
labelStatus = "status" labelStatus = "status"
labelSuccess = "success" labelSuccess = "success"
labelFailure = "failure" labelFailure = "failure"
@@ -55,12 +39,10 @@ var (
// Options struct holds wrapper options // Options struct holds wrapper options
type Options struct { type Options struct {
Logger logger.Logger
Meter meter.Meter Meter meter.Meter
Tracer tracer.Tracer Tracer tracer.Tracer
DatabaseHost string DatabaseHost string
DatabaseName string DatabaseName string
MeterMetricPrefix string
MeterStatsInterval time.Duration MeterStatsInterval time.Duration
LoggerLevel logger.Level LoggerLevel logger.Level
LoggerEnabled bool LoggerEnabled bool
@@ -73,28 +55,21 @@ type Option func(*Options)
// NewOptions create new Options struct from provided option slice // NewOptions create new Options struct from provided option slice
func NewOptions(opts ...Option) Options { func NewOptions(opts ...Option) Options {
options := Options{ options := Options{
Logger: logger.DefaultLogger,
Meter: meter.DefaultMeter, Meter: meter.DefaultMeter,
Tracer: tracer.DefaultTracer, Tracer: tracer.DefaultTracer,
MeterStatsInterval: DefaultMeterStatsInterval, MeterStatsInterval: DefaultMeterStatsInterval,
MeterMetricPrefix: DefaultMeterMetricPrefix,
LoggerLevel: logger.DebugLevel,
LoggerObserver: DefaultLoggerObserver,
} }
for _, o := range opts { for _, o := range opts {
o(&options) o(&options)
} }
options.Meter = options.Meter.Clone( options.Meter = options.Meter.Clone(
meter.MetricPrefix(options.MeterMetricPrefix),
meter.Labels( meter.Labels(
labelHost, options.DatabaseHost, labelHost, options.DatabaseHost,
labelDatabase, options.DatabaseName, labelDatabase, options.DatabaseName,
), ),
) )
options.Logger = options.Logger.Clone(logger.WithCallerSkipCount(1))
return options return options
} }
@@ -105,13 +80,6 @@ func MetricInterval(td time.Duration) Option {
} }
} }
// MetricPrefix specifies prefix for each metric
func MetricPrefix(pref string) Option {
return func(o *Options) {
o.MeterMetricPrefix = pref
}
}
func DatabaseHost(host string) Option { func DatabaseHost(host string) Option {
return func(o *Options) { return func(o *Options) {
o.DatabaseHost = host o.DatabaseHost = host
@@ -131,34 +99,6 @@ func Meter(m meter.Meter) Option {
} }
} }
// Logger passes logger.Logger to wrapper
func Logger(l logger.Logger) Option {
return func(o *Options) {
o.Logger = l
}
}
// LoggerEnabled enable sql logging
func LoggerEnabled(b bool) Option {
return func(o *Options) {
o.LoggerEnabled = b
}
}
// LoggerLevel passes logger.Level option
func LoggerLevel(lvl logger.Level) Option {
return func(o *Options) {
o.LoggerLevel = lvl
}
}
// LoggerObserver passes observer to fill logger fields
func LoggerObserver(obs func(context.Context, string, string, time.Duration, error) []interface{}) Option {
return func(o *Options) {
o.LoggerObserver = obs
}
}
// Tracer passes tracer.Tracer to wrapper // Tracer passes tracer.Tracer to wrapper
func Tracer(t tracer.Tracer) Option { func Tracer(t tracer.Tracer) Option {
return func(o *Options) { return func(o *Options) {
@@ -177,8 +117,8 @@ func QueryName(ctx context.Context, name string) context.Context {
} }
func getQueryName(ctx context.Context) string { func getQueryName(ctx context.Context) string {
if v, ok := ctx.Value(queryNameKey{}).(string); ok { if v, ok := ctx.Value(queryNameKey{}).(string); ok && v != labelUnknown {
return v return v
} }
return "" return getCallerName()
} }

View File

@@ -1,4 +1,4 @@
package wrapper // import "go.unistack.org/micro-wrapper-sql-1/v3" package wrapper // import "go.unistack.org/micro-wrapper-sql/v3"
import ( import (
"context" "context"

161
stmt.go
View File

@@ -6,7 +6,8 @@ import (
"fmt" "fmt"
"time" "time"
"go.unistack.org/micro/v4/tracer" requestid "go.unistack.org/micro-wrapper-requestid/v3"
"go.unistack.org/micro/v3/tracer"
) )
var ( var (
@@ -32,6 +33,7 @@ func (w *wrapperStmt) Close() error {
} else { } else {
ctx = context.Background() ctx = context.Background()
} }
_ = ctx
labels := []string{labelMethod, "Close"} labels := []string{labelMethod, "Close"}
ts := time.Now() ts := time.Now()
err := w.stmt.Close() err := w.stmt.Close()
@@ -44,10 +46,11 @@ func (w *wrapperStmt) Close() error {
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Close", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "Close", getCallerName(), td, err)...)
} }
*/
return err return err
} }
@@ -73,6 +76,7 @@ func (w *wrapperStmt) Exec(args []driver.Value) (driver.Result, error) {
} else { } else {
ctx = context.Background() ctx = context.Background()
} }
_ = ctx
labels := []string{labelMethod, "Exec"} labels := []string{labelMethod, "Exec"}
ts := time.Now() ts := time.Now()
res, err := w.stmt.Exec(args) // nolint:staticcheck res, err := w.stmt.Exec(args) // nolint:staticcheck
@@ -85,11 +89,11 @@ func (w *wrapperStmt) Exec(args []driver.Value) (driver.Result, error) {
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Exec", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "Exec", getCallerName(), td, err)...)
} }
*/
return res, err return res, err
} }
@@ -101,10 +105,10 @@ func (w *wrapperStmt) Query(args []driver.Value) (driver.Rows, error) {
} else { } else {
ctx = context.Background() ctx = context.Background()
} }
_ = ctx
labels := []string{labelMethod, "Query"} labels := []string{labelMethod, "Query"}
ts := time.Now() ts := time.Now()
// nolint:staticcheck rows, err := w.stmt.Query(args) // nolint:staticcheck
rows, err := w.stmt.Query(args)
td := time.Since(ts) td := time.Since(ts)
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
@@ -114,33 +118,42 @@ func (w *wrapperStmt) Query(args []driver.Value) (driver.Rows, error) {
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "Query", labelUnknown, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "Query", getCallerName(), td, err)...)
} }
*/
return rows, err return rows, err
} }
// ColumnConverter implements driver.ColumnConverter
func (w *wrapperStmt) ColumnConverter(idx int) driver.ValueConverter {
s, ok := w.stmt.(driver.ColumnConverter) // nolint:staticcheck
if !ok {
return nil
}
return s.ColumnConverter(idx)
}
// ExecContext implements driver.StmtExecContext ExecContext // ExecContext implements driver.StmtExecContext ExecContext
func (w *wrapperStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) { func (w *wrapperStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error) {
var nctx context.Context var nctx context.Context
var span tracer.Span var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "ExecContext")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "ExecContext")
}
span.AddLabels("method", "ExecContext")
name := getQueryName(ctx) name := getQueryName(ctx)
if name != "" { if w.ctx != nil {
span.AddLabels("query", name) nctx, span = w.opts.Tracer.Start(w.ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} else { } else {
name = labelUnknown nctx, span = w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} }
span.AddLabels("db.method", "ExecContext")
span.AddLabels("db.statement", name)
defer span.Finish() defer span.Finish()
if len(args) > 0 { if len(args) > 0 {
span.AddLabels("args", fmt.Sprintf("%v", namedValueToLabels(args))) span.AddLabels("db.args", fmt.Sprintf("%v", namedValueToLabels(args)))
}
if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
} }
labels := []string{labelMethod, "ExecContext", labelQuery, name} labels := []string{labelMethod, "ExecContext", labelQuery, name}
@@ -151,29 +164,29 @@ func (w *wrapperStmt) ExecContext(ctx context.Context, args []driver.NamedValue)
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "ExecContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "ExecContext", name, td, err)...)
} }
*/
return res, err return res, err
} }
values, err := namedValueToValue(args) values, err := namedValueToValue(args)
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error()) /*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "ExecContext", name, 0, err)...)
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "ExecContext", name, 0, err)...).Log(ctx, w.opts.LoggerLevel) }
} */
return nil, err return nil, err
} }
ts := time.Now() ts := time.Now()
@@ -182,19 +195,18 @@ func (w *wrapperStmt) ExecContext(ctx context.Context, args []driver.NamedValue)
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "ExecContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "ExecContext", name, td, err)...)
} }
*/
return res, err return res, err
} }
@@ -202,21 +214,21 @@ func (w *wrapperStmt) ExecContext(ctx context.Context, args []driver.NamedValue)
func (w *wrapperStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) { func (w *wrapperStmt) QueryContext(ctx context.Context, args []driver.NamedValue) (driver.Rows, error) {
var nctx context.Context var nctx context.Context
var span tracer.Span var span tracer.Span
if w.ctx != nil {
nctx, span = w.opts.Tracer.Start(w.ctx, "QueryContext")
} else {
nctx, span = w.opts.Tracer.Start(ctx, "QueryContext")
}
span.AddLabels("method", "QueryContext")
name := getQueryName(ctx) name := getQueryName(ctx)
if name != "" { if w.ctx != nil {
span.AddLabels("query", name) nctx, span = w.opts.Tracer.Start(w.ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} else { } else {
name = labelUnknown nctx, span = w.opts.Tracer.Start(ctx, "sdk.database", tracer.WithSpanKind(tracer.SpanKindClient))
} }
span.AddLabels("db.method", "QueryContext")
span.AddLabels("db.statement", name)
defer span.Finish() defer span.Finish()
if len(args) > 0 { if len(args) > 0 {
span.AddLabels("args", fmt.Sprintf("%v", namedValueToLabels(args))) span.AddLabels("db.args", fmt.Sprintf("%v", namedValueToLabels(args)))
}
if id, ok := ctx.Value(requestid.XRequestIDKey{}).(string); ok {
span.AddLabels("x-request-id", id)
} }
labels := []string{labelMethod, "QueryContext", labelQuery, name} labels := []string{labelMethod, "QueryContext", labelQuery, name}
if conn, ok := w.stmt.(driver.StmtQueryContext); ok { if conn, ok := w.stmt.(driver.StmtQueryContext); ok {
@@ -226,18 +238,18 @@ func (w *wrapperStmt) QueryContext(ctx context.Context, args []driver.NamedValue
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "QueryContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "QueryContext", name, td, err)...)
} }
*/
return rows, err return rows, err
} }
@@ -245,12 +257,12 @@ func (w *wrapperStmt) QueryContext(ctx context.Context, args []driver.NamedValue
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error()) /*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "QueryContext", name, 0, err)...)
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "QueryContext", name, 0, err)...).Log(ctx, w.opts.LoggerLevel) }
} */
return nil, err return nil, err
} }
ts := time.Now() ts := time.Now()
@@ -259,18 +271,17 @@ func (w *wrapperStmt) QueryContext(ctx context.Context, args []driver.NamedValue
te := td.Seconds() te := td.Seconds()
if err != nil { if err != nil {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelFailure)...).Inc()
span.AddLabels("error", true) span.SetStatus(tracer.SpanStatusError, err.Error())
span.AddLabels("err", err.Error())
} else { } else {
w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc() w.opts.Meter.Counter(meterRequestTotal, append(labels, labelStatus, labelSuccess)...).Inc()
} }
w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te) w.opts.Meter.Summary(meterRequestLatencyMicroseconds, labels...).Update(te)
w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te) w.opts.Meter.Histogram(meterRequestDurationSeconds, labels...).Update(te)
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(ctx, "QueryContext", name, td, err)...).Log(ctx, w.opts.LoggerLevel) w.opts.Logger.Log(ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(ctx, "QueryContext", name, td, err)...)
} }
*/
return rows, err return rows, err
} }

32
tx.go
View File

@@ -5,7 +5,7 @@ import (
"database/sql/driver" "database/sql/driver"
"time" "time"
"go.unistack.org/micro/v4/tracer" "go.unistack.org/micro/v3/tracer"
) )
var _ driver.Tx = (*wrapperTx)(nil) var _ driver.Tx = (*wrapperTx)(nil)
@@ -23,19 +23,18 @@ func (w *wrapperTx) Commit() error {
ts := time.Now() ts := time.Now()
err := w.tx.Commit() err := w.tx.Commit()
td := time.Since(ts) td := time.Since(ts)
_ = td
if w.span != nil { if w.span != nil {
if err != nil { if err != nil {
w.span.AddLabels("error", true) w.span.SetStatus(tracer.SpanStatusError, err.Error())
w.span.AddLabels("err", err.Error())
} }
w.span.Finish() w.span.Finish()
} }
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(w.ctx, "Commit", labelUnknown, td, err)...).Log(w.ctx, w.opts.LoggerLevel) w.opts.Logger.Log(w.ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(w.ctx, "Commit", getCallerName(), td, err)...)
} }
*/
w.ctx = nil w.ctx = nil
return err return err
@@ -46,19 +45,18 @@ func (w *wrapperTx) Rollback() error {
ts := time.Now() ts := time.Now()
err := w.tx.Rollback() err := w.tx.Rollback()
td := time.Since(ts) td := time.Since(ts)
_ = td
if w.span != nil { if w.span != nil {
if err != nil { if err != nil {
w.span.AddLabels("error", true) w.span.SetStatus(tracer.SpanStatusError, err.Error())
w.span.AddLabels("err", err.Error())
} }
w.span.Finish() w.span.Finish()
} }
/*
if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) { if w.opts.LoggerEnabled && w.opts.Logger.V(w.opts.LoggerLevel) {
w.opts.Logger.Fields(w.opts.LoggerObserver(w.ctx, "Rollback", labelUnknown, td, err)...).Log(w.ctx, w.opts.LoggerLevel) w.opts.Logger.Log(w.ctx, w.opts.LoggerLevel, w.opts.LoggerObserver(w.ctx, "Rollback", getCallerName(), td, err)...)
} }
*/
w.ctx = nil w.ctx = nil
return err return err

View File

@@ -4,12 +4,14 @@ import (
"database/sql/driver" "database/sql/driver"
) )
/*
func wrapDriver(d driver.Driver, opts Options) driver.Driver { func wrapDriver(d driver.Driver, opts Options) driver.Driver {
if _, ok := d.(driver.DriverContext); ok { if _, ok := d.(driver.DriverContext); ok {
return &wrapperDriver{driver: d, opts: opts} return &wrapperDriver{driver: d, opts: opts}
} }
return struct{ driver.Driver }{&wrapperDriver{driver: d, opts: opts}} return struct{ driver.Driver }{&wrapperDriver{driver: d, opts: opts}}
} }
*/
// WrapConn allows an existing driver.Conn to be wrapped. // WrapConn allows an existing driver.Conn to be wrapped.
func WrapConn(c driver.Conn, opts ...Option) driver.Conn { func WrapConn(c driver.Conn, opts ...Option) driver.Conn {

22230
wrap_gen.go

File diff suppressed because it is too large Load Diff