feat(rpc): apply filter in auditlog

Signed-off-by: slasher <shenjie1@oppo.com>
This commit is contained in:
slasher 2023-10-11 18:45:16 +08:00 committed by 梁曟風
parent 91421b7dc7
commit 7d3a90f8e9
9 changed files with 37 additions and 36 deletions

View File

@ -21,7 +21,6 @@ import (
"net/http"
"runtime/debug"
"strconv"
"strings"
"sync"
"time"
@ -54,6 +53,7 @@ type jsonAuditlog struct {
decoder Decoder
metricSender MetricSender
logFile LogCloser
logFilter LogFilter
logPool sync.Pool
bodyPool sync.Pool
@ -138,11 +138,17 @@ func Open(module string, cfg *Config) (ph rpc.ProgressHandler, logFile LogCloser
}
}
logFilter, err := newLogFilter(cfg.Filters)
if err != nil {
return nil, nil, errors.Info(err, "new log filter").Detail(err)
}
return &jsonAuditlog{
module: module,
decoder: &defaultDecoder{},
metricSender: NewPrometheusSender(cfg.MetricConfig),
logFile: logFile,
logFilter: logFilter,
logPool: sync.Pool{
New: func() interface{} {
@ -251,7 +257,7 @@ func (j *jsonAuditlog) Handler(w http.ResponseWriter, req *http.Request, f func(
j.metricSender.Send(auditLog.ToBytesWithTab(b))
if j.logFile == nil || (len(j.cfg.KeywordsFilter) > 0 && defaultLogFilter(req, j.cfg.KeywordsFilter)) {
if j.logFile == nil || j.logFilter.Filter(auditLog) {
return
}
@ -268,18 +274,6 @@ func (j *jsonAuditlog) Handler(w http.ResponseWriter, req *http.Request, f func(
}
}
// defaultLogFilter support uri and method filter based on keywords
func defaultLogFilter(r *http.Request, words []string) bool {
method := strings.ToLower(r.Method)
for _, word := range words {
str := strings.ToLower(word)
if method == str || strings.Contains(r.RequestURI, str) {
return true
}
}
return false
}
// ExtraHeader provides extra response header writes to the ResponseWriter.
func ExtraHeader(w http.ResponseWriter) http.Header {
h := make(http.Header)

View File

@ -56,6 +56,7 @@ func initServer(t *testing.T, name string, cfg Config) (server *httptest.Server,
cfg.LogDir = tmpDir
cfg.MetricConfig = PrometheusConfig{Idc: name}
cfg.Filters = []FilterConfig{{Must: Conditions{"term": {"method": "GET"}}}}
var ah rpc.ProgressHandler
ah, lc, err = Open(name, &cfg)
@ -177,7 +178,7 @@ func initNoContentLengthServer(t *testing.T) (server *httptest.Server, tmpDir st
func TestOpen(t *testing.T) {
cfg := Config{
KeywordsFilter: []string{"Get"},
Filters: []FilterConfig{{Must: Conditions{"term": {"method": "GET"}}}},
}
server, tmpDir, lc := initServer(t, "testOpen", cfg)
defer func() {

View File

@ -38,8 +38,8 @@ type Config struct {
Backup int `json:"backup"`
MetricConfig PrometheusConfig `json:"metric_config"`
// KeywordsFilter log filter based on uri and request method
KeywordsFilter []string `json:"keywords_filter"`
// Filters are or relations
Filters []FilterConfig `json:"filters"`
// LogFormat valid value is "text" or "json", default is "text"
LogFormat string `json:"log_format"`

View File

@ -27,6 +27,7 @@ import (
"time"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/rpc/auditlog"
"github.com/cubefs/cubefs/blobstore/common/trace"
)
@ -460,6 +461,10 @@ func (a *app) List(c *rpc.Context) {
files = append(files, resp)
}
extraHeader := auditlog.ExtraHeader(c.Writer)
extraHeader.Add("http-header-key", "http-header-value")
extraHeader["oWN-defined-KEY"] = []string{"ODvalue", "0x10"}
c.RespondStatusData(http.StatusOK, files)
}

View File

@ -2,7 +2,14 @@
"log_level": "debug",
"auditlog": {
"logdir": "/tmp/examples/",
"rotate_new": false
"rotate_new": false,
"filters": [
{
"must": {"range": {"status_code": "405-405"}},
"must_not": {"match": {"method": "POST"}}
},
{"should": {"term": {"path": ["/x", "/y", "/z"]}}}
]
},
"app": {
"bind_addr": ":9999",

View File

@ -17,13 +17,12 @@
"service": "服务名",
"tag": "标签",
"team": "团队",
"enable_req_length_cnt": "是否启用请求长度统计true或者false,默认false",
"enable_resp_length_cnt": "是否启用响应长度统计true或者false,默认false",
"enable_resp_duration": "是否启用响应时延true或者false,默认false",
"max_api_level": "api最大层级数如/get/name为2"
},
"keywords_filter": "关键字过滤目前支持url和请求方法过滤如/download、get等"
"filters": "按照日志字段多条件组合匹配过滤日志"
},
"auth": {
"enable_auth": "是否开启鉴权true或者false默认false",
@ -38,4 +37,4 @@
"maxbackups": "保留日志文件个数"
}
}
```
```

View File

@ -263,11 +263,9 @@ BlobNode的配置是基于[公有配置](./base.md),以下配置说明主要
"chunkbits": 29,
"log_file_suffix": ".log",
"backup": 10,
"keywords_filter": [
"list",
"metrics",
"/shard/get/"
],
"filters": [
{"should": {"match": {"path": ["list", "metrics", "/shard/get/"]}}}
],
"metric_config": {
"idc": "bjht",
"service": "BLOBNODE",
@ -292,4 +290,4 @@ BlobNode的配置是基于[公有配置](./base.md),以下配置说明主要
}
}
}
```
```

View File

@ -17,13 +17,12 @@ The basic configuration is shared by each module and mainly includes server port
"service": "service name",
"tag": "tag",
"team": "team",
"enable_req_length_cnt": "whether to enable request length statistics, true or false, default is false",
"enable_resp_length_cnt": "whether to enable response length statistics, true or false, default is false",
"enable_resp_duration": "whether to enable response latency, true or false, default is false",
"max_api_level": "maximum API level, such as 2 for /get/name"
},
"keywords_filter": "keyword filter, currently supports URL and request method filtering, such as /download, GET, etc."
"filters": "Filter log by multi-criteria matching of log's fields"
},
"auth": {
"enable_auth": "whether to enable authentication, true or false, default is false",
@ -38,4 +37,4 @@ The basic configuration is shared by each module and mainly includes server port
"maxbackups": "number of log files to keep"
}
}
```
```

View File

@ -265,11 +265,9 @@ BlobNode configuration is based on the [public configuration](./base.md), and th
"chunkbits": 29,
"log_file_suffix": ".log",
"backup": 10,
"keywords_filter": [
"list",
"metrics",
"/shard/get/"
],
"filters": [
{"should": {"match": {"path": ["list", "metrics", "/shard/get/"]}}}
],
"metric_config": {
"idc": "bjht",
"service": "BLOBNODE",
@ -294,4 +292,4 @@ BlobNode configuration is based on the [public configuration](./base.md), and th
}
}
}
```
```