2014-11-18 3 views
3

Я вычисляю продолжительность моих сервис-процессов, используя SUM-Aggregation. Каждый шаг выполненного процесса будет сохранен в Elasticsearch под идентификатором вызова.Elasticsearch: Можно обрабатывать результаты агрегации?

Это то, что я контролирую:

Duration of Request-Processing for ID #123 (calling service #1) 

Duration of Server-Response for ID #123 (calling service #1) 

**Complete Duration for ID #123** 

Duration of Request-Processing for ID #124 (calling service #1) 

Duration of Server-Response for ID #124 (calling service #1) 

**Complete duration for ID #124** 

Фильтр:

{ 
"from" : 0, "size" :0, 

    "query" : { 
     "filtered" : { 
      "query" : { "match_all" : {}}, 
      "filter" : { 
       "term" : { 
        "callingId" : "123", 
       } 
      } 
     } 
    }, 
    "aggs" : { 
     "total_duration" : { "sum" : { "field" : "duration" } }, 
     "max_duration":{"max": {"field":"duration"}}, 
     "min_duration":{"min":{"field":"duration"}} 
     } 
    } 
    } 

Это возвращает полную длительность процесса, а также говорит мне, какая часть процесса была самой быстрой анс, какая часть была самый медленный.

Дальше: Хочу рассчитать среднее значение длительность процесса производства по обслуживанию. В этом случае я забочусь только об общей продолжительности для каждой службы, поэтому я могу их скопировать.

Как я могу создать средний, минимальный и максимальный из моих total_durations?

EDIT: Я добавил несколько примеров данных, надеюсь, вы сможете с ним работать.

call1:

{ 
"callerId":"U1", 
"operation":"Initialize", 
"status":"INITIALIZED", 
"duration":1, 
"serviceId":"1" 
} 

{ 
"callerId":"U1", 
"operation":"Calculate", 
"status":"STARTED", 
"duration":1, 
"serviceId":"1" 
} 

{ 
"callerId":"U1", 
"operation":"Finish", 
"status":"FINISHED", 
"duration":1200, 
"serviceId":"1" 
} 

sum: 1202 

вызов 2:

{ 
"callerId":"U2", 
"operation":"Initialize", 
"status":"INITIALIZED", 
"duration":2, 
"serviceId":"1" 
} 

{ 
"callerId":"U2", 
"operation":"Calculate", 
"status":"STARTED", 
"duration":1, 
"serviceId":"1" 
} 

{ 
"callerId":"U2", 
"operation":"Finish", 
"status":"FINISHED", 
"duration":1030, 
"serviceId":"1" 
} 

sum: 1033 

Aggregation для всех Сервис-вызовов для Service ID # 1 Это то, что я хочу, чтобы вычислить:

Max: 1202 
Min: 1033 
AVG: 1116 
+0

Можете ли вы поделиться некоторыми данные? И отображение вашего индекса? –

+0

сделано, я надеюсь, что это полезно – Goot

ответ

3

Немного сложнее, но вот это g OES (только в 1,4 из this type of aggregation):

{ 
    "query": { 
    "filtered": { 
     "query": { 
     "match_all": {} 
     }, 
     "filter": { 
     "term": { 
      "serviceId": 1 
     } 
     } 
    } 
    }, 
    "aggs": { 
    "executionTimes": { 
     "scripted_metric": { 
     "init_script": "_agg['values'] = new java.util.HashMap();", 
     "map_script": "if (_agg.values[doc['callerId'].value]==null) {_agg.values[doc['callerId'].value]=doc['duration'].value;} else {_agg.values[doc['callerId'].value].add(doc['duration'].value);}", 
     "combine_script":"someHashMap = new java.util.HashMap();for(x in _agg.values.keySet()) {value=_agg.values[x]; sum=0; for(y in value) {sum+=y}; someHashMap.put(x,sum)}; return someHashMap;", 
     "reduce_script": "finalArray = []; finalMap = new java.util.HashMap(); for(map in _aggs){for(x in map.keySet()){if(finalMap.containsKey(x)){value=finalMap.get(x);finalMap.put(x,value+map.get(x));} else {finalMap.put(x,map.get(x))}}}; finalAvgValue=0; finalMaxValue=-1; finalMinValue=-1; for(key in finalMap.keySet()){currentValue=finalMap.get(key);finalAvgValue+=currentValue; if(finalMinValue<0){finalMinValue=currentValue} else if(finalMinValue>currentValue){finalMinValue=currentValue}; if(currentValue>finalMaxValue) {finalMaxValue=currentValue}}; finalArray.add(finalMaxValue); finalArray.add(finalMinValue); finalArray.add(finalAvgValue/finalMap.size()); return finalArray", 
     "lang": "groovy" 
     } 
    } 
    } 
} 

Кроме того, я не говорю, что это лучший подход, но только один я смог найти. Кроме того, я не говорю, что решение в лучшем виде. Возможно, он может быть очищен и улучшен. Я хотел показать, однако, что это возможно. Имейте в виду, что это доступно в 1.4.

Основная идея подхода заключается в использовании сценариев для построения структуры данных, которая должна содержать необходимую вам информацию, вычисляемой на разных этапах согласно scripted metric aggregation. Кроме того, агрегация выполняется только для одного serviceId. Если вы хотите сделать это для всех serviceIds, я думаю, вам может понадобиться немного подумать о структуре данных в сценариях.

Для запроса выше, и для точных данных вы предусмотрели вывод заключается в следующем:

{ 
    "took": 3, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 6, 
     "max_score": 0, 
     "hits": [] 
    }, 
    "aggregations": { 
     "executionTimes": { 
     "value": [ 
      1202, 
      1033, 
      "1117.5" 
     ] 
     } 
    } 
} 

Порядок значений в массиве value это [макс, мин, ср], в соответствии со сценарием в reduce_script ,

+0

Фантастический! Я надеялся на такой подход, пока Reducers не прибудут в версии 2.0.0. Я дам ему попробовать. Поскольку я доверяю вашему ответу, я сразу приму это. благодаря – Goot