mirror of
https://github.com/astaxie/beego.git
synced 2024-11-24 05:50:54 +00:00
Support opentracing filter for Orm
This commit is contained in:
parent
26b016a3a4
commit
dec98f004c
@ -18,8 +18,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// FilterChain is used to build a 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.
|
||||||
|
// 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)
|
||||||
|
|
||||||
var globalFilterChains = make([]FilterChain, 0, 4)
|
var globalFilterChains = make([]FilterChain, 0, 4)
|
||||||
|
59
pkg/orm/filter/opentracing/filter.go
Normal file
59
pkg/orm/filter/opentracing/filter.go
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// Copyright 2020 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package opentracing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/opentracing/opentracing-go"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/pkg/orm"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FilterChainBuilder provides an extension point
|
||||||
|
// this Filter's behavior looks a little bit strange
|
||||||
|
// for example:
|
||||||
|
// if we want to trace QuerySetter
|
||||||
|
// actually we trace invoking "QueryTable" and "QueryTableWithCtx"
|
||||||
|
type FilterChainBuilder struct {
|
||||||
|
// CustomSpanFunc users are able to custom their span
|
||||||
|
CustomSpanFunc func(span opentracing.Span, ctx context.Context, inv *orm.Invocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
|
||||||
|
return func(ctx context.Context, inv *orm.Invocation) {
|
||||||
|
operationName := builder.operationName(ctx, inv)
|
||||||
|
span, spanCtx := opentracing.StartSpanFromContext(ctx, operationName)
|
||||||
|
defer span.Finish()
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (builder *FilterChainBuilder) operationName(ctx context.Context, inv *orm.Invocation) string {
|
||||||
|
if n, ok := ctx.Value(orm.TxNameKey).(string); ok {
|
||||||
|
return inv.Method + "#" + n
|
||||||
|
}
|
||||||
|
return inv.Method + "#" + inv.GetTableName()
|
||||||
|
}
|
43
pkg/orm/filter/opentracing/filter_test.go
Normal file
43
pkg/orm/filter/opentracing/filter_test.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2020 beego
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package opentracing
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/opentracing/opentracing-go"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/pkg/orm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilterChainBuilder_FilterChain(t *testing.T) {
|
||||||
|
next := func(ctx context.Context, inv *orm.Invocation) {
|
||||||
|
inv.TxName = "Hello"
|
||||||
|
}
|
||||||
|
|
||||||
|
builder := &FilterChainBuilder{
|
||||||
|
CustomSpanFunc: func(span opentracing.Span, ctx context.Context, inv *orm.Invocation) {
|
||||||
|
span.SetTag("hello", "hell")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
inv := &orm.Invocation{
|
||||||
|
Method: "Hello",
|
||||||
|
TxStartTime: time.Now(),
|
||||||
|
}
|
||||||
|
builder.FilterChain(next)(context.Background(), inv)
|
||||||
|
}
|
@ -29,6 +29,10 @@ import (
|
|||||||
// FilterChainBuilder is an extension point,
|
// FilterChainBuilder is an extension point,
|
||||||
// when we want to support some configuration,
|
// when we want to support some configuration,
|
||||||
// please use this structure
|
// please use this structure
|
||||||
|
// this Filter's behavior looks a little bit strange
|
||||||
|
// for example:
|
||||||
|
// if we want to records the metrics of QuerySetter
|
||||||
|
// actually we only records metrics of invoking "QueryTable" and "QueryTableWithCtx"
|
||||||
type FilterChainBuilder struct {
|
type FilterChainBuilder struct {
|
||||||
summaryVec prometheus.ObserverVec
|
summaryVec prometheus.ObserverVec
|
||||||
}
|
}
|
||||||
|
@ -30,22 +30,14 @@ type FilterChainBuilder struct {
|
|||||||
|
|
||||||
func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc {
|
func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.FilterFunc {
|
||||||
return func(ctx *context.Context) {
|
return func(ctx *context.Context) {
|
||||||
span := opentracing.SpanFromContext(ctx.Request.Context())
|
operationName := builder.operationName(ctx)
|
||||||
spanCtx := ctx.Request.Context()
|
|
||||||
if span == nil {
|
|
||||||
operationName := ctx.Input.URL()
|
|
||||||
// it means that there is not any span, so we create a span as the root span.
|
|
||||||
// TODO, if we support multiple servers, this need to be changed
|
|
||||||
route, found := beego.BeeApp.Handlers.FindRouter(ctx)
|
|
||||||
if found {
|
|
||||||
operationName = route.GetPattern()
|
|
||||||
}
|
|
||||||
span, spanCtx = opentracing.StartSpanFromContext(spanCtx, operationName)
|
|
||||||
newReq := ctx.Request.Clone(spanCtx)
|
|
||||||
ctx.Reset(ctx.ResponseWriter.ResponseWriter, newReq)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
span, spanCtx := opentracing.StartSpanFromContext(ctx.Request.Context(), operationName)
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
|
newReq := ctx.Request.Clone(spanCtx)
|
||||||
|
ctx.Reset(ctx.ResponseWriter.ResponseWriter, newReq)
|
||||||
|
|
||||||
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("status", ctx.Output.Status)
|
||||||
@ -56,3 +48,14 @@ func (builder *FilterChainBuilder) FilterChain(next beego.FilterFunc) beego.Filt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (builder *FilterChainBuilder) operationName(ctx *context.Context) string {
|
||||||
|
operationName := ctx.Input.URL()
|
||||||
|
// it means that there is not any span, so we create a span as the root span.
|
||||||
|
// TODO, if we support multiple servers, this need to be changed
|
||||||
|
route, found := beego.BeeApp.Handlers.FindRouter(ctx)
|
||||||
|
if found {
|
||||||
|
operationName = route.GetPattern()
|
||||||
|
}
|
||||||
|
return operationName
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user