{"record":{"id":"16fa51bc5a05af75","repo":"jaegertracing/jaeger","slug":"failed-to-convert-aggregations-to-metrics-w","errorCode":null,"errorMessage":"failed to convert aggregations to metrics: %w","messagePattern":"failed to convert aggregations to metrics: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/metricstore/elasticsearch/to_domain.go","lineNumber":34,"sourceCode":"\n// Translator converts raw Elasticsearch aggregation results into Jaeger's metrics domain model\n// (metrics.MetricFamily). It uses a configurable function to extract values from buckets,\n// ensuring flexibility across different metric types (e.g., latencies, call rates).\ntype Translator struct {\n\tbucketsToPointsFunc func(buckets []esclient.HistogramBucket) []*Pair\n}\n\nfunc NewTranslator(bucketsToPointsFunc func(buckets []esclient.HistogramBucket) []*Pair) Translator {\n\treturn Translator{\n\t\tbucketsToPointsFunc: bucketsToPointsFunc,\n\t}\n}\n\n// ToDomainMetricsFamily converts Elasticsearch aggregations to Jaeger's MetricFamily.\nfunc (t *Translator) ToDomainMetricsFamily(m MetricsQueryParams, result *esclient.SearchResponse) (*metrics.MetricFamily, error) {\n\tdomainMetrics, err := t.toDomainMetrics(m, result)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to convert aggregations to metrics: %w\", err)\n\t}\n\n\tif m.GroupByOperation {\n\t\tm.metricName = strings.Replace(m.metricName, \"service\", \"service_operation\", 1)\n\t\tm.metricDesc += \" & operation\"\n\t}\n\n\treturn &metrics.MetricFamily{\n\t\tName:    m.metricName,\n\t\tType:    metrics.MetricType_GAUGE,\n\t\tHelp:    m.metricDesc,\n\t\tMetrics: domainMetrics,\n\t}, nil\n}\n\n// toDomainMetrics converts Elasticsearch aggregations to Jaeger metrics.\nfunc (t *Translator) toDomainMetrics(m MetricsQueryParams, result *esclient.SearchResponse) ([]*metrics.Metric, error) {\n\tlabels := buildServiceLabels(m.ServiceNames)","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/jaegertracing/jaeger/blob/806f4447841ecdb60519f408b004a599d515f437/internal/storage/metricstore/elasticsearch/to_domain.go#L16-L52","documentation":"Translator.ToDomainMetricsFamily converts an Elasticsearch SearchResponse's aggregations into Jaeger's MetricFamily. If the internal toDomainMetrics step fails — e.g. aggregations are missing or malformed — the error is wrapped with this message so callers know the ES response could not be translated, distinguishing translation failures from query execution failures.","triggerScenarios":"Calling ToDomainMetricsFamily with a SearchResponse whose Aggregations do not contain the expected date_histogram (or terms, when GroupByOperation is set) aggregations, or whose buckets fail processing.","commonSituations":"Querying an ES cluster/index where the Jaeger metrics rollup jobs were never configured; response shape changed between ES versions; a proxy returning an error body that partially parses as a SearchResponse.","solutions":["Check the wrapped cause: usually '<aggName> aggregation not found' or 'failed to process bucket'.","Verify the queried time range contains data and that ES metrics aggregation jobs are enabled.","Confirm the response actually came from the Jaeger metrics indices, not an error page or different index."],"exampleFix":"// verify response before translation\nif result == nil || result.Aggregations == nil {\n  return nil, fmt.Errorf(\"empty aggregations in search response\")\n}\nfam, err := translator.ToDomainMetricsFamily(params, result)","handlingStrategy":"type-guard","validationCode":"if result == nil || result.Aggregations == nil || len(result.Aggregations) == 0 {\n  return fmt.Errorf(\"search response has no aggregations to convert\")\n}","typeGuard":"func hasAggregations(resp *esclient.SearchResponse, names ...string) bool {\n  if resp == nil || resp.Aggregations == nil {\n    return false\n  }\n  for _, n := range names {\n    if _, ok := resp.Aggregations[n]; !ok {\n      return false\n    }\n  }\n  return true\n}","tryCatchPattern":"fam, err := translator.ToDomainMetricsFamily(params, result)\nif err != nil {\n  log.Printf(\"translation failed: %v\", err) // wrapped cause names the missing agg\n  return emptyFamily\n}","preventionTips":["Verify the ES metrics rollup configuration exists before querying.","Compare the raw aggregation names in the traced response with the translator's expected constants.","Return an empty family gracefully when the time window has no data."],"tags":["elasticsearch","metrics","aggregation","translation"],"backgroundTag":"aggregation-mapping-failed","analyzedSha":"806f4447841ecdb60519f408b004a599d515f437","analyzedAt":"2026-09-01T02:39:22.140Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}