1
0
mirror of https://github.com/astaxie/beego.git synced 2025-06-11 20:10:40 +00:00

deprecated httplib and then support prometheus for httplib

This commit is contained in:
Ming Deng
2020-08-09 13:41:39 +00:00
parent dec98f004c
commit 2e891152dd
5 changed files with 216 additions and 1 deletions

24
pkg/httplib/filter.go Normal file
View File

@ -0,0 +1,24 @@
// 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 httplib
import (
"context"
"net/http"
)
type FilterChain func(next Filter) Filter
type Filter func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error)

View File

@ -0,0 +1,73 @@
// 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 prometheus
import (
"context"
"net/http"
"strconv"
"time"
"github.com/prometheus/client_golang/prometheus"
beego "github.com/astaxie/beego/pkg"
"github.com/astaxie/beego/pkg/httplib"
)
type FilterChainBuilder struct {
summaryVec prometheus.ObserverVec
}
func (builder *FilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filter {
builder.summaryVec = prometheus.NewSummaryVec(prometheus.SummaryOpts{
Name: "beego",
Subsystem: "remote_http_request",
ConstLabels: map[string]string{
"server": beego.BConfig.ServerName,
"env": beego.BConfig.RunMode,
"appname": beego.BConfig.AppName,
},
Help: "The statics info for remote http requests",
}, []string{"proto", "scheme", "method", "host", "path", "status", "duration", "isError"})
return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
startTime := time.Now()
resp, err := next(ctx, req)
endTime := time.Now()
go builder.report(startTime, endTime, ctx, req, resp, err)
return resp, err
}
}
func (builder *FilterChainBuilder) report(startTime time.Time, endTime time.Time,
ctx context.Context, req *httplib.BeegoHTTPRequest, resp *http.Response, err error) {
proto := req.GetRequest().Proto
scheme := req.GetRequest().URL.Scheme
method := req.GetRequest().Method
host := req.GetRequest().URL.Host
path := req.GetRequest().URL.Path
status := resp.StatusCode
dur := int(endTime.Sub(startTime) / time.Millisecond)
builder.summaryVec.WithLabelValues(proto, scheme, method, host, path,
strconv.Itoa(status), strconv.Itoa(dur), strconv.FormatBool(err == nil))
}

View File

@ -0,0 +1,41 @@
// 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 prometheus
import (
"context"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/pkg/httplib"
)
func TestFilterChainBuilder_FilterChain(t *testing.T) {
next := func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
time.Sleep(100 * time.Millisecond)
return &http.Response{
StatusCode: 404,
}, nil
}
builder := &FilterChainBuilder{}
filter := builder.FilterChain(next)
req := httplib.Get("https://github.com/notifications?query=repo%3Aastaxie%2Fbeego")
resp, err := filter(context.Background(), req)
assert.NotNil(t, resp)
assert.Nil(t, err)
}

View File

@ -34,6 +34,7 @@ package httplib
import (
"bytes"
"compress/gzip"
"context"
"crypto/tls"
"encoding/json"
"encoding/xml"
@ -66,6 +67,11 @@ var defaultSetting = BeegoHTTPSettings{
var defaultCookieJar http.CookieJar
var settingMutex sync.Mutex
// it will be the last filter and execute request.Do
var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
return req.doRequest(ctx)
}
// createDefaultCookie creates a global cookiejar to store cookies.
func createDefaultCookie() {
settingMutex.Lock()
@ -145,6 +151,7 @@ type BeegoHTTPSettings struct {
DumpBody bool
Retries int // if set to -1 means will retry forever
RetryDelay time.Duration
FilterChains []FilterChain
}
// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url.
@ -295,6 +302,18 @@ func (b *BeegoHTTPRequest) SetCheckRedirect(redirect func(req *http.Request, via
return b
}
// SetFilters will use the filter as the invocation filters
func (b *BeegoHTTPRequest) SetFilters(fcs ...FilterChain) *BeegoHTTPRequest {
b.setting.FilterChains = fcs
return b
}
// AddFilters adds filter
func (b *BeegoHTTPRequest) AddFilters(fcs ...FilterChain) *BeegoHTTPRequest {
b.setting.FilterChains = append(b.setting.FilterChains, fcs...)
return b
}
// Param adds query param in to request.
// params build query string as ?key1=value1&key2=value2...
func (b *BeegoHTTPRequest) Param(key, value string) *BeegoHTTPRequest {
@ -397,7 +416,7 @@ func (b *BeegoHTTPRequest) buildURL(paramBody string) {
if err != nil {
log.Println("Httplib:", err)
}
//iocopy
// iocopy
_, err = io.Copy(fileWriter, fh)
fh.Close()
if err != nil {
@ -440,6 +459,21 @@ func (b *BeegoHTTPRequest) getResponse() (*http.Response, error) {
// DoRequest executes client.Do
func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
return b.DoRequestWithCtx(context.Background())
}
func (b *BeegoHTTPRequest) DoRequestWithCtx(ctx context.Context) (resp *http.Response, err error) {
root := doRequestFilter
if len(b.setting.FilterChains) > 0 {
for i := len(b.setting.FilterChains) - 1; i >= 0; i-- {
root = b.setting.FilterChains[i](root)
}
}
return root(ctx, b)
}
func (b *BeegoHTTPRequest) doRequest(ctx context.Context) (resp *http.Response, err error) {
var paramBody string
if len(b.params) > 0 {
var buf bytes.Buffer