Watcher

Les fonctions d’alerte vous permettent de surveiller les changements ou les anomalies dans vos données et d’effectuer les actions nécessaires en conséquence. Par exemple, vous pourriez vouloir :

  • Surveiller les médias sociaux comme un autre moyen de détecter les défaillances des systèmes automatisés en contact avec l’utilisateur, comme les distributeurs automatiques de billets ou les systèmes de billetterie. Lorsque le nombre de tweets et de posts dans une zone dépasse un seuil d’importance, prévenez un technicien de service.
  • Surveiller votre infrastructure, en suivant l’utilisation des disques dans le temps. Ouvrez un ticket de service d’assistance lorsque l’un des serveurs risque de manquer d’espace libre dans les prochains jours.
  • Suivez l’activité du réseau pour détecter les activités malveillantes et modifiez de manière proactive la configuration du pare-feu pour rejeter l’utilisateur malveillant.
  • Surveiller Elasticsearch, et envoyer une notification immédiate à l’administrateur système si des nœuds quittent le cluster ou si le débit des requêtes dépasse un certain seuil.
  • Surveillez les temps de réponse des applications et si le temps de chargement des pages dépasse les SLA pendant plus de 5 minutes, ouvrez un ticket de service d’assistance. Si les SLA sont dépassés pendant une heure, contactez l’administrateur en service.

Tous ces cas d’utilisation partagent quelques propriétés clés :

  • Les données pertinentes ou les modifications de données peuvent être identifiées par une requête périodique de recherche élastique.
  • Les résultats de la requête peuvent être vérifiés par rapport à une condition.
  • Une ou plusieurs actions sont entreprises si la condition est vraie - un courriel est envoyé, un système tiers est notifié ou les résultats de la requête sont stockés.

Voici deux exemple fonctionnel de mise en place de seuil d’alerte sur la mémoire disque et ram.

POST _watcher/watch/free_disk_space
{
    "trigger" : {
      "schedule" : {
        "interval" : "5m"
      }
    },
    "input" : {
      "search" : {
        "request" : {
          "search_type" : "query_then_fetch",
          "indices" : [
            ".monitoring-es-7*"
          ],
          "rest_total_hits_as_int" : true,
          "body" : {
            "query" : {
              "bool" : {
                "filter" : [
                  {
                    "range" : {
                      "timestamp" : {
                        "gte" : "{{ctx.trigger.scheduled_time}}||-5m"
                      }
                    }
                  }
                ]
              }
            },
            "aggs" : {
              "nodes" : {
                "terms" : {
                  "field" : "source_node.name",
                  "size" : 100
                },
                "aggs" : {
                  "total_in_bytes" : {
                    "max" : {
                      "field" : "node_stats.fs.total.total_in_bytes"
                    }
                  },
                  "available_in_bytes" : {
                    "max" : {
                      "field" : "node_stats.fs.total.available_in_bytes"
                    }
                  },
                  "free_ratio" : {
                    "bucket_script" : {
                      "buckets_path" : {
                        "available_in_bytes" : "available_in_bytes",
                        "total_in_bytes" : "total_in_bytes"
                      },
                      "script" : "params.available_in_bytes / params.total_in_bytes"
                    }
                  }
                }
              }
            },
            "size" : 0
          }
        }
      }
    },
    "condition" : {
      "script" : {
        "source" : "return ctx.payload.aggregations.nodes.buckets.stream().anyMatch(it -> it.free_ratio.value < ctx.metadata.lower_bound);",
        "lang" : "painless"
      }
    },
    "transform" : {
      "script" : {
        "source" : "ctx.payload.aggregations.nodes.buckets.stream().filter(it -> it.free_ratio.value < ctx.metadata.lower_bound).map(it -> ['node_name':it.key,'ratio':it.free_ratio.value, 'available_in_gb':Math.round((it.available_in_bytes.value/1073741824) * 100)/100,'total_in_gb':Math.round((it.total_in_bytes.value/1073741824)* 100)/100]).collect(Collectors.toList());",
        "lang" : "painless"
      }
    },
     "throttle_period" : "24h",
     "actions" : {
      "email_report" : {
        "email" : {
          "profile" : "standard",
          "to" : [
            "MAILLIST"
          ],
          "subject" : "[ELK - Incident] Espace disque faible",
          "body" : {
            "html" : "<p> Available space on Filesystem: {{it.free_ratio.value}} is below recommended ratio of {{ctx.metadata.lower_bound}} for following nodes: {{#ctx.payload._value}} <br> For node {{node_name}}: <br> {{available_in_gb}}gb of {{total_in_gb}}gb is available : {{ratio}} {{/ctx.payload._value}} </p>"
          }
        }
      }
    },
    "metadata" : {
      "lower_bound" : 0.3,
      "name" : "free_disk_space",
      "xpack" : {
        "type" : "json"
      }
    }
  }
POST _watcher/watch/check_memory
{
  "trigger": {
    "schedule": {
      "interval": "5m"
    }
  },
  "input": {
    "search": {
      "request": {
        "search_type": "query_then_fetch",
        "indices": [
          ".monitoring-es-7*"
        ],
        "rest_total_hits_as_int": true,
        "body": {
          "query": {
            "bool": {
              "filter": [
                {
                  "range": {
                    "timestamp": {
                      "gte": "{{ctx.trigger.scheduled_time}}||-5m"
                    }
                  }
                },
                {
                  "exists": {
                    "field": "node_stats.jvm.mem.heap_used_percent"
                  }
                }
              ]
            }
          },
          "aggs": {
            "nodes": {
              "terms": {
                "field": "source_node.name",
                "size": 100
              },
              "aggs": {
                "heap_used_percent": {
                  "max": {
                    "field": "node_stats.jvm.mem.heap_used_percent"
                  }
                }
              }
            }
          },
          "size": 0
        }
      }
    }
  },
  "condition": {
    "script": {
      "source": "return ctx.payload.aggregations.nodes.buckets.stream().anyMatch(it -> it.heap_used_percent.value > ctx.metadata.higher_bound);",
      "lang": "painless"
    }
  },
   "throttle_period" : "24h",
   "actions": {
   "email_report": {
      "email": {
        "profile": "standard",
        "to": [
          "MAILIST"
        ],
        "subject": "[ELK - WARNING] JVM Memory too high",
        "body": {
          "html": "<p> JVM Usage on node is below recommended ratio of {{ctx.metadata.higher_bound}}%  for following nodes: <br>{{#ctx.payload._value}} <br>   <br> For node {{node_name}}: {{heap_used}} %  {{/ctx.payload._value}}</p>"
        }
      }
    }
  },
  "metadata": {
    "higher_bound": 75,
    "name" : "check_memory"
  },
  "transform": {
    "script": {
      "source": "ctx.payload.aggregations.nodes.buckets.stream().filter(it -> it.heap_used_percent.value > ctx.metadata.higher_bound).map(it -> ['node_name':it.key,'heap_used':it.heap_used_percent.value]).collect(Collectors.toList());",
      "lang": "painless"
    }
  }
}