MetadataHandler returns metric metadata held by Cortex for a given tenant. It is kept and returned as a set.
(m MetadataQuerier)
| 44 | // MetadataHandler returns metric metadata held by Cortex for a given tenant. |
| 45 | // It is kept and returned as a set. |
| 46 | func MetadataHandler(m MetadataQuerier) http.Handler { |
| 47 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| 48 | limit, err := validateLimits("limit", w, r) |
| 49 | if err != nil { |
| 50 | return |
| 51 | } |
| 52 | |
| 53 | limitPerMetric, err := validateLimits("limit_per_metric", w, r) |
| 54 | if err != nil { |
| 55 | return |
| 56 | } |
| 57 | |
| 58 | metric := r.FormValue("metric") |
| 59 | req := &client.MetricsMetadataRequest{ |
| 60 | Limit: int64(limit), |
| 61 | LimitPerMetric: int64(limitPerMetric), |
| 62 | Metric: metric, |
| 63 | } |
| 64 | |
| 65 | resp, err := m.MetricsMetadata(r.Context(), req) |
| 66 | if err != nil { |
| 67 | w.WriteHeader(http.StatusBadRequest) |
| 68 | util.WriteJSONResponse(w, metadataErrorResult{Status: statusError, Error: err.Error()}) |
| 69 | return |
| 70 | } |
| 71 | |
| 72 | // Put all the elements of the pseudo-set into a map of slices for marshalling. |
| 73 | metrics := map[string][]metricMetadata{} |
| 74 | for _, m := range resp { |
| 75 | ms, ok := metrics[m.MetricFamily] |
| 76 | // We have to check limit both ingester and here since the ingester only check |
| 77 | // for one user, it cannot handle the case when the mergeMetadataQuerier |
| 78 | // (tenant-federation) is used. |
| 79 | if limitPerMetric > 0 && len(ms) >= limitPerMetric { |
| 80 | continue |
| 81 | } |
| 82 | |
| 83 | if !ok { |
| 84 | if limit >= 0 && len(metrics) >= limit { |
| 85 | break |
| 86 | } |
| 87 | // Most metrics will only hold 1 copy of the same metadata. |
| 88 | ms = make([]metricMetadata, 0, 1) |
| 89 | metrics[m.MetricFamily] = ms |
| 90 | } |
| 91 | metrics[m.MetricFamily] = append(ms, metricMetadata{Type: string(m.Type), Help: m.Help, Unit: m.Unit}) |
| 92 | } |
| 93 | |
| 94 | util.WriteJSONResponse(w, metadataSuccessResult{Status: statusSuccess, Data: metrics}) |
| 95 | }) |
| 96 | } |
| 97 | |
| 98 | func validateLimits(name string, w http.ResponseWriter, r *http.Request) (int, error) { |
| 99 | v := defaultLimit |