1
0
mirror of https://github.com/astaxie/beego.git synced 2024-11-21 23:20: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

@ -16,15 +16,15 @@ package beego
var ( var (
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
BuildVersion string BuildVersion string
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
BuildGitRevision string BuildGitRevision string
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
BuildStatus string BuildStatus string
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
BuildTag string BuildTag string
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
BuildTime string BuildTime string
// Deprecated: using pkg/, we will delete this in v2.1.0 // Deprecated: using pkg/, we will delete this in v2.1.0
GoVersion string GoVersion string

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"
@ -163,7 +163,7 @@ func init() {
} }
appConfigPath = filepath.Join(WorkPath, "conf", filename) appConfigPath = filepath.Join(WorkPath, "conf", filename)
if configPath := os.Getenv("BEEGO_CONFIG_PATH"); configPath != "" { if configPath := os.Getenv("BEEGO_CONFIG_PATH"); configPath != "" {
appConfigPath = configPath appConfigPath = configPath
} }
if !utils.FileExists(appConfigPath) { if !utils.FileExists(appConfigPath) {
appConfigPath = filepath.Join(AppPath, "conf", filename) appConfigPath = filepath.Join(AppPath, "conf", filename)

View File

@ -51,9 +51,9 @@ import (
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
type Configer interface { type Configer interface {
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
Set(key, val string) error //support section::key type in given key when using ini type. Set(key, val string) error //support section::key type in given key when using ini type.
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. String(key string) string //support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
Strings(key string) []string //get string slice Strings(key string) []string //get string slice
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
@ -65,7 +65,7 @@ type Configer interface {
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
Float(key string) (float64, error) Float(key string) (float64, error)
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same. DefaultString(key string, defaultVal string) string // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0
DefaultStrings(key string, defaultVal []string) []string //get string slice DefaultStrings(key string, defaultVal []string) []string //get string slice
// Deprecated: using pkg/config, we will delete this in v2.1.0 // Deprecated: using pkg/config, we will delete this in v2.1.0

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

@ -1,4 +1,4 @@
// Copyright 2020 // Copyright 2020
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -111,4 +111,4 @@ func registerCommentRouter() error {
} }
return nil return nil
} }

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -40,4 +40,4 @@ func TestFilterChainBuilder_FilterChain(t *testing.T) {
TxStartTime: time.Now(), TxStartTime: time.Now(),
} }
builder.FilterChain(next)(context.Background(), inv) builder.FilterChain(next)(context.Background(), inv)
} }

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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)
}, },
} }
@ -59,7 +64,7 @@ func NewFilterTxOrmDecorator(delegate TxOrmer, root Filter, txName string) TxOrm
root: root, root: root,
insideTx: true, insideTx: true,
txStartTime: time.Now(), txStartTime: time.Now(),
txName: txName, txName: txName,
} }
return res return res
} }
@ -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)
@ -191,10 +196,10 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS
func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter { func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrTableName interface{}) QuerySeter {
var ( var (
res QuerySeter res QuerySeter
name string name string
md interface{} md interface{}
mi *modelInfo mi *modelInfo
) )
if table, ok := ptrStructOrTableName.(string); ok { if table, ok := ptrStructOrTableName.(string); ok {
@ -213,10 +218,10 @@ func (f *filterOrmDecorator) QueryTableWithCtx(ctx context.Context, ptrStructOrT
Args: []interface{}{ptrStructOrTableName}, Args: []interface{}{ptrStructOrTableName},
InsideTx: f.insideTx, InsideTx: f.insideTx,
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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -15,6 +15,7 @@
package orm package orm
import ( import (
"context"
"time" "time"
) )
@ -22,27 +23,27 @@ import (
type Invocation struct { type Invocation struct {
Method string Method string
// Md may be nil in some cases. It depends on method // Md may be nil in some cases. It depends on method
Md interface{} Md interface{}
// the args are all arguments except context.Context // the args are all arguments except context.Context
Args []interface{} Args []interface{}
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
TxStartTime time.Time TxStartTime time.Time
TxName string TxName string
} }
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

@ -1,4 +1,4 @@
// Copyright 2020 // Copyright 2020
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

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

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -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
} }

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
// Copyright 2020 beego // Copyright 2020 beego
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.