commit
fd15b2026b
@ -1,11 +1,14 @@
|
||||
# developing
|
||||
|
||||
- [Fix issue 4961, `leafInfo.match()` use `path.join()` to deal with `wildcardValues`, which may lead to cross directory risk ](https://github.com/beego/beego/pull/4964)
|
||||
- [Fix 4975: graceful server listen the specific address](https://github.com/beego/beego/pull/4979)
|
||||
- [Fix 4976: make admin serve HTTP only](https://github.com/beego/beego/pull/4980)
|
||||
# v2.0.3
|
||||
- [upgrade redisgo to v1.8.8](https://github.com/beego/beego/pull/4872)
|
||||
- [fix prometheus CVE-2022-21698](https://github.com/beego/beego/pull/4878)
|
||||
- [upgrade to Go 1.18](https://github.com/beego/beego/pull/4896)
|
||||
- [make `PatternLogFormatter` handling the arguments](https://github.com/beego/beego/pull/4914/files)
|
||||
- [Add httplib OpenTelemetry Filter](https://github.com/beego/beego/pull/4888, https://github.com/beego/beego/pull/4915)
|
||||
- [Add orm OpenTelemetry Filter](https://github.com/beego/beego/issues/4944)
|
||||
- [Support NewBeegoRequestWithCtx in httplib](https://github.com/beego/beego/pull/4895)
|
||||
- [Support lifecycle callback](https://github.com/beego/beego/pull/4918)
|
||||
- [Append column comments to create table sentence when using postgres](https://github.com/beego/beego/pull/4940)
|
||||
|
||||
90
client/orm/filter/opentelemetry/filter.go
Normal file
90
client/orm/filter/opentelemetry/filter.go
Normal file
@ -0,0 +1,90 @@
|
||||
// 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 opentelemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
type (
|
||||
CustomSpanFunc func(ctx context.Context, span otelTrace.Span, inv *orm.Invocation)
|
||||
FilterChainOption func(fcv *FilterChainBuilder)
|
||||
)
|
||||
|
||||
// FilterChainBuilder provides an opentelemtry Filter
|
||||
type FilterChainBuilder struct {
|
||||
// customSpanFunc users are able to custom their span
|
||||
customSpanFunc CustomSpanFunc
|
||||
}
|
||||
|
||||
func NewFilterChainBuilder(options ...FilterChainOption) *FilterChainBuilder {
|
||||
fcb := &FilterChainBuilder{}
|
||||
for _, o := range options {
|
||||
o(fcb)
|
||||
}
|
||||
return fcb
|
||||
}
|
||||
|
||||
// WithCustomSpanFunc add function to custom span
|
||||
func WithCustomSpanFunc(customSpanFunc CustomSpanFunc) FilterChainOption {
|
||||
return func(fcv *FilterChainBuilder) {
|
||||
fcv.customSpanFunc = customSpanFunc
|
||||
}
|
||||
}
|
||||
|
||||
// FilterChain traces invocation with opentelemetry
|
||||
// Unless invocation.Method is Begin*, Commit or Rollback
|
||||
func (builder *FilterChainBuilder) FilterChain(next orm.Filter) orm.Filter {
|
||||
return func(ctx context.Context, inv *orm.Invocation) []interface{} {
|
||||
if strings.HasPrefix(inv.Method, "Begin") || inv.Method == "Commit" || inv.Method == "Rollback" {
|
||||
return next(ctx, inv)
|
||||
}
|
||||
spanCtx, span := otel.Tracer("beego_orm").Start(ctx, invOperationName(ctx, inv))
|
||||
defer span.End()
|
||||
|
||||
res := next(spanCtx, inv)
|
||||
builder.buildSpan(spanCtx, span, inv)
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
// buildSpan add default span attributes and custom attributes with customSpanFunc
|
||||
func (builder *FilterChainBuilder) buildSpan(ctx context.Context, span otelTrace.Span, inv *orm.Invocation) {
|
||||
span.SetAttributes(attribute.String("orm.method", inv.Method))
|
||||
span.SetAttributes(attribute.String("orm.table", inv.GetTableName()))
|
||||
span.SetAttributes(attribute.Bool("orm.insideTx", inv.InsideTx))
|
||||
v, _ := ctx.Value(orm.TxNameKey).(string)
|
||||
span.SetAttributes(attribute.String("orm.txName", v))
|
||||
span.SetAttributes(attribute.String("span.kind", "client"))
|
||||
span.SetAttributes(attribute.String("component", "beego"))
|
||||
|
||||
if builder.customSpanFunc != nil {
|
||||
builder.customSpanFunc(ctx,span, inv)
|
||||
}
|
||||
}
|
||||
|
||||
func invOperationName(ctx context.Context, inv *orm.Invocation) string {
|
||||
if n, ok := ctx.Value(orm.TxNameKey).(string); ok {
|
||||
return inv.Method + "#tx(" + n + ")"
|
||||
}
|
||||
return inv.Method + "#" + inv.GetTableName()
|
||||
}
|
||||
61
client/orm/filter/opentelemetry/filter_test.go
Normal file
61
client/orm/filter/opentelemetry/filter_test.go
Normal file
@ -0,0 +1,61 @@
|
||||
// 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 opentelemetry
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
|
||||
"go.opentelemetry.io/otel/sdk/trace"
|
||||
otelTrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/beego/beego/v2/client/orm"
|
||||
)
|
||||
|
||||
func TestFilterChainBuilderFilterChain(t *testing.T) {
|
||||
// Init Trace
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
exp, err := stdouttrace.New(stdouttrace.WithWriter(buf))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
tp := trace.NewTracerProvider(trace.WithBatcher(exp))
|
||||
otel.SetTracerProvider(tp)
|
||||
|
||||
// Build FilterChain
|
||||
csf := func(ctx context.Context, span otelTrace.Span, inv *orm.Invocation) {
|
||||
span.SetAttributes(attribute.String("hello", "work"))
|
||||
}
|
||||
builder := NewFilterChainBuilder(WithCustomSpanFunc(csf))
|
||||
|
||||
inv := &orm.Invocation{Method: "Hello"}
|
||||
next := func(ctx context.Context, inv *orm.Invocation) []interface{} { return nil }
|
||||
|
||||
builder.FilterChain(next)(context.Background(), inv)
|
||||
|
||||
// Close tp
|
||||
err = tp.Shutdown(context.Background())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// Assert opentelemetry span name
|
||||
assert.Equal(t, "Hello#", string(buf.Bytes()[9:15]))
|
||||
}
|
||||
2
go.mod
2
go.mod
@ -31,6 +31,8 @@ require (
|
||||
github.com/stretchr/testify v1.7.1
|
||||
go.etcd.io/etcd/client/v3 v3.5.4
|
||||
go.opentelemetry.io/otel v1.7.0
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0
|
||||
go.opentelemetry.io/otel/sdk v1.7.0
|
||||
go.opentelemetry.io/otel/trace v1.7.0
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
||||
google.golang.org/grpc v1.38.0
|
||||
|
||||
5
go.sum
5
go.sum
@ -468,6 +468,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
|
||||
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0 h1:8hPcgCg0rUJiKE6VWahRvjgLUrNl7rW2hffUEPKXVEM=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.7.0/go.mod h1:K4GDXPY6TjUiwbOh+DkKaEdCF8y+lvMoM6SeAPyfCCM=
|
||||
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
|
||||
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
|
||||
go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
|
||||
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
@ -627,6 +631,7 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
|
||||
|
||||
@ -101,6 +101,7 @@ func registerAdmin() error {
|
||||
|
||||
// copy config to avoid conflict
|
||||
adminCfg := *BConfig
|
||||
adminCfg.Listen.EnableHTTPS = false
|
||||
beeAdminApp = &adminApp{
|
||||
HttpServer: NewHttpServerWithCfg(&adminCfg),
|
||||
}
|
||||
|
||||
@ -169,7 +169,6 @@ func (srv *Server) ServeTLS(ln net.Listener) error {
|
||||
}
|
||||
|
||||
go srv.handleSignals()
|
||||
log.Println(os.Getpid(), srv.Addr)
|
||||
return srv.internalServe(ln)
|
||||
}
|
||||
|
||||
|
||||
@ -215,7 +215,8 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
|
||||
if app.Cfg.Listen.ListenTCP4 {
|
||||
server.Network = "tcp4"
|
||||
}
|
||||
ln, err := net.Listen(server.Network, app.Server.Addr)
|
||||
ln, err := net.Listen(server.Network, server.Addr)
|
||||
logs.Info("graceful http server Running on http://%s", server.Addr)
|
||||
if err != nil {
|
||||
logs.Critical("Listen for HTTP[graceful mode]: ", err)
|
||||
endRunning <- true
|
||||
|
||||
@ -282,6 +282,8 @@ func (t *Tree) addseg(segments []string, route interface{}, wildcards []string,
|
||||
|
||||
// Match router to runObject & params
|
||||
func (t *Tree) Match(pattern string, ctx *context.Context) (runObject interface{}) {
|
||||
// fix issue 4961, deal with "./ ../ //"
|
||||
pattern = path.Clean(pattern)
|
||||
if pattern == "" || pattern[0] != '/' {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -68,7 +68,8 @@ func init() {
|
||||
matchTestInfo("/", "/", nil),
|
||||
matchTestInfo("/customer/login", "/customer/login", nil),
|
||||
matchTestInfo("/customer/login", "/customer/login.json", map[string]string{":ext": "json"}),
|
||||
matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}),
|
||||
// This case need to be modified when fix issue 4961, "//" will be replaced with "/" and last "/" will be deleted before route.
|
||||
matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http:/customer/123"}),
|
||||
matchTestInfo("/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}),
|
||||
matchTestInfo("/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}),
|
||||
matchTestInfo("/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}),
|
||||
@ -125,6 +126,14 @@ func init() {
|
||||
// test for fix of issue 4946
|
||||
notMatchTestInfo("/suffix/:name", "/suffix.html/suffix.html"),
|
||||
matchTestInfo("/suffix/:id/name", "/suffix/1234/name.html", map[string]string{":id": "1234", ":ext": "html"}),
|
||||
// test for fix of issue 4961,path.join() lead to cross directory risk
|
||||
matchTestInfo("/book1/:name/fixPath1/*.*", "/book1/name1/fixPath1/mybook/../mybook2.txt", map[string]string{":name": "name1", ":path": "mybook2"}),
|
||||
notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/name1/fixPath1/mybook/../../mybook2.txt"),
|
||||
notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/../fixPath1/mybook/../././////evil.txt"),
|
||||
notMatchTestInfo("/book1/:name/fixPath1/*.*", "/book1/./fixPath1/mybook/../././////evil.txt"),
|
||||
notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"),
|
||||
notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"),
|
||||
notMatchTestInfo("/book2/:type:string/fixPath1/:name", "/book2/type1/fixPath1/name1/../../././////evilType/evilName"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user