watcher 基礎語法與使用
-
Xpack-Watchs基本使用:
首先看一個watcher的例子:
## 創建一個watcher,比如定義一個trigger 每個10s鍾看一下input里的數據 PUT _xpack/watcher/watch/school_watcher { "trigger": { "schedule": { "interval": "10s" } }, ## 查看任務信息 "input": { "search": { "request": { ## 監控具體索引 "indices": ["school*"], ## body里面具體些搜索語句 "body": { "size": 0, "query": { "match": { ## 比如索引里面name 有 hello 則進行報警 "name": "hello" } } } } } }, ## 對於上面的查詢結果進行比較: "condition": { ## compare進行比較 "compare": { ## 上面的query查詢的結果會放入到ctx.payload中: ## 比如獲取 ctx.payload.hits.total ctx.payload._shards.total 等等 "ctx.payload.hits.total": { "gt": 0 } } }, ## transform作用:重新查詢出文檔內容賦值給ctx.payload "transform": { "search": { "request": { "indices": ["school*"], "body": { "size": 10, "query": { "match": { "name": "hello" } } } } } }, ## 根據上面的查詢、比較結果,執行actions里面定義的動作(定義多種報警類型) "actions": { ## 報警名字 "log_hello": { ## 防止報警風暴: 設置閾值 15m內曾經報警過, 則不報警 "throttle_period": "15m", ## 報警方式:logging、mail、http等 "logging": { ## 報警具體內容:使用 {{ 查詢參數 }} 進行賦值: "text": "Found {{ctx.payload.hits.total}} hello in the school" } } } }
-
ctx.payload取值規范:
比如我們進行search搜索school里面name=zhangsan的數據:
## payload取值規范:比如我們進行search搜索school: GET school/_search { "query": { "match": { "name": "zhangsan" } } }
查詢結果如下:
{ "took": 14, "timed_out": false, "_shards": { "total": 2, "successful": 2, "skipped": 0, "failed": 0 }, "hits": { "total": 1, "max_score": 1.5404451, "hits": [ { "_index": "school", "_type": "student", "_id": "1", "_score": 1.5404451, "_source": { "name": "zhangsan", "age": 25, "course": "elasticsearch", "study_date": "2018-06-15T20:30:50", "mark": "today is a good day" } } ] } }
表示查詢:ctx.payload結果集:
## 表示查詢:ctx.payload結果集: {{#ctx.payload.hits.hits}} {{_source.name}} {{_source.course}} {{/ctx.payload.hits.hits}}
比如我們進行search搜索school並采用聚合的方式來查詢terms course數據:
GET school/_search { "size": 0, "aggs": { "myterms": { "terms": { "field": "course", "size": 10 } } } }
查詢結果:
{ "took": 11, "timed_out": false, "_shards": { "total": 2, "successful": 2, "skipped": 0, "failed": 0 }, "hits": { "total": 10, "max_score": 0, "hits": [] }, "aggregations": { "myterms": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "elasticsearch", "doc_count": 7 }, { "key": "good", "doc_count": 1 }, { "key": "spring", "doc_count": 1 }, { "key": "spring elasticsearch", "doc_count": 1 } ] } } }
payload取值使用:現在想取得上面的hits.hits里面的數據內容,就可以使用如下方式:
## 表示查詢:ctx.payload結果集: {{#ctx.payload.aggregations.aggsname.buckets}} {{key}} {{doc_count}} {{/ctx.payload.aggregations.aggsname.buckets}} ## 針對這里內容就是: {{#ctx.payload.aggregations.myterms.buckets}} {{key}} {{doc_count}} {{/ctx.payload.aggregations.myterms.buckets}}
-
watcher API使用:
#查看一個watcher # GET _xpack/watcher/watch/school_watcher #刪除一個watcher # DELETE _xpack/watcher/watch/school_watcher #執行watcher # POST _xpack/watcher/watch/school_watcher/_execute #查看執行結果 GET /.watcher-history*/_search?pretty { "sort" : [ { "result.execution_time" : "desc" } ], "query": { "match": { "watch_id": "school_watcher" } } }
-
triggers的幾種類型
#--------------------triggers的幾種類型-------------------- #hourly、daily、weekly、monthly、yearly、cron、interval #hourly:每小時執行 #例如:12:00, 12:15, 12:30, 12:45, 1:00, 1:15 { "trigger" : { "schedule" : { "hourly" : { "minute" : [ 0, 15, 30, 45 ] } } } } #daily:每天執行 #每天00:00, 12:00, and 17:00 { "trigger" : { "schedule" : { "daily" : { "at" : [ "midnight", "noon", "17:00" ] } } } } #每天00:00, 00:30, 12:00, 12:30, 17:00 and 17:30 { "trigger" : { "schedule" : { "daily" : { "at" { "hour" : [ 0, 12, 17 ], "minute" : [0, 30] } } } } } #weekly:指定星期幾 #周二12:00,周五17:00 { "trigger" : { "schedule" : { "weekly" : [ { "on" : "tuesday", "at" : "noon" }, { "on" : "friday", "at" : "17:00" } ] } } } #周二、周五的17:00 { "trigger" : { "schedule" : { "weekly" : { "on" : [ "tuesday", "friday" ], "at" : [ "noon", "17:00" ] } } } } #monthly:指定每月哪天執行 #每月10號中午、每月20號17:00 { "trigger" : { "schedule" : { "monthly" : [ { "on" : 10, "at" : "noon" }, { "on" : 20, "at" : "17:00" } ] } } } #每月10號、20號的00:00,12:00 { "trigger" : { "schedule" : { "monthly" : { "on" : [ 10, 20 ], "at" : [ "midnight", "noon" ] } } } } #yearly-指定月、日、時 #每年的1月10日12:00,每年的7月20日17:00 { "trigger" : { "schedule" : { "yearly" : [ { "in" : "january", "on" : 10, "at" : "noon" }, { "in" : "july", "on" : 20, "at" : "17:00" } ] } } } #每年1月10日,1月20日,12月10日,12月20日的12:00,00:00 { "trigger" : { "schedule" : { "yearly" : { "in" : [ "jan", "dec" ], "on" : [ 10, 20 ], "at" : [ "midnight", "noon" ] } } } } #cron-表達式 <seconds> <minutes> <hours> <day_of_month> <month> <day_of_week> [year] 0 5 9 * * ? 0 0-5 9 * * ? 0 0/15 9 * * ? #interval-周期的 #間隔單位:s:秒、m:分鍾、h:小時、d:天、w:星期
-
input的幾種類型:
#--------------------Inputs的幾種類型-------------------- #Simple、Search、HTTP、Chain #Simple Input-靜態數據 #每天12點觸發 { "trigger" : { "schedule" : { "daily" : { "at" : "noon" } } }, "input" : { "simple" : { "name" : "John" } }, "actions" : { "reminder_email" : { "email" : { "to" : "to@host.domain", "subject" : "Reminder", "body" : "Dear {{ctx.payload.name}}, by the time you read these lines, I'll be gone" } } } } #Search-搜索 { "input" : { "search" : { "request" : { "indices" : [ "logs" ], "body" : { "query" : { "match_all" : {} } } } } }, "condition" : { "compare" : { "ctx.payload.hits.total" : { "gt" : 5 }} } ... } #Http-請求 #request.host #request.port #request.path #request.headers #request.params #request.url:request.scheme, request.host, request.port and request.params #request.method:head、get、post、put、delete #request.auth #request.body #request.proxy.host #request.proxy.port #request.connection_timeout #request.read_timeout #response_content_type:json, yaml and text #extract #get請求 { "input" : { "http" : { "request" : { "host" : "example.com", "port" : 9200, "path" : "/idx/_search" } } } } #含有body體內容 { "input" : { "http" : { "request" : { "host" : "host.domain", "port" : 9200, "path" : "/idx/_search", "body" : "{\"query\" : { \"match\" : { \"category\" : \"event\"}}}" } } } } #含有參數的 { "input" : { "http" : { "request" : { "host" : "host.domain", "port" : "9200", "path" : "/_cluster/stats", "params" : { "human" : "true" } } } } } #含有用戶密碼 { "input" : { "http" : { "request" : { "host" : "host.domain", "port" : "9200", "path" : "/myservice", "auth" : { "basic" : { "username" : "user", "password" : "pass" } } } } } } #直接請求url的 { "input" : { "http" : { "request" : { "url" : "http://api.openweathermap.org/data/2.5/weather", "params" : { "lat" : "52.374031", "lon" : "4.88969", "appid" : "<your openweathermap appid>" } } } } } #Chain-input-同時設置多個input,串行 { "input" : { "chain" : { "inputs" : [ ## 第一步input { "first" : { "simple" : { "path" : "/_search" } } }, ## 第二步input (可以去使用第一步input返回的結果) { "second" : { "http" : { "request" : { "host" : "localhost", "port" : 9200, "path" : "{{ctx.payload.first.path}}" } } } } ] } } }
-
condition條件設置:如果condition條件返回true 則會觸發action 如果返回 false 則就停止,不執行action
#--------------------條件設置-------------------- #Always Condition "condition" : { "always" : {} } #Never Condition "condition" : { "never" : {} } #Compare Condition (進行和查詢的結果進行比較語法如下:) # eq:、not_eq、gt、gte、lt、lte ## 比如錯誤條數超過了5條進行報警、響應長時間超過多少毫秒進行報警等 { "condition" : { "compare" : { "ctx.payload.hits.total" : { "gte" : 5 } } } #<{expression}> 正則表達式 使用 <> 中寫正則表達式: 比如 當前時間 - 5分鍾 進行比較,如下: { "condition" : { "compare" : { "ctx.execution_time" : { "gte" : "<{now-5m}>" } } } #{{path}} 比較,這個就是最開始的示例里面的獲取參數方式,如下: { "condition" : { "compare" : { "ctx.payload.aggregations.status.buckets.error.doc_count" : { "not_eq" : "{{ctx.payload.aggregations.handled.buckets.true.doc_count}}" } } } #Array Compare Condition 數組比較: 比如當前的doc_count大於25 就進行報警 { "condition": { "array_compare": { "ctx.payload.aggregations.top_tweeters.buckets" : { "path": "doc_count" , "gte": { "value": 25, } } } } } #Script Condition 腳本方式 { "input" : { "search" : { "indices" : "log-events", "body" : { "size" : 0, "query" : { "match" : { "status" : "error" } } } } }, "condition" : { "script" : { ## 當前返回的條數是否大於閾值,進行報警 "inline" : "return ctx.payload.hits.total > threshold", "params" : { "threshold" : 5 } } } }
-
Action 觸發器
#--------------------Actions-------------------- #Email Action--發送郵件 #如果使用發送郵件的報警,則需要在elasticsearch.yml中配置發送郵件服務的信息 xpack.notification.email: default_account: gmail_account account: gmail_account: profile: gmail smtp: auth: true starttls.enable: true host: smtp.gmail.com port: 587 user: <username> password: <password> outlook_account: profile: outlook smtp: auth: true starttls.enable: true host: smtp-mail.outlook.com port: 587 user: <username> password: <password>: exchange_account: profile: outlook email_defaults: from: <email address of service account> smtp: auth: true starttls.enable: true host: <your exchange server> port: 587 user: <email address of service account> password: <password> #發送郵件 "actions" : { ## actions名字 "send_email" : { "email" : { "to" : "'Recipient Name <recipient@example.com>'", #"to" : ['Personal Name <user1@host.domain>', 'user2@host.domain'], "subject" : "Watcher Notification", "body" : "{{ctx.payload.hits.total}} error logs found" } } } #發送含有附件信息的郵件 "actions" : { "email_admin" : { "email": { "to": "'John Doe <john.doe@example.com>'", "attachments" : { ## 附件方式 "my_image.png" : { "http" : { "content_type" : "image.png", "request" : { "url": "http://example.org/foo/my-image.png" } } }, ## xpack reporting插件生成方式: "dashboard.pdf" : { "reporting" : { "url": "http://example.org:5601/api/reporting/generate/dashboard/Error-Monitoring" } }, ## 自定義附件 "data.yml" : { "data" : { "format" : "yaml" } } } } } } #Webhook Action,發送一個http請求 #發送github的issue "actions" : { "create_github_issue" : { ## 因為發郵件到達率不是特別高,所以可以使用外部的接口調用方式 ## 比如這里調用url為外部的手機短信接口進行發送 "webhook" : { ## 請求方式 "method" : "POST", ## 外部請求地址 "url" : "https://api.github.com/repos/<owner>/<repo>/issues", ## 請求報文 "body" : "{ \"title\": \"Found errors in 'contact.html'\", \"body\": \"Found {{ctx.payload.hits.total}} errors in the last 5 minutes\", \"assignee\": \"web-admin\", \"labels\": [ \"bug\", \"sev2\" ] }", ## 用戶名密碼 "auth" : { "basic" : { "username" : "<username>", "password" : "<password>" } } } } } #帶有url參數的請求 "actions" : { "my_webhook" : { "webhook" : { "method" : "POST", "host" : "mylisteningserver", "port" : 9200, "path": ":/alert", "params" : { "watch_id" : "{{ctx.watch_id}}" } } } } #自定義header "actions" : { "my_webhook" : { "webhook" : { "method" : "POST", "host" : "mylisteningserver", "port" : 9200, "path": ":/alert/{{ctx.watch_id}}", "headers" : { "Content-Type" : "application/yaml" }, "body" : "count: {{ctx.payload.hits.total}}" } } } #Index Action--創建索引文檔 "actions" : { "index_payload" : { "index" : { "index" : "my-index", "doc_type" : "my-type", "doc_id": "my-id" } } } #Logging Action--記錄日志 #level:error, warn, info, debug and trace ## 日志種類: #category:xpack.watcher.actions.logging "actions" : { "log" : { "transform" : { ... }, ## 日志報警 "logging" : { "text" : "executed at {{ctx.execution_time}}", ## 日志級別 "level": "info" } } } #Jira Action 與jira集成 #HipChat Action #Slack Action #PagerDuty Action
-
使用接口的形式創建一個watcher, 進行模擬:
-
執watcher腳本:
## 查詢school GET school/student/_search { "query": { "match_all":{} } } ## 創建school_watcher PUT _xpack/watcher/watch/school_watcher { "trigger": { "schedule": { "interval": "10s" } }, "input": { "search": { "request": { "indices": ["school*"], "body": { "size": 0, "query": { "match": { "name": "hello" } } } } } }, "condition": { "compare": { "ctx.payload.hits.total": { "gt": 0 } } }, "transform": { "search": { "request": { "indices": ["school*"], "body": { "size": 10, "query": { "match": { "name": "hello" } } } } } }, "actions": { "log_hello": { "throttle_period": "15m", "logging": { "text": "Found {{ctx.payload.hits.total}} hello in the school" } } } } ## 查看watcher執行結果 GET /.watcher-history*/_search?pretty { "sort" : [ { "result.execution_time" : "desc" } ], "query": { "match": { "watch_id": "school_watcher" } } } ## 進行數據測試: POST /school/student { "name": "hello", "age": 18, "course": "elasticsearch", "study_date": "2018-08-20T20:30:50", "mark": "take care day day" }
-
可視化操作watcher,可以啟用、禁用、添加修改、刪除watcher
-
## watch使用文章:https://www.cnblogs.com/reboot51/p/8328720.html
watcher使用:
## 創建一個watcher,比如定義一個trigger 每個10s鍾看一下input里的數據 PUT _xpack/watcher/watch/applog_error_watcher { "trigger": { "schedule": { "interval": "10s" } }, "input": { "search": { "request": { "indices": ["javalog-app-*"], "body": { "size": 0, "query": { "match": { "level": "ERROR" } } } } } }, "condition": { "compare": { "ctx.payload.hits.total": { "gt": 0 } } }, "transform": { "search": { "request": { "indices": ["javalog-app-*"], "body": { "size": 10, "query": { "match": { "name": "hello" } } } } } }, "actions": { "test_error": { "throttle_period": "1m", "webhook" : { "method" : "POST", "url" : "http://192.168.11.32:8001/watch", "body" : "{ \"title\": \"異常錯誤告警\", \"traceId\": \"{{#ctx.payload.hits.hits}} {{_source.traceId}} {{/ctx.payload.hits.hits}}\", \"spanId\" : \"{{#ctx.payload.hits.hits}} {{_source.spanId}} {{/ctx.payload.hits.hits}}\", \"level\":\"告警級別P1\", \"body\": \"{{#ctx.payload.hits.hits}} {{_source.messageInfo}} {{/ctx.payload.hits.hits}}\" } } } } } ## {{#ctx.payload.hits.hits}} {{_source.traceId}} {{/ctx.payload.hits.hits}} ## {{#ctx.payload.hits.hits}} {{_source.spanId}} {{/ctx.payload.hits.hits}} ## {{#ctx.payload.hits.hits}} {{_source.messageInfo}} {{/ctx.payload.hits.hits}} ## 查詢error GET javalog-app-2019.01.24/_search { "query": { "match": { "level.keyword": "ERROR" } } } # 查看一個watcher # GET _xpack/watcher/watch/applog_error_watcher #刪除一個watcher # DELETE _xpack/watcher/watch/applog_error_watcher #執行watcher # POST _xpack/watcher/watch/applog_error_watcher/_execute #查看執行結果 GET /.watcher-history*/_search?pretty { "sort" : [ { "result.execution_time" : "desc" } ], "query": { "match": { "watch_id": "applog_error_watcher" } } }