in pilot/pkg/model/telemetry.go [553:698]
func mergeMetrics(metrics []*tpb.Metrics, mesh *meshconfig.MeshConfig) map[string]metricsConfig {
type metricOverride struct {
Disabled *wrappers.BoolValue
TagOverrides map[string]*tpb.MetricsOverrides_TagOverride
}
// provider -> mode -> metric -> overrides
providers := map[string]map[tpb.WorkloadMode]map[string]metricOverride{}
if len(metrics) == 0 {
for _, dp := range mesh.GetDefaultProviders().GetMetrics() {
// Insert the default provider. It has no overrides; presence of the key is sufficient to
// get the filter created.
providers[dp] = map[tpb.WorkloadMode]map[string]metricOverride{}
}
}
providerNames := mesh.GetDefaultProviders().GetMetrics()
for _, m := range metrics {
names := getProviderNames(m.Providers)
// If providers is set, it overrides the parent. If not, inherent from the parent. It is not a deep merge.
if len(names) > 0 {
providerNames = names
}
}
// Record the names of all providers we should configure. Anything else we will ignore
inScopeProviders := sets.New(providerNames...)
parentProviders := mesh.GetDefaultProviders().GetMetrics()
disabledAllMetricsProviders := sets.New()
for _, m := range metrics {
providerNames := getProviderNames(m.Providers)
// If providers is not set, use parent's
if len(providerNames) == 0 {
providerNames = parentProviders
}
parentProviders = providerNames
for _, provider := range providerNames {
if !inScopeProviders.Contains(provider) {
// We don't care about this, remove it
// This occurs when a top level provider is later disabled by a lower level
continue
}
if _, f := providers[provider]; !f {
providers[provider] = map[tpb.WorkloadMode]map[string]metricOverride{
tpb.WorkloadMode_CLIENT: {},
tpb.WorkloadMode_SERVER: {},
}
}
mp := providers[provider]
// For each override, we normalize the configuration. The metrics list is an ordered list - latter
// elements have precedence. As a result, we will apply updates on top of previous entries.
for _, o := range m.Overrides {
// if we disable all metrics, we should drop the entire filter
if isAllMetrics(o.GetMatch()) && o.Disabled.GetValue() {
disabledAllMetricsProviders.Insert(provider)
continue
}
// root namespace disables all, but then enables them by namespace scoped
disabledAllMetricsProviders.Delete(provider)
metricsNames := getMatches(o.GetMatch())
// If client or server is set explicitly, only apply there. Otherwise, we will apply to both.
// Note: client and server keys may end up the same, which is fine
for _, mode := range getModes(o.GetMatch().GetMode()) {
// Next, get all matches.
// This is a bit funky because the matches are oneof of ENUM and customer metric. We normalize
// these to strings, so we may end up with a list like [REQUEST_COUNT, my-customer-metric].
// TODO: we always flatten ALL_METRICS into each metric mode. For some stats providers (prometheus),
// we are able to apply overrides to all metrics directly rather than duplicating the config.
// We should tweak this to collapse to this mode where possible
for _, metricName := range metricsNames {
if _, f := mp[mode]; !f {
mp[mode] = map[string]metricOverride{}
}
override := mp[mode][metricName]
if o.Disabled != nil {
override.Disabled = o.Disabled
}
for k, v := range o.TagOverrides {
if override.TagOverrides == nil {
override.TagOverrides = map[string]*tpb.MetricsOverrides_TagOverride{}
}
override.TagOverrides[k] = v
}
mp[mode][metricName] = override
}
}
}
}
}
processed := map[string]metricsConfig{}
for provider, modeMap := range providers {
if disabledAllMetricsProviders.Contains(provider) {
continue
}
for mode, metricMap := range modeMap {
for metric, override := range metricMap {
tags := []tagOverride{}
for k, v := range override.TagOverrides {
o := tagOverride{Name: k}
switch v.Operation {
case tpb.MetricsOverrides_TagOverride_REMOVE:
o.Remove = true
o.Value = ""
case tpb.MetricsOverrides_TagOverride_UPSERT:
o.Value = v.GetValue()
o.Remove = false
}
tags = append(tags, o)
}
// Keep order deterministic
sort.Slice(tags, func(i, j int) bool {
return tags[i].Name < tags[j].Name
})
mo := metricsOverride{
Name: metric,
Disabled: override.Disabled.GetValue(),
Tags: tags,
}
tmm := processed[provider]
switch mode {
case tpb.WorkloadMode_CLIENT:
tmm.ClientMetrics = append(tmm.ClientMetrics, mo)
default:
tmm.ServerMetrics = append(tmm.ServerMetrics, mo)
}
processed[provider] = tmm
}
}
// Keep order deterministic
tmm := processed[provider]
sort.Slice(tmm.ServerMetrics, func(i, j int) bool {
return tmm.ServerMetrics[i].Name < tmm.ServerMetrics[j].Name
})
sort.Slice(tmm.ClientMetrics, func(i, j int) bool {
return tmm.ClientMetrics[i].Name < tmm.ClientMetrics[j].Name
})
processed[provider] = tmm
}
return processed
}