Skip to content

Commit

Permalink
基于消息测试能够匹配的规则列表
Browse files Browse the repository at this point in the history
  • Loading branch information
mylxsw committed Sep 5, 2020
1 parent 882dd31 commit ea7936a
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 10 deletions.
22 changes: 22 additions & 0 deletions api/controller/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"net/http"
"strings"

"github.com/mylxsw/adanos-alert/internal/job"
"github.com/mylxsw/adanos-alert/internal/repository"
"github.com/mylxsw/adanos-alert/pkg/misc"
"github.com/mylxsw/adanos-alert/pkg/template"
"github.com/mylxsw/asteria/log"
"github.com/mylxsw/container"
"github.com/mylxsw/glacier/web"
"github.com/pkg/errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
Expand All @@ -27,6 +29,7 @@ func (m *MessageController) Register(router *web.Router) {
router.Group("/messages", func(router *web.Router) {
router.Get("/", m.Messages).Name("messages:all")
router.Get("/{id}/", m.Message).Name("messages:one")
router.Post("/{id}/matched-rules/", m.TestMatchedRules).Name("messages:matched-rules")

router.Post("/", m.AddCommonMessage).Name("messages:add:common")
router.Post("/logstash/", m.AddLogstashMessage).Name("messages:add:logstash")
Expand Down Expand Up @@ -253,3 +256,22 @@ func (m *MessageController) AddOpenFalconMessage(ctx web.Context, messageRepo re
id, err := m.saveMessage(messageRepo, misc.OpenFalconToCommonMessage(tos, content))
return m.errorWrap(ctx, id, err)
}

// TestMatchedRules 测试 message 匹配哪些规则
func (m *MessageController) TestMatchedRules(ctx web.Context, msgRepo repository.MessageRepo, ruleRepo repository.RuleRepo) ([]job.MatchedRule, error) {
msgID, err := primitive.ObjectIDFromHex(ctx.PathVar("id"))
if err != nil {
return nil, errors.Wrap(err, "invalid message id")
}

message, err := msgRepo.Get(msgID)
if err != nil {
if err == repository.ErrNotFound {
return nil, errors.Wrap(err, "no such message")
}

return nil, errors.Wrap(err, "query message failed")
}

return job.BuildMessageMatchTest(ruleRepo)(message)
}
5 changes: 3 additions & 2 deletions dashboard/src/components/MessageCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<b-badge v-if="message.status === 'grouped'" variant="success">已分组</b-badge>
<b-badge v-if="message.status === 'canceled'" variant="danger">无规则,已取消</b-badge>
<b-badge v-if="message.status === 'expired'" variant="warning">匹配规则,已过期</b-badge>
<b-button size="sm" class="ml-2" variant="warning" @click="testMatchedRules(message.id)" v-if="testMatchedRules">测试</b-button>
</div>
</template>

Expand Down Expand Up @@ -45,16 +46,16 @@
props: {
message: Object,
message_index: Number,
testMatchedRules: Function,
},
methods: {
}
}
</script>

<style scoped>
.adanos-code {
max-height: 100rem;
max-height: 50rem;
white-space: pre-wrap!important;
word-wrap: break-word!important;
*white-space:normal!important;
Expand Down
5 changes: 5 additions & 0 deletions dashboard/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ import Audit from "./views/Audit"

Vue.use(Router);

const routerPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(error => error)
}

export default new Router({
routes: [
{path: '/', component: Groups},
Expand Down
45 changes: 42 additions & 3 deletions dashboard/src/views/Messages.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,37 @@
</b-form>
</b-card-text>
</b-card>
<MessageCard v-for="(message, index) in messages" :key="index" class="mb-3" :message="message" :message_index="index"></MessageCard>
<MessageCard v-for="(message, index) in messages" :key="index" class="mb-3" :message="message" :message_index="index" :test-matched-rules="testMatchedRules"></MessageCard>
<b-card v-if="messages.length === 0">
<b-card-body>There are no records to show</b-card-body>
</b-card>
<paginator :per_page="2" :cur="cur" :next="next" path="/messages" :query="this.$route.query"></paginator>
</b-col>

<b-modal id="matched-rules-dialog" title="匹配到的规则" hide-footer size="xl">
<b-table responsive="true" :items="matched_rules" :fields="matched_rules_fields">
<template v-slot:cell(name)="row">
<span v-b-tooltip.hover :title="row.item.rule.id">{{ row.item.rule.name }}</span>
<b-link :to="'/rules/' + row.item.rule.id + '/edit'" target="_blank" class="ml-2">
<font-awesome-icon icon="external-link-alt"></font-awesome-icon>
</b-link>
<p>
<b-badge variant="info" v-for="(tag, index) in row.item.rule.tags" :key="index" class="mr-1">{{ tag }}</b-badge>
</p>
</template>
<template v-slot:cell(rule)="row">
<p class="adanos-pre-fold" v-b-tooltip.hover :title="row.item.rule.rule">
<code>{{ row.item.rule.rule }}</code>
</p>
</template>
<template v-slot:cell(aggregate_rule)="row">
<p class="adanos-pre-fold" v-b-tooltip.hover :title="row.item.rule.aggregate_rule">
<code>{{ row.item.rule.aggregate_rule }}</code>
</p>
<p><b-badge variant="success" v-if="row.item.aggregate_key" v-b-tooltip.hover title="实际匹配的聚合 Key">{{ row.item.aggregate_key }}</b-badge></p>
</template>
</b-table>
</b-modal>
</b-row>
</template>

Expand All @@ -43,6 +68,12 @@
messages: [],
cur: parseInt(this.$route.query.next !== undefined ? this.$route.query.next : 0),
next: -1,
matched_rules: [],
matched_rules_fields: [
{key: 'name', label: '规则名称/ID'},
{key: 'rule', label: '规则'},
{key: 'aggregate_rule', label: '聚合条件'},
],
};
},
watch: {
Expand All @@ -59,10 +90,18 @@
tags: this.search.tags.join(),
meta: this.search.meta,
origin: this.search.origin,
}}).catch(err => {err});
}}).catch(err => {this.ToastError(err);});
},
testMatchedRules(id) {
axios.post('/api/messages/' + id + '/matched-rules/', {}).then(resp => {
this.matched_rules = resp.data;
this.$root.$emit('bv::show::modal', "matched-rules-dialog");
}).catch(error => {
this.ErrorBox(error);
});
},
loadMore() {
var params = this.$route.query;
let params = this.$route.query;
params.offset = this.cur;
axios.get('/api/messages/', {
Expand Down
6 changes: 3 additions & 3 deletions dashboard/src/views/Rules.vue
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,14 @@ export default {
},
searchSubmit(evt) {
evt.preventDefault();
var query = this.search;
let query = this.search;
query.offset = 0;
this.$router.push({path: '/rules', query: query}).catch(err => {
err
this.ToastError(err)
});
},
reload() {
var params = this.$route.query;
let params = this.$route.query;
params.offset = this.cur;
axios.get('/api/rules/', {
Expand Down
39 changes: 37 additions & 2 deletions internal/job/aggregation.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (a *AggregationJob) Handle() {
}

func (a *AggregationJob) groupingMessages(msgRepo repository.MessageRepo, groupRepo repository.MessageGroupRepo, ruleRepo repository.RuleRepo) error {
matchers, err := a.initializeMatchers(ruleRepo)
matchers, err := initializeMatchers(ruleRepo)
if err != nil {
log.Error(err.Error())
return err
Expand Down Expand Up @@ -114,7 +114,7 @@ func (a *AggregationJob) groupingMessages(msgRepo repository.MessageRepo, groupR
})
}

func (a *AggregationJob) initializeMatchers(ruleRepo repository.RuleRepo) ([]*matcher.MessageMatcher, error) {
func initializeMatchers(ruleRepo repository.RuleRepo) ([]*matcher.MessageMatcher, error) {
// get all rules
rules, err := ruleRepo.Find(bson.M{"status": repository.RuleStatusEnabled})
if err != nil {
Expand Down Expand Up @@ -188,3 +188,38 @@ func buildMessageFinger(groupRule string, msg repository.Message) string {

return groupKey
}

type MatchedRule struct {
Rule repository.Rule `json:"rule"`
AggregateKey string `json:"aggregate_key"`
}

// BuildMessageMatchTest 创建 message 与规则的匹配测试,用于检测 message 能够匹配哪些规则
func BuildMessageMatchTest(ruleRepo repository.RuleRepo) func(msg repository.Message) ([]MatchedRule, error) {
return func(msg repository.Message) ([]MatchedRule, error) {
matchedRules := make([]MatchedRule, 0)

matchers, err := initializeMatchers(ruleRepo)
if err != nil {
log.Error(err.Error())
return matchedRules, err
}

for _, m := range matchers {
matched, err := m.Match(msg)
if err != nil {
continue
}

// if the message matched a rule, update message's group_id and skip to next message
if matched {
matchedRules = append(matchedRules, MatchedRule{
Rule: m.Rule(),
AggregateKey: buildMessageFinger(m.Rule().AggregateRule, msg),
})
}
}

return matchedRules, nil
}
}

0 comments on commit ea7936a

Please sign in to comment.