@fedor-sg
Инженер-программист

Как преобразовать результаты агрегации Elasticsearch в проценты и вывести сообщение в зависимости от результатов?

Имеется маппинг:
PUT /status_email/_mapping
{
  "status_email" : {
    "mappings" : {
      "properties" : {
        "date_consume_queue" : {
          "type" : "date",
          "format" : "yyyy-MM-dd HH:mm:ss.SSSZZ||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
        },
        "date_publish_queue" : {
          "type" : "date",
          "format" : "yyyy-MM-dd HH:mm:ss.SSSZZ||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
        },
        "date_send_message" : {
          "type" : "date",
          "format" : "yyyy-MM-dd HH:mm:ss.SSSZZ||yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
        },
        "email_to" : {
          "type" : "text",
          "fielddata" : true
        },
        "ip" : {
          "type" : "ip"
        },
        "log_level" : {
          "type" : "text",
          "fielddata" : true
        },
        "login" : {
          "type" : "text",
          "fielddata" : true
        },
        "message_id" : {
          "type" : "text",
          "fielddata" : true
        },
        "response_code" : {
          "type" : "text",
          "fielddata" : true
        },
        "response_text" : {
          "type" : "text",
          "fielddata" : true
        },
        "status" : {
          "type" : "boolean"
        },
        "uuid" : {
          "type" : "text",
          "fielddata" : true
        }
      }
    }
  }
}

На его основе размещаются документы, которые содержат статусы помещения писем в SMTP-сервер.

Необходимо агрегировать успешные и ошибочные статусы. Результаты агрегации перевести в процентное соотношение, если результат не превышает 10% ошибок, то выводить "OK", иначе "ERROR".

Пример одного из добавляемых документов:
{
  "date_publish_queue" : "2020-08-17 10:25:30.755+0300",
  "log_level" : "Info",
  "uuid" : "84d2cb67-dfca-44c0-bbfb-32ac8df39937",
  "email_to" : "test_1@mail.ru",
  "ip" : "::ffff:192.168.1.11",
  "login" : "test",
  "date_consume_queue" : "2020-08-17 10:25:31.075+0300",
  "response_code" : "250 2.0.0 Ok: queued as C7DF0122588",
  "date_send_message" : "2020-08-17 10:25:31.829+0300",
  "message_id" : "<96defcce-76f4-08ba-6483-5a0f709c2f0f@mail.ru>",
  "response_text" : "send",
  "status" : true
}

Пример моего запроса:
GET /status_email/_search?pretty
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date_publish_queue": {
              "gte": "now-1h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "smtp_bad": {
      "filter": {
        "bool": {
          "must_not": [
            {
              "exists": {
                "field": "status"
              }
            },
            {
              "match": {
                "status": "false"
              }
            },
            {
              "match_phrase": {
                "response_code": "250 2.0.0 Ok"
              }
            }
          ]
        }
      }
    },
    "smtp_good": {
      "filter": {
        "bool": {
          "must": [
            {
              "exists": {
                "field": "status"
              }
            },
            {
              "match": {
                "status": "true"
              }
            },
            {
              "match_phrase": {
                "response_code": "250 2.0.0 Ok"
              }
            }
          ]
        }
      }
    }
  }
}

Пример ответа на такой запрос:
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 200,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "smtp_bad" : {
      "doc_count" : 7
    },
    "smtp_good" : {
      "doc_count" : 193
    }
  }
}

Необходимо от этих значений посчитать проценты. Например:
  • Ошибочные отправки писем = 7 / 200 * 100 = 3.5%
  • Успешные отправки писем = 193 / 200 * 100 = 96.5%

Если процент превысит ошибочных отправлений превышает 10%, то необходимо вывести "ERROR", иначе вывести "OK".
Попробовал вычислить проценты успехов и ошибок отправки писем:
GET /status_email/_search?pretty
{
  "size": 0,
  "query": {
    "bool": {
      "must": [
        {
          "range": {
            "date_publish_queue": {
              "gte": "now-1h"
            }
          }
        }
      ]
    }
  },
  "aggs": {
    "result": {
      "terms": {
        "script": {
          "source": "'this a hack'"
        }
      },
      "aggs": {
        "smtp_bad": {
          "filter": {
            "bool": {
              "must_not": [
                {
                  "exists": {
                    "field": "status"
                  }
                },
                {
                  "match": {
                    "status": "false"
                  }
                },
                {
                  "match_phrase": {
                    "response_code": "250 2.0.0 Ok"
                  }
                }
              ]
            }
          }
        },
        "smtp_good": {
          "filter": {
            "bool": {
              "must": [
                {
                  "exists": {
                    "field": "status"
                  }
                },
                {
                  "match": {
                    "status": "true"
                  }
                },
                {
                  "match_phrase": {
                    "response_code": "250 2.0.0 Ok"
                  }
                }
              ]
            }
          }
        },
        "percent_smtp_good": {
          "bucket_script": {
            "buckets_path": {
              "total": "_count",
              "good": "smtp_good._count"
            },
            "script": {
              "params": {
                "full_percent": 100
              },
              "source": "params.good / params.total * params.full_percent"
            }
          }
        },
        "percent_smtp_bad": {
          "bucket_script": {
            "buckets_path": {
              "total": "_count",
              "bad": "smtp_bad._count"
            },
            "script": {
              "params": {
                "full_percent": 100
              },
              "source": "params.bad / params.total * params.full_percent"
            }
          }
        }
      }
    }
  }
}

Как можно организовать вывод строки в зависимости от результатов агрегации?
  • Вопрос задан
  • 85 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы