Groovy:如何按部署环境分组指标生成目标映射表?
按部署环境分组指标的Groovy实现方法
问题描述
我不是Groovy专家,现有如下JSON格式的Metrics数据:
{ "metrics": [ { "name": "metric_a", "help": "This tracks your A stuff.", "type": "GAUGE", "labels": ["pool"], "unit": "", "aggregates": [], "meta": [ { "category": "CAT A", "deployment": "environment-a" } ], "additional_notes": "Some stuff (potentially)" }, ... ] ... }
我需要将这些指标按部署环境(deployment字段)组织成一个映射表:以部署环境为键,对应环境下的所有指标名称数组为值。
当前尝试的代码无法实现预期效果,所有指标都被加入到同一个列表中:
parentChild = [:] children = [] metrics.each { metric -> def metricName = metric.name def depName = metric.meta.findResult{ it.deployment } children.add(metricName) parentChild.put(depName, children) }
期望得到的结果:
[environment-a: [metric_a,metric_b,metric_c,...], environment-b: [metric_d,metric_e,metric_f,...] ...]
请问实现这种分组映射的最优方法是什么?
解决方案
问题根源
你当前代码的问题在于,所有部署环境都共用了同一个children列表对象。每次向children添加指标名称时,所有环境对应的列表都会同步变化,最终所有键都指向同一个包含所有指标的列表。
方法一:使用groupBy(最优方案)
Groovy的groupBy方法可以直接按指定条件对集合分组,再通过collectEntries将分组后的结果映射为「环境名→指标名列表」的结构:
def envToMetrics = metrics.groupBy { metric -> // 从meta中提取部署环境,找不到则返回默认值(比如"unknown") metric.meta.findResult { it.deployment } ?: "unknown" }.collectEntries { env, metricsInEnv -> [env, metricsInEnv*.name] }
groupBy先将指标按部署环境分组,得到一个键为环境名、值为对应指标对象列表的Map;collectEntries遍历这个Map,将每个值转换为指标名称的列表,最终得到你需要的结构。
方法二:修复原代码逻辑
如果不想用groupBy,可以修改原代码,为每个环境单独创建列表:
def parentChild = [:] metrics.each { metric -> def metricName = metric.name def depName = metric.meta.findResult{ it.deployment } ?: "unknown" // 如果该环境还没有对应的列表,就新建一个 if (!parentChild.containsKey(depName)) { parentChild[depName] = [] } // 向对应环境的列表添加指标名称 parentChild[depName].add(metricName) }
这种方式手动管理每个环境的列表,避免了共用同一个列表的问题。
内容的提问来源于stack exchange,提问作者Jason Davis
相关产品推荐
相关产品推荐

