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
105 changes: 105 additions & 0 deletions docs/sample/others/prometheus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Metric Filter Quick Start

## Start PrometheusPushGateway [Docker environment]:

##### Use Docker to install and start:

Directly obtain the latest version of the official image `prom/pushgateway:latest` The startup command is as follows:

```shell
$ docker pull prom/pushgateway
```

```shell
$ docker run -d -p 9091:9091 prom/pushgateway
```

Use the command `./pushgateway` command to start the service. At this time, the browser can access the UI page by accessing `http://<ip>:9091`, but there is no data display on the default Metrics, that is because we have not yet sent to PushGateway Push any data.

However, the PushGateway service itself comes with some metrics, which can be obtained by visiting the `http://<ip>:9091/metrics` address. You can see that it contains some monitoring metrics related to go and process.

##### Check if the configuration is successful:

PushGateway provides a standard API interface and allows users to add data. The default URL address is: `http://<ip>:9091/metrics/job/<JOBNAME>{/<LABEL_NAME>/<LABEL_VALUE>}`, where `<JOBNAME>` It is a required item, which is the value of the job label. It can be followed by any number of label pairs. Generally, we will add an instance`/<INSTANCE_NAME>` instance name label to facilitate the distinction of each indicator. Next, you can push a simple indicator data to PushGateway for testing.

```shell
$ echo "test_metric 123456" | curl --data-binary @- http://<ip>:9091/metrics/job/test_job
```

After the execution is complete, refresh the PushGateway UI page to verify that you can see the test_metric indicator data you just added.

It can also be tested in the following way:
```shell
$ cat <<EOF | curl --data-binary @- http://<ip>:9091/metrics/job/test_job/instance/test_instance
# TYPE test_metrics counter
test_metrics{label="app1",name="demo"} 100.00
# TYPE another_test_metrics gauge
# HELP another_test_metrics Just an example.
another_test_metrics 123.45
EOF
```

## Start Pixiu:

Examples of official references is in `https://github.com/dubbo-go-pixiu/samples`

Add the following configuration file to the `samples/http/simple/pixiu/conf.yaml`

```yaml
static_resources:
listeners:
- name: "net/http"
protocol_type: "HTTP"
address:
socket_address:
address: "0.0.0.0"
port: 8888
filter_chains:
filters:
- name: dgp.filter.httpconnectionmanager
config:
route_config:
routes:
- match:
prefix: /user
route:
cluster: user
cluster_not_found_response_code: 505
http_filters:
- name: dgp.filter.http.prometheusmetric
metric_collect_rules:
enable: true
metric_path: "/metrics"
push_gateway_url: "http://127.0.0.1:9091"
push_interval_seconds: 3
push_job_name: "prometheus"
config:
idle_timeout: 5s
read_timeout: 5s
write_timeout: 5s
clusters:
- name: "user"
lb_policy: "lb"
endpoints:
- id: 1
socket_address:
address: 127.0.0.1
port: 1314
health_checks:
- protocol: "tcp"
timeout: 1s
interval: 2s
healthy_threshold: 4
unhealthy_threshold: 4
shutdown_config:
timeout: "60s"
step_timeout: "10s"
reject_policy: "immediacy"
```

Then execute the following command .

```shell
go run cmd/pixiu/*.go gateway start -c samples/http/simplep/pixiu/conf.yaml
```
Then you can also query the collected indicator data on the PushGateway UI page .
90 changes: 90 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
4 changes: 4 additions & 0 deletions pixiu/pkg/common/extension/filter/filter_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
)

import (
"github.com/creasty/defaults"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -111,6 +112,9 @@ func (fm *FilterManager) Apply(name string, conf map[string]interface{}) (HttpFi
if err := yaml.ParseConfig(factoryConf, conf); err != nil {
return nil, errors.Wrap(err, "config error")
}
if err = defaults.Set(factoryConf); err != nil {
return nil, err
}
err = filter.Apply()
if err != nil {
return nil, errors.Wrap(err, "create fail")
Expand Down
37 changes: 37 additions & 0 deletions pixiu/pkg/filter/prometheus/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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"`
MetricPath 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 `default:"http://127.0.0.1:9091" 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"
}
)
110 changes: 110 additions & 0 deletions pixiu/pkg/filter/prometheus/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* 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"
)

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{
Cfg: &MetricCollectConfiguration{},
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.MetricPath)

f.Prom.SetPushGatewayUrl(f.Cfg.Rules.PushGatewayURL, "/metrics", 3)
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
}
96 changes: 96 additions & 0 deletions pixiu/pkg/filter/prometheus/metric_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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,
MetricPath: "/metrics",
PushGatewayURL: "http://127.0.0.1:9091",
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"`
}
1 change: 1 addition & 0 deletions pixiu/pkg/pluginregistry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/network/dubboproxy/filter/proxy"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/network/grpcconnectionmanager"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/network/httpconnectionmanager"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/prometheus"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/seata"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/tracing"
_ "github.com/apache/dubbo-go-pixiu/pixiu/pkg/filter/traffic"
Expand Down
Loading