Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASoC 2022] Pixiu Metrics Implementation #433 #480

Merged
merged 15 commits into from
Sep 19, 2022
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/apache/dubbo-go-pixiu

go 1.18
go 1.17

require (
cloud.google.com/go/compute v1.6.0
Expand Down Expand Up @@ -77,6 +77,7 @@ require (
github.com/prometheus/client_golang v1.12.1
github.com/prometheus/client_model v0.2.0
github.com/prometheus/common v0.33.0
github.com/prometheus/exporter-toolkit v0.7.1
github.com/prometheus/prometheus v2.5.0+incompatible
github.com/ryanuber/go-glob v1.0.0
github.com/spf13/cast v1.5.0
Expand Down Expand Up @@ -217,6 +218,7 @@ require (
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/josharian/native v0.0.0-20200817173448-b6b71def0850 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
github.com/klauspost/compress v1.15.8 // indirect
Expand Down Expand Up @@ -249,6 +251,7 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
Expand Down
94 changes: 94 additions & 0 deletions go.sum

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pixiu/pkg/common/constant/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const (
HTTPLoadBalanceFilter = "dgp.filter.http.loadbalance"
HTTPEventFilter = "dgp.filter.http.event"
HTTPTrafficFilter = "dgp.filter.http.traffic"
HTTPPrometheusMetricFilter = "dgp.filter.http.prometheusmetric"

DubboHttpFilter = "dgp.filter.dubbo.http"
DubboProxyFilter = "dgp.filter.dubbo.proxy"
Expand Down
36 changes: 36 additions & 0 deletions pixiu/pkg/filter/prometheus/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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

type (
MetricCollectConfiguration struct {
Rules MetricCollectRule `yaml:"metric_collect_rules" json:"metric_collect_rules"`
}

MetricCollectRule struct {
gongna-au marked this conversation as resolved.
Show resolved Hide resolved
Enable bool `json:"enbale,omitempty" yaml:"enable,omitempty"`
MeticPath string `json:"metric_path,omitempty" yaml:"metric_path,omitempty"`
// Push Gateway URL in format http://domain:port
// where JOBNAME can be any string of your choice
PushGatewayURL string `json:"push_gateway_url,omitempty" yaml:"push_gateway_url,omitempty"`
// Push interval in seconds
// lint:ignore ST1011 renaming would be breaking change
PushIntervalSeconds int `json:"push_interval_seconds,omitempty" yaml:"push_interval_seconds,omitempty"`
PushJobName string `json:"push_job_name,omitempty" yaml:"push_job_name,omitempty"`
// Pushgateway job name, defaults to "prometheus"
}
)
109 changes: 109 additions & 0 deletions pixiu/pkg/filter/prometheus/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 (
stdHttp "net/http"
"time"
)

import (
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/constant"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/extension/filter"
contextHttp "github.com/apache/dubbo-go-pixiu/pixiu/pkg/context/http"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
prom "github.com/apache/dubbo-go-pixiu/pkg/metrics/prometheus"
)

const (
Kind = constant.HTTPPrometheusMetricFilter
)

func init() {
filter.RegisterHttpFilter(&Plugin{})
}

type (
Plugin struct {
}

FilterFactory struct {
Cfg *MetricCollectConfiguration
Prom *prom.Prometheus
}

Filter struct {
Cfg *MetricCollectConfiguration
Prom *prom.Prometheus
}
)

func (p Plugin) Kind() string {
return Kind
}

func (p *Plugin) CreateFilterFactory() (filter.HttpFilterFactory, error) {

return &FilterFactory{
Prom: prom.NewPrometheus(),
}, nil
}

func (factory *FilterFactory) Config() interface{} {

return factory.Cfg
}

func (factory *FilterFactory) Apply() error {

return nil
}

func (factory *FilterFactory) PrepareFilterChain(ctx *contextHttp.HttpContext, chain filter.FilterChain) error {

f := &Filter{
Cfg: factory.Cfg,
Prom: factory.Prom,
}
chain.AppendDecodeFilters(f)
return nil
}

func (f *Filter) Decode(ctx *contextHttp.HttpContext) filter.FilterStatus {

if f.Cfg == nil {
logger.Errorf("Message:Filter Metric Collect Configuration is null")
ctx.SendLocalReply(stdHttp.StatusForbidden, constant.Default403Body)
return filter.Continue
}
if f.Prom == nil {
logger.Errorf("Message:Prometheus Collector is not initialized")
ctx.SendLocalReply(stdHttp.StatusForbidden, constant.Default403Body)
return filter.Continue
}

f.Prom.SetMetricPath(f.Cfg.Rules.MeticPath)
f.Prom.SetPushGateway(f.Cfg.Rules.PushGatewayURL, time.Duration(f.Cfg.Rules.PushIntervalSeconds), f.Cfg.Rules.PushJobName)
start := f.Prom.HandlerFunc()
err := start(ctx)
if err != nil {
logger.Errorf("Message:Context HandlerFunc error")
ctx.SendLocalReply(stdHttp.StatusForbidden, constant.Default403Body)
}
return filter.Continue
}
95 changes: 95 additions & 0 deletions pixiu/pkg/filter/prometheus/metric_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 (
"bytes"
"encoding/json"
"net/http"
"testing"
)

import (
"github.com/stretchr/testify/assert"
)

import (
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/client"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/extension/filter"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/yaml"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/context/mock"
)

func TestExporterApiMetric(t *testing.T) {

rules := MetricCollectConfiguration{
MetricCollectRule{
Enable: true,
MeticPath: "/metrics",
PushGatewayURL: "http://domain:port",
PushIntervalSeconds: 3,
PushJobName: "prometheus",
},
}
_, err := yaml.MarshalYML(rules)
assert.Nil(t, err)

config := &rules
p := Plugin{}
msg := "this is test msg"
metricFilterFactory, _ := p.CreateFilterFactory()

if factory, ok := metricFilterFactory.(*FilterFactory); ok {
factory.Cfg = config

err = factory.Apply()
assert.Nil(t, err)

chain := filter.NewDefaultFilterChain()
data := GetApiStatsResponse()
body, _ := json.Marshal(&data)
request, _ := http.NewRequest("POST", "/_api/health", bytes.NewBuffer(body))
ctx := mock.GetMockHTTPContext(request)
ctx.TargetResp = client.NewResponse([]byte(msg))
err := factory.PrepareFilterChain(ctx, chain)
assert.Nil(t, err)
chain.OnDecode(ctx)

}

}

func GetApiStatsResponse() ApiStatsResponse {
return ApiStatsResponse{
ApiStats: []ApiStat{
{
ApiName: "api1",
ApiRequests: 1000,
},
},
}
}

type ApiStatsResponse struct {
ApiStats []ApiStat `json:"api_stats"`
}

type ApiStat struct {
ApiName string `json:"api_name"`
ApiRequests int64 `json:"api_requests"`
}
Loading