1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-22 04:50:54 +00:00

Merge pull request #4148 from flycash/fix/end2end

Fix prometheus and opentracing bug found in end2end tests
This commit is contained in:
Ming Deng 2020-08-11 16:33:54 +08:00 committed by GitHub
commit d326d74c34
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 256 additions and 196 deletions

View File

@ -15,13 +15,13 @@
package beego package beego
import ( import (
"crypto/tls"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"reflect" "reflect"
"runtime" "runtime"
"strings" "strings"
"crypto/tls"
"github.com/astaxie/beego/config" "github.com/astaxie/beego/config"
"github.com/astaxie/beego/context" "github.com/astaxie/beego/context"

View File

@ -27,15 +27,18 @@ type fakeConfigContainer struct {
func (c *fakeConfigContainer) getData(key string) string { func (c *fakeConfigContainer) getData(key string) string {
return c.data[strings.ToLower(key)] return c.data[strings.ToLower(key)]
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Set(key, val string) error { func (c *fakeConfigContainer) Set(key, val string) error {
c.data[strings.ToLower(key)] = val c.data[strings.ToLower(key)] = val
return nil return nil
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) String(key string) string { func (c *fakeConfigContainer) String(key string) string {
return c.getData(key) return c.getData(key)
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string { func (c *fakeConfigContainer) DefaultString(key string, defaultval string) string {
v := c.String(key) v := c.String(key)
@ -44,6 +47,7 @@ func (c *fakeConfigContainer) DefaultString(key string, defaultval string) strin
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Strings(key string) []string { func (c *fakeConfigContainer) Strings(key string) []string {
v := c.String(key) v := c.String(key)
@ -52,6 +56,7 @@ func (c *fakeConfigContainer) Strings(key string) []string {
} }
return strings.Split(v, ";") return strings.Split(v, ";")
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string { func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []string {
v := c.Strings(key) v := c.Strings(key)
@ -60,10 +65,12 @@ func (c *fakeConfigContainer) DefaultStrings(key string, defaultval []string) []
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Int(key string) (int, error) { func (c *fakeConfigContainer) Int(key string) (int, error) {
return strconv.Atoi(c.getData(key)) return strconv.Atoi(c.getData(key))
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int { func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
v, err := c.Int(key) v, err := c.Int(key)
@ -72,10 +79,12 @@ func (c *fakeConfigContainer) DefaultInt(key string, defaultval int) int {
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Int64(key string) (int64, error) { func (c *fakeConfigContainer) Int64(key string) (int64, error) {
return strconv.ParseInt(c.getData(key), 10, 64) return strconv.ParseInt(c.getData(key), 10, 64)
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 { func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
v, err := c.Int64(key) v, err := c.Int64(key)
@ -84,10 +93,12 @@ func (c *fakeConfigContainer) DefaultInt64(key string, defaultval int64) int64 {
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Bool(key string) (bool, error) { func (c *fakeConfigContainer) Bool(key string) (bool, error) {
return ParseBool(c.getData(key)) return ParseBool(c.getData(key))
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool { func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
v, err := c.Bool(key) v, err := c.Bool(key)
@ -96,10 +107,12 @@ func (c *fakeConfigContainer) DefaultBool(key string, defaultval bool) bool {
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) Float(key string) (float64, error) { func (c *fakeConfigContainer) Float(key string) (float64, error) {
return strconv.ParseFloat(c.getData(key), 64) return strconv.ParseFloat(c.getData(key), 64)
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 { func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float64 {
v, err := c.Float(key) v, err := c.Float(key)
@ -108,6 +121,7 @@ func (c *fakeConfigContainer) DefaultFloat(key string, defaultval float64) float
} }
return v return v
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) DIY(key string) (interface{}, error) { func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
if v, ok := c.data[strings.ToLower(key)]; ok { if v, ok := c.data[strings.ToLower(key)]; ok {
@ -115,10 +129,12 @@ func (c *fakeConfigContainer) DIY(key string) (interface{}, error) {
} }
return nil, errors.New("key not find") return nil, errors.New("key not find")
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) { func (c *fakeConfigContainer) GetSection(section string) (map[string]string, error) {
return nil, errors.New("not implement in the fakeConfigContainer") return nil, errors.New("not implement in the fakeConfigContainer")
} }
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
func (c *fakeConfigContainer) SaveConfigFile(filename string) error { func (c *fakeConfigContainer) SaveConfigFile(filename string) error {
return errors.New("not implement in the fakeConfigContainer") return errors.New("not implement in the fakeConfigContainer")

View File

@ -58,7 +58,6 @@ func (output *BeegoOutput) Clear() {
output.Status = 0 output.Status = 0
} }
// Header sets response header item string via given key. // Header sets response header item string via given key.
func (output *BeegoOutput) Header(key, val string) { func (output *BeegoOutput) Header(key, val string) {
output.Context.ResponseWriter.Header().Set(key, val) output.Context.ResponseWriter.Header().Set(key, val)

4
go.sum
View File

@ -185,6 +185,7 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -219,6 +220,9 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c h1:FodBYPZKH5tAN2O60HlglMwXGAeV/4k+NKbli79M/2c=
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=

View File

@ -6,10 +6,11 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"reflect"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/pkg/toolbox" "github.com/astaxie/beego/pkg/toolbox"
) )
@ -230,10 +231,19 @@ func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
t.Errorf("invalid response map length: got %d want %d", t.Errorf("invalid response map length: got %d want %d",
len(decodedResponseBody), len(expectedResponseBody)) len(decodedResponseBody), len(expectedResponseBody))
} }
assert.Equal(t, len(expectedResponseBody), len(decodedResponseBody))
assert.Equal(t, 2, len(decodedResponseBody))
if !reflect.DeepEqual(decodedResponseBody, expectedResponseBody) { var database, cache map[string]interface{}
t.Errorf("handler returned unexpected body: got %v want %v", if decodedResponseBody[0]["message"] == "database" {
decodedResponseBody, expectedResponseBody) database = decodedResponseBody[0]
cache = decodedResponseBody[1]
} else {
database = decodedResponseBody[1]
cache = decodedResponseBody[0]
} }
assert.Equal(t, expectedResponseBody[0], database)
assert.Equal(t, expectedResponseBody[1], cache)
} }

View File

@ -498,6 +498,7 @@ func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *A
// InsertFilterChain adds a FilterFunc built by filterChain. // InsertFilterChain adds a FilterFunc built by filterChain.
// This filter will be executed before all filters. // This filter will be executed before all filters.
// the filter's behavior is like stack
func InsertFilterChain(pattern string, filterChain FilterChain, params ...bool) *App { func InsertFilterChain(pattern string, filterChain FilterChain, params ...bool) *App {
BeeApp.Handlers.InsertFilterChain(pattern, filterChain, params...) BeeApp.Handlers.InsertFilterChain(pattern, filterChain, params...)
return BeeApp return BeeApp

View File

@ -33,6 +33,7 @@ type FilterFunc func(ctx *context.Context)
// when a request with a matching URL arrives. // when a request with a matching URL arrives.
type FilterRouter struct { type FilterRouter struct {
filterFunc FilterFunc filterFunc FilterFunc
next *FilterRouter
tree *Tree tree *Tree
pattern string pattern string
returnOnOutput bool returnOnOutput bool
@ -81,6 +82,8 @@ func (f *FilterRouter) filter(ctx *context.Context, urlPath string, preFilterPar
ctx.Input.SetParam(k, v) ctx.Input.SetParam(k, v)
} }
} }
} else if f.next != nil {
return f.next.filter(ctx, urlPath, preFilterParams)
} }
if f.returnOnOutput && ctx.ResponseWriter.Started { if f.returnOnOutput && ctx.ResponseWriter.Started {
return true, true return true, true

View File

@ -39,7 +39,6 @@ func TestControllerRegister_InsertFilterChain(t *testing.T) {
ctx.Output.Body([]byte("hello")) ctx.Output.Body([]byte("hello"))
}) })
r, _ := http.NewRequest("GET", "/chain/user", nil) r, _ := http.NewRequest("GET", "/chain/user", nil)
w := httptest.NewRecorder() w := httptest.NewRecorder()

View File

@ -17,14 +17,11 @@ package opentracing
import ( import (
"context" "context"
"net/http" "net/http"
"strconv"
"github.com/astaxie/beego/pkg/httplib"
logKit "github.com/go-kit/kit/log" logKit "github.com/go-kit/kit/log"
opentracingKit "github.com/go-kit/kit/tracing/opentracing" opentracingKit "github.com/go-kit/kit/tracing/opentracing"
"github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/log"
"github.com/astaxie/beego/pkg/httplib"
) )
type FilterChainBuilder struct { type FilterChainBuilder struct {
@ -38,14 +35,8 @@ func (builder *FilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filt
return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) { return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
method := req.GetRequest().Method method := req.GetRequest().Method
host := req.GetRequest().URL.Host
path := req.GetRequest().URL.Path
proto := req.GetRequest().Proto operationName := method + "#" + req.GetRequest().URL.String()
scheme := req.GetRequest().URL.Scheme
operationName := host + path + "#" + method
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName) span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
defer span.Finish() defer span.Finish()
@ -54,21 +45,24 @@ func (builder *FilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filt
resp, err := next(spanCtx, req) resp, err := next(spanCtx, req)
if resp != nil { if resp != nil {
span.SetTag("status", strconv.Itoa(resp.StatusCode)) span.SetTag("http.status_code", resp.StatusCode)
} }
span.SetTag("http.method", method)
span.SetTag("method", method) span.SetTag("peer.hostname", req.GetRequest().URL.Host)
span.SetTag("host", host) span.SetTag("http.url", req.GetRequest().URL.String())
span.SetTag("path", path) span.SetTag("http.scheme", req.GetRequest().URL.Scheme)
span.SetTag("proto", proto) span.SetTag("span.kind", "client")
span.SetTag("scheme", scheme) span.SetTag("component", "beego")
span.LogFields(log.String("url", req.GetRequest().URL.String()))
if err != nil { if err != nil {
span.LogFields(log.String("error", err.Error())) span.SetTag("error", true)
span.SetTag("message", err.Error())
} else if resp != nil && !(resp.StatusCode < 300 && resp.StatusCode >= 200) {
span.SetTag("error", true)
} }
span.SetTag("peer.address", req.GetRequest().RemoteAddr)
span.SetTag("http.proto", req.GetRequest().Proto)
if builder.CustomSpanFunc != nil { if builder.CustomSpanFunc != nil {
builder.CustomSpanFunc(span, ctx, req, resp, err) builder.CustomSpanFunc(span, ctx, req, resp, err)
} }

View File

@ -63,11 +63,13 @@ func (builder *FilterChainBuilder) report(startTime time.Time, endTime time.Time
host := req.GetRequest().URL.Host host := req.GetRequest().URL.Host
path := req.GetRequest().URL.Path path := req.GetRequest().URL.Path
status := resp.StatusCode status := -1
if resp != nil {
status = resp.StatusCode
}
dur := int(endTime.Sub(startTime) / time.Millisecond) dur := int(endTime.Sub(startTime) / time.Millisecond)
builder.summaryVec.WithLabelValues(proto, scheme, method, host, path, builder.summaryVec.WithLabelValues(proto, scheme, method, host, path,
strconv.Itoa(status), strconv.Itoa(dur), strconv.FormatBool(err == nil)) strconv.Itoa(status), strconv.Itoa(dur), strconv.FormatBool(err == nil))
} }

View File

@ -358,7 +358,7 @@ func addAliasWthDB(aliasName, driverName string, db *sql.DB, params ...common.KV
return al, nil return al, nil
} }
func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.KV)(*alias, error){ func newAliasWithDb(aliasName, driverName string, db *sql.DB, params ...common.KV) (*alias, error) {
kvs := common.NewKVs(params...) kvs := common.NewKVs(params...)
var stmtCache *lru.Cache var stmtCache *lru.Cache
@ -430,7 +430,6 @@ func RegisterDataBase(aliasName, driverName, dataSource string, params ...common
al *alias al *alias
) )
db, err = sql.Open(driverName, dataSource) db, err = sql.Open(driverName, dataSource)
if err != nil { if err != nil {
err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error()) err = fmt.Errorf("register db `%s`, %s", aliasName, err.Error())

View File

@ -76,7 +76,6 @@ func TestRegisterDataBase_MaxStmtCacheSize841(t *testing.T) {
assert.Equal(t, al.DB.stmtDecoratorsLimit, 841) assert.Equal(t, al.DB.stmtDecoratorsLimit, 841)
} }
func TestDBCache(t *testing.T) { func TestDBCache(t *testing.T) {
dataBaseCache.add("test1", &alias{}) dataBaseCache.add("test1", &alias{})
dataBaseCache.add("default", &alias{}) dataBaseCache.add("default", &alias{})

View File

@ -27,6 +27,7 @@ import (
var _ Ormer = new(DoNothingOrm) var _ Ormer = new(DoNothingOrm)
type DoNothingOrm struct { type DoNothingOrm struct {
} }
func (d *DoNothingOrm) Read(md interface{}, cols ...string) error { func (d *DoNothingOrm) Read(md interface{}, cols ...string) error {
@ -149,19 +150,19 @@ func (d *DoNothingOrm) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOpti
return nil, nil return nil, nil
} }
func (d *DoNothingOrm) DoTx(task func(txOrm TxOrmer) error) error { func (d *DoNothingOrm) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
return nil return nil
} }
func (d *DoNothingOrm) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error { func (d *DoNothingOrm) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
return nil return nil
} }
func (d *DoNothingOrm) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (d *DoNothingOrm) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
return nil return nil
} }
func (d *DoNothingOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (d *DoNothingOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
return nil return nil
} }

View File

@ -22,7 +22,7 @@ import (
// don't forget to call next(...) inside your Filter // don't forget to call next(...) inside your Filter
type FilterChain func(next Filter) Filter type FilterChain func(next Filter) Filter
// Filter's behavior is a little big strang. // Filter's behavior is a little big strange.
// it's only be called when users call methods of Ormer // it's only be called when users call methods of Ormer
type Filter func(ctx context.Context, inv *Invocation) type Filter func(ctx context.Context, inv *Invocation)
@ -31,6 +31,6 @@ var globalFilterChains = make([]FilterChain, 0, 4)
// AddGlobalFilterChain adds a new FilterChain // AddGlobalFilterChain adds a new FilterChain
// All orm instances built after this invocation will use this filterChain, // All orm instances built after this invocation will use this filterChain,
// but instances built before this invocation will not be affected // but instances built before this invocation will not be affected
func AddGlobalFilterChain(filterChain FilterChain) { func AddGlobalFilterChain(filterChain ...FilterChain) {
globalFilterChains = append(globalFilterChains, filterChain) globalFilterChains = append(globalFilterChains, filterChain...)
} }

View File

@ -16,6 +16,7 @@ package opentracing
import ( import (
"context" "context"
"strings"
"github.com/opentracing/opentracing-go" "github.com/opentracing/opentracing-go"
@ -27,6 +28,8 @@ import (
// for example: // for example:
// if we want to trace QuerySetter // if we want to trace QuerySetter
// actually we trace invoking "QueryTable" and "QueryTableWithCtx" // actually we trace invoking "QueryTable" and "QueryTableWithCtx"
// the method Begin*, Commit and Rollback are ignored.
// When use using those methods, it means that they want to manager their transaction manually, so we won't handle them.
type FilterChainBuilder struct { type FilterChainBuilder struct {
// CustomSpanFunc users are able to custom their span // CustomSpanFunc users are able to custom their span
CustomSpanFunc func(span opentracing.Span, ctx context.Context, inv *orm.Invocation) CustomSpanFunc func(span opentracing.Span, ctx context.Context, inv *orm.Invocation)
@ -35,25 +38,34 @@ type FilterChainBuilder struct {
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter { func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
return func(ctx context.Context, inv *orm.Invocation) { return func(ctx context.Context, inv *orm.Invocation) {
operationName := builder.operationName(ctx, inv) operationName := builder.operationName(ctx, inv)
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName) if strings.HasPrefix(inv.Method, "Begin") || inv.Method == "Commit" || inv.Method == "Rollback" {
defer span.Finish() next(ctx, inv)
return
next(spanCtx, inv)
span.SetTag("Method", inv.Method)
span.SetTag("Table", inv.GetTableName())
span.SetTag("InsideTx", inv.InsideTx)
span.SetTag("TxName", spanCtx.Value(orm.TxNameKey))
if builder.CustomSpanFunc != nil {
builder.CustomSpanFunc(span, spanCtx, inv)
} }
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
defer span.Finish()
next(spanCtx, inv)
builder.buildSpan(span, spanCtx, inv)
}
}
func (builder *FilterChainBuilder) buildSpan(span opentracing.Span, ctx context.Context, inv *orm.Invocation) {
span.SetTag("orm.method", inv.Method)
span.SetTag("orm.table", inv.GetTableName())
span.SetTag("orm.insideTx", inv.InsideTx)
span.SetTag("orm.txName", ctx.Value(orm.TxNameKey))
span.SetTag("span.kind", "client")
span.SetTag("component", "beego")
if builder.CustomSpanFunc != nil {
builder.CustomSpanFunc(span, ctx, inv)
} }
} }
func (builder *FilterChainBuilder) operationName(ctx context.Context, inv *orm.Invocation) string { func (builder *FilterChainBuilder) operationName(ctx context.Context, inv *orm.Invocation) string {
if n, ok := ctx.Value(orm.TxNameKey).(string); ok { if n, ok := ctx.Value(orm.TxNameKey).(string); ok {
return inv.Method + "#" + n return inv.Method + "#tx(" + n + ")"
} }
return inv.Method + "#" + inv.GetTableName() return inv.Method + "#" + inv.GetTableName()
} }

View File

@ -22,7 +22,12 @@ import (
"time" "time"
) )
const TxNameKey = "TxName" const (
TxNameKey = "TxName"
)
var _ Ormer = new(filterOrmDecorator)
var _ TxOrmer = new(filterOrmDecorator)
type filterOrmDecorator struct { type filterOrmDecorator struct {
ormer ormer
@ -41,7 +46,7 @@ func NewFilterOrmDecorator(delegate Ormer, filterChains ...FilterChain) Ormer {
ormer: delegate, ormer: delegate,
TxBeginner: delegate, TxBeginner: delegate,
root: func(ctx context.Context, inv *Invocation) { root: func(ctx context.Context, inv *Invocation) {
inv.execute() inv.execute(ctx)
}, },
} }
@ -77,8 +82,8 @@ func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, co
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
err = f.ormer.ReadWithCtx(ctx, md, cols...) err = f.ormer.ReadWithCtx(c, md, cols...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -99,8 +104,8 @@ func (f *filterOrmDecorator) ReadForUpdateWithCtx(ctx context.Context, md interf
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
err = f.ormer.ReadForUpdateWithCtx(ctx, md, cols...) err = f.ormer.ReadForUpdateWithCtx(c, md, cols...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -126,8 +131,8 @@ func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interfa
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
ok, res, err = f.ormer.ReadOrCreateWithCtx(ctx, md, col1, cols...) ok, res, err = f.ormer.ReadOrCreateWithCtx(c, md, col1, cols...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -152,8 +157,8 @@ func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interfac
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.LoadRelatedWithCtx(ctx, md, name, args...) res, err = f.ormer.LoadRelatedWithCtx(c, md, name, args...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -177,8 +182,8 @@ func (f *filterOrmDecorator) QueryM2MWithCtx(ctx context.Context, md interface{}
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res = f.ormer.QueryM2MWithCtx(ctx, md, name) res = f.ormer.QueryM2MWithCtx(c, md, name)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -215,8 +220,8 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
Md: md, Md: md,
mi: mi, mi: mi,
f: func() { f: func(c context.Context) {
res = f.ormer.QueryTableWithCtx(ctx, ptrStructOrTableName) res = f.ormer.QueryTableWithCtx(c, ptrStructOrTableName)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -231,7 +236,7 @@ func (f *filterOrmDecorator) DBStats() *sql.DBStats {
Method: "DBStats", Method: "DBStats",
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res = f.ormer.DBStats() res = f.ormer.DBStats()
}, },
} }
@ -256,8 +261,8 @@ func (f *filterOrmDecorator) InsertWithCtx(ctx context.Context, md interface{})
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.InsertWithCtx(ctx, md) res, err = f.ormer.InsertWithCtx(c, md)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -281,8 +286,8 @@ func (f *filterOrmDecorator) InsertOrUpdateWithCtx(ctx context.Context, md inter
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.InsertOrUpdateWithCtx(ctx, md, colConflitAndArgs...) res, err = f.ormer.InsertOrUpdateWithCtx(c, md, colConflitAndArgs...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -317,8 +322,8 @@ func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, m
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.InsertMultiWithCtx(ctx, bulk, mds) res, err = f.ormer.InsertMultiWithCtx(c, bulk, mds)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -342,8 +347,8 @@ func (f *filterOrmDecorator) UpdateWithCtx(ctx context.Context, md interface{},
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.UpdateWithCtx(ctx, md, cols...) res, err = f.ormer.UpdateWithCtx(c, md, cols...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -367,8 +372,8 @@ func (f *filterOrmDecorator) DeleteWithCtx(ctx context.Context, md interface{},
mi: mi, mi: mi,
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.ormer.DeleteWithCtx(ctx, md, cols...) res, err = f.ormer.DeleteWithCtx(c, md, cols...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -388,8 +393,8 @@ func (f *filterOrmDecorator) RawWithCtx(ctx context.Context, query string, args
Args: []interface{}{query, args}, Args: []interface{}{query, args},
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res = f.ormer.RawWithCtx(ctx, query, args...) res = f.ormer.RawWithCtx(c, query, args...)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -404,7 +409,7 @@ func (f *filterOrmDecorator) Driver() Driver {
Method: "Driver", Method: "Driver",
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res = f.ormer.Driver() res = f.ormer.Driver()
}, },
} }
@ -434,28 +439,28 @@ func (f *filterOrmDecorator) BeginWithCtxAndOpts(ctx context.Context, opts *sql.
Args: []interface{}{opts}, Args: []interface{}{opts},
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
f: func() { f: func(c context.Context) {
res, err = f.TxBeginner.BeginWithCtxAndOpts(ctx, opts) res, err = f.TxBeginner.BeginWithCtxAndOpts(c, opts)
res = NewFilterTxOrmDecorator(res, f.root, getTxNameFromCtx(ctx)) res = NewFilterTxOrmDecorator(res, f.root, getTxNameFromCtx(c))
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
return res, err return res, err
} }
func (f *filterOrmDecorator) DoTx(task func(txOrm TxOrmer) error) error { func (f *filterOrmDecorator) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
return f.DoTxWithCtxAndOpts(context.Background(), nil, task) return f.DoTxWithCtxAndOpts(context.Background(), nil, task)
} }
func (f *filterOrmDecorator) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error { func (f *filterOrmDecorator) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
return f.DoTxWithCtxAndOpts(ctx, nil, task) return f.DoTxWithCtxAndOpts(ctx, nil, task)
} }
func (f *filterOrmDecorator) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (f *filterOrmDecorator) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
return f.DoTxWithCtxAndOpts(context.Background(), opts, task) return f.DoTxWithCtxAndOpts(context.Background(), opts, task)
} }
func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
var ( var (
err error err error
) )
@ -466,8 +471,8 @@ func (f *filterOrmDecorator) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.T
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
TxName: getTxNameFromCtx(ctx), TxName: getTxNameFromCtx(ctx),
f: func() { f: func(c context.Context) {
err = f.TxBeginner.DoTxWithCtxAndOpts(ctx, opts, task) err = doTxTemplate(f, c, opts, task)
}, },
} }
f.root(ctx, inv) f.root(ctx, inv)
@ -484,7 +489,7 @@ func (f *filterOrmDecorator) Commit() error {
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
TxName: f.txName, TxName: f.txName,
f: func() { f: func(c context.Context) {
err = f.TxCommitter.Commit() err = f.TxCommitter.Commit()
}, },
} }
@ -502,7 +507,7 @@ func (f *filterOrmDecorator) Rollback() error {
InsideTx: f.insideTx, InsideTx: f.insideTx,
TxStartTime: f.txStartTime, TxStartTime: f.txStartTime,
TxName: f.txName, TxName: f.txName,
f: func() { f: func(c context.Context) {
err = f.TxCommitter.Rollback() err = f.TxCommitter.Rollback()
}, },
} }
@ -517,4 +522,3 @@ func getTxNameFromCtx(ctx context.Context) string {
} }
return txName return txName
} }

View File

@ -131,49 +131,49 @@ func TestFilterOrmDecorator_DoTx(t *testing.T) {
o := &filterMockOrm{} o := &filterMockOrm{}
od := NewFilterOrmDecorator(o, func(next Filter) Filter { od := NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) { return func(ctx context.Context, inv *Invocation) {
assert.Equal(t, "DoTxWithCtxAndOpts", inv.Method) if inv.Method == "DoTxWithCtxAndOpts" {
assert.Equal(t, 2, len(inv.Args)) assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "", inv.GetTableName()) assert.Equal(t, "", inv.GetTableName())
assert.False(t, inv.InsideTx) assert.False(t, inv.InsideTx)
}
next(ctx, inv) next(ctx, inv)
} }
}) })
err := od.DoTx(func(txOrm TxOrmer) error { err := od.DoTx(func(c context.Context, txOrm TxOrmer) error {
return errors.New("tx error") return nil
}) })
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, "tx error", err.Error())
err = od.DoTxWithCtx(context.Background(), func(txOrm TxOrmer) error { err = od.DoTxWithCtx(context.Background(), func(c context.Context, txOrm TxOrmer) error {
return errors.New("tx ctx error") return nil
}) })
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, "tx ctx error", err.Error())
err = od.DoTxWithOpts(nil, func(txOrm TxOrmer) error { err = od.DoTxWithOpts(nil, func(c context.Context, txOrm TxOrmer) error {
return errors.New("tx opts error") return nil
}) })
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, "tx opts error", err.Error())
od = NewFilterOrmDecorator(o, func(next Filter) Filter { od = NewFilterOrmDecorator(o, func(next Filter) Filter {
return func(ctx context.Context, inv *Invocation) { return func(ctx context.Context, inv *Invocation) {
assert.Equal(t, "DoTxWithCtxAndOpts", inv.Method) if inv.Method == "DoTxWithCtxAndOpts" {
assert.Equal(t, 2, len(inv.Args)) assert.Equal(t, 2, len(inv.Args))
assert.Equal(t, "", inv.GetTableName()) assert.Equal(t, "", inv.GetTableName())
assert.Equal(t, "do tx name", inv.TxName) assert.Equal(t, "do tx name", inv.TxName)
assert.False(t, inv.InsideTx) assert.False(t, inv.InsideTx)
}
next(ctx, inv) next(ctx, inv)
} }
}) })
ctx := context.WithValue(context.Background(), TxNameKey, "do tx name") ctx := context.WithValue(context.Background(), TxNameKey, "do tx name")
err = od.DoTxWithCtxAndOpts(ctx, nil, func(txOrm TxOrmer) error { err = od.DoTxWithCtxAndOpts(ctx, nil, func(c context.Context, txOrm TxOrmer) error {
return errors.New("tx ctx opts error") return nil
}) })
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, "tx ctx opts error", err.Error())
} }
func TestFilterOrmDecorator_Driver(t *testing.T) { func TestFilterOrmDecorator_Driver(t *testing.T) {
@ -348,6 +348,8 @@ func TestFilterOrmDecorator_ReadOrCreate(t *testing.T) {
assert.Equal(t, int64(13), i) assert.Equal(t, int64(13), i)
} }
var _ Ormer = new(filterMockOrm)
// filterMockOrm is only used in this test file // filterMockOrm is only used in this test file
type filterMockOrm struct { type filterMockOrm struct {
DoNothingOrm DoNothingOrm
@ -377,8 +379,8 @@ func (f *filterMockOrm) InsertWithCtx(ctx context.Context, md interface{}) (int6
return 100, errors.New("insert error") return 100, errors.New("insert error")
} }
func (f *filterMockOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (f *filterMockOrm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(c context.Context, txOrm TxOrmer) error) error {
return task(nil) return task(ctx, nil)
} }
func (f *filterMockOrm) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) { func (f *filterMockOrm) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {

View File

@ -28,4 +28,5 @@ func TestAddGlobalFilterChain(t *testing.T) {
} }
}) })
assert.Equal(t, 1, len(globalFilterChains)) assert.Equal(t, 1, len(globalFilterChains))
globalFilterChains = nil
} }

View File

@ -15,6 +15,7 @@
package orm package orm
import ( import (
"context"
"time" "time"
) )
@ -28,7 +29,7 @@ type Invocation struct {
mi *modelInfo mi *modelInfo
// f is the Orm operation // f is the Orm operation
f func() f func(ctx context.Context)
// insideTx indicates whether this is inside a transaction // insideTx indicates whether this is inside a transaction
InsideTx bool InsideTx bool
@ -37,12 +38,12 @@ type Invocation struct {
} }
func (inv *Invocation) GetTableName() string { func (inv *Invocation) GetTableName() string {
if inv.mi != nil{ if inv.mi != nil {
return inv.mi.table return inv.mi.table
} }
return "" return ""
} }
func (inv *Invocation) execute() { func (inv *Invocation) execute(ctx context.Context) {
inv.f() inv.f(ctx)
} }

View File

@ -28,7 +28,6 @@ import (
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
// As tidb can't use go get, so disable the tidb testing now // As tidb can't use go get, so disable the tidb testing now
// _ "github.com/pingcap/tidb" // _ "github.com/pingcap/tidb"
) )
// A slice string field. // A slice string field.

View File

@ -528,19 +528,24 @@ func (o *orm) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxO
return taskTxOrm, nil return taskTxOrm, nil
} }
func (o *orm) DoTx(task func(txOrm TxOrmer) error) error { func (o *orm) DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error {
return o.DoTxWithCtx(context.Background(), task) return o.DoTxWithCtx(context.Background(), task)
} }
func (o *orm) DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error { func (o *orm) DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error {
return o.DoTxWithCtxAndOpts(ctx, nil, task) return o.DoTxWithCtxAndOpts(ctx, nil, task)
} }
func (o *orm) DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (o *orm) DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
return o.DoTxWithCtxAndOpts(context.Background(), opts, task) return o.DoTxWithCtxAndOpts(context.Background(), opts, task)
} }
func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error { func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error {
return doTxTemplate(o, ctx, opts, task)
}
func doTxTemplate(o TxBeginner, ctx context.Context, opts *sql.TxOptions,
task func(ctx context.Context, txOrm TxOrmer) error) error {
_txOrm, err := o.BeginWithCtxAndOpts(ctx, opts) _txOrm, err := o.BeginWithCtxAndOpts(ctx, opts)
if err != nil { if err != nil {
return err return err
@ -559,9 +564,8 @@ func (o *orm) DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task
} }
} }
}() }()
var taskTxOrm = _txOrm var taskTxOrm = _txOrm
err = task(taskTxOrm) err = task(ctx, taskTxOrm)
panicked = false panicked = false
return err return err
} }
@ -588,18 +592,11 @@ func NewOrm() Ormer {
// NewOrmUsingDB create new orm with the name // NewOrmUsingDB create new orm with the name
func NewOrmUsingDB(aliasName string) Ormer { func NewOrmUsingDB(aliasName string) Ormer {
o := new(orm)
if al, ok := dataBaseCache.get(aliasName); ok { if al, ok := dataBaseCache.get(aliasName); ok {
o.alias = al return newDBWithAlias(al)
if Debug {
o.db = newDbQueryLog(al, al.DB)
} else {
o.db = al.DB
}
} else { } else {
panic(fmt.Errorf("<Ormer.Using> unknown db alias name `%s`", aliasName)) panic(fmt.Errorf("<Ormer.Using> unknown db alias name `%s`", aliasName))
} }
return o
} }
// NewOrmWithDB create a new ormer object with specify *sql.DB for query // NewOrmWithDB create a new ormer object with specify *sql.DB for query
@ -609,14 +606,21 @@ func NewOrmWithDB(driverName, aliasName string, db *sql.DB, params ...common.KV)
return nil, err return nil, err
} }
return newDBWithAlias(al), nil
}
func newDBWithAlias(al *alias) Ormer {
o := new(orm) o := new(orm)
o.alias = al o.alias = al
if Debug { if Debug {
o.db = newDbQueryLog(o.alias, db) o.db = newDbQueryLog(al, al.DB)
} else { } else {
o.db = db o.db = al.DB
} }
return o, nil if len(globalFilterChains) > 0 {
return NewFilterOrmDecorator(o, globalFilterChains...)
}
return o
} }

View File

@ -2523,5 +2523,3 @@ func TestInsertOrUpdate(t *testing.T) {
throwFailNow(t, AssertIs((((user2.Status+1)-1)*3)/3, test.Status)) throwFailNow(t, AssertIs((((user2.Status+1)-1)*3)/3, test.Status))
} }
} }

View File

@ -96,10 +96,10 @@ type TxBeginner interface {
BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error) BeginWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions) (TxOrmer, error)
//closure control transaction //closure control transaction
DoTx(task func(txOrm TxOrmer) error) error DoTx(task func(ctx context.Context, txOrm TxOrmer) error) error
DoTxWithCtx(ctx context.Context, task func(txOrm TxOrmer) error) error DoTxWithCtx(ctx context.Context, task func(ctx context.Context, txOrm TxOrmer) error) error
DoTxWithOpts(opts *sql.TxOptions, task func(txOrm TxOrmer) error) error DoTxWithOpts(opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(txOrm TxOrmer) error) error DoTxWithCtxAndOpts(ctx context.Context, opts *sql.TxOptions, task func(ctx context.Context, txOrm TxOrmer) error) error
} }
type TxCommitter interface { type TxCommitter interface {

View File

@ -468,12 +468,13 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter
// // do something // // do something
// } // }
// } // }
func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, params...bool) { func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, params ...bool) {
root := p.chainRoot root := p.chainRoot
filterFunc := chain(root.filterFunc) filterFunc := chain(root.filterFunc)
p.chainRoot = newFilterRouter(pattern, BConfig.RouterCaseSensitive, filterFunc, params...) p.chainRoot = newFilterRouter(pattern, BConfig.RouterCaseSensitive, filterFunc, params...)
} p.chainRoot.next = root
}
// add Filter into // add Filter into
func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) { func (p *ControllerRegister) insertFilterRouter(pos int, mr *FilterRouter) (err error) {

View File

@ -57,7 +57,7 @@ func TestFileProvider_SessionExist(t *testing.T) {
_ = fp.SessionInit(180, sessionPath) _ = fp.SessionInit(180, sessionPath)
exists, err := fp.SessionExist(sid) exists, err := fp.SessionExist(sid)
if err != nil{ if err != nil {
t.Error(err) t.Error(err)
} }
if exists { if exists {

View File

@ -31,7 +31,6 @@ type FilterChainBuilder struct {
CustomSpanFunc func(span opentracing.Span, ctx *beegoCtx.Context) CustomSpanFunc func(span opentracing.Span, ctx *beegoCtx.Context)
} }
func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc { func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc {
return func(ctx *beegoCtx.Context) { return func(ctx *beegoCtx.Context) {
var ( var (
@ -55,9 +54,21 @@ func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.Filt
next(ctx) next(ctx)
// if you think we need to do more things, feel free to create an issue to tell us // if you think we need to do more things, feel free to create an issue to tell us
span.SetTag("status", ctx.Output.Status) span.SetTag("http.status_code", ctx.ResponseWriter.Status)
span.SetTag("method", ctx.Input.Method()) span.SetTag("http.method", ctx.Input.Method())
span.SetTag("route", ctx.Input.GetData("RouterPattern")) span.SetTag("peer.hostname", ctx.Request.Host)
span.SetTag("http.url", ctx.Request.URL.String())
span.SetTag("http.scheme", ctx.Request.URL.Scheme)
span.SetTag("span.kind", "server")
span.SetTag("component", "beego")
if ctx.Output.IsServerError() || ctx.Output.IsClientError() {
span.SetTag("error", true)
}
span.SetTag("peer.address", ctx.Request.RemoteAddr)
span.SetTag("http.proto", ctx.Request.Proto)
span.SetTag("beego.route", ctx.Input.GetData("RouterPattern"))
if builder.CustomSpanFunc != nil { if builder.CustomSpanFunc != nil {
builder.CustomSpanFunc(span, ctx) builder.CustomSpanFunc(span, ctx)
} }
@ -70,7 +81,7 @@ func (builder *FilterChainBuilder) operationName(ctx *beegoCtx.Context) string {
// TODO, if we support multiple servers, this need to be changed // TODO, if we support multiple servers, this need to be changed
route, found := beego.BeeApp.Handlers.FindRouter(ctx) route, found := beego.BeeApp.Handlers.FindRouter(ctx)
if found { if found {
operationName = route.GetPattern() operationName = ctx.Input.Method() + "#" + route.GetPattern()
} }
return operationName return operationName
} }