@@ -83,6 +83,26 @@ def _pick(labels: Dict[str, str], keys) -> Optional[str]:
8383 return None
8484
8585
86+ def _resolve_inst_key (rlabels : dict , project_id : str = "" ) -> str :
87+ """Build a globally unique instance key.
88+
89+ Redis standalone instance_id is a full GCP path (projects/…/instances/name)
90+ which is already globally unique. Valkey and Redis Cluster return short names
91+ via instance_id or cluster_id, so we prefix with project_id to avoid
92+ collisions across projects.
93+ """
94+ raw_id = (
95+ rlabels .get ("instance_id" )
96+ or rlabels .get ("cluster_id" )
97+ or rlabels .get ("resource_name" )
98+ or "unknown"
99+ )
100+ # Full GCP path (starts with "projects/") is already globally unique
101+ if raw_id .startswith ("projects/" ):
102+ return raw_id
103+ return f"{ project_id } /{ raw_id } " if project_id else raw_id
104+
105+
86106def _point_value (point , default = 0 ):
87107 """Extract a numeric value from a GCP monitoring point, handling both int64 and double types."""
88108 try :
@@ -163,12 +183,7 @@ def _accumulate_commands(results, table, product_name: str, project_id: str):
163183 mlabels = dict (ts .metric .labels )
164184
165185 # Identify instance/cluster id & node
166- inst_key = (
167- rlabels .get ("instance_id" )
168- or rlabels .get ("cluster_id" )
169- or rlabels .get ("resource_name" )
170- or "unknown"
171- )
186+ inst_key = _resolve_inst_key (rlabels , project_id )
172187 node_id = rlabels .get ("node_id" ) or rlabels .get ("shard_id" ) or "unknown"
173188 entry = _ensure_node_entry (table , inst_key , node_id )
174189
@@ -229,15 +244,10 @@ def _apply_processed_categories(table):
229244 del entry ["points" ]
230245
231246
232- def _attach_memory_usage (results , table , key_name = "BytesUsedForCache" ):
247+ def _attach_memory_usage (results , table , project_id = "" , key_name = "BytesUsedForCache" ):
233248 for ts in results :
234249 rlabels = dict (ts .resource .labels )
235- inst_key = (
236- rlabels .get ("instance_id" )
237- or rlabels .get ("cluster_id" )
238- or rlabels .get ("resource_name" )
239- or "unknown"
240- )
250+ inst_key = _resolve_inst_key (rlabels , project_id )
241251 node_id = rlabels .get ("node_id" ) or rlabels .get ("shard_id" ) or "unknown"
242252 if inst_key not in table or node_id not in table [inst_key ]:
243253 _ensure_node_entry (table , inst_key , node_id )
@@ -252,17 +262,12 @@ def _attach_memory_usage(results, table, key_name="BytesUsedForCache"):
252262 entry [key_name ] = max (prev , maxv )
253263
254264
255- def _attach_capacity_scalar (results , table , key_name = "MaxMemory" ):
265+ def _attach_capacity_scalar (results , table , project_id = "" , key_name = "MaxMemory" ):
256266 """Attach a capacity scalar (e.g., memory size); applies to all nodes within the instance/cluster."""
257267 cap_by_inst = defaultdict (int )
258268 for ts in results :
259269 rlabels = dict (ts .resource .labels )
260- inst_key = (
261- rlabels .get ("instance_id" )
262- or rlabels .get ("cluster_id" )
263- or rlabels .get ("resource_name" )
264- or "unknown"
265- )
270+ inst_key = _resolve_inst_key (rlabels , project_id )
266271 v_max = 0
267272 for point in ts .points :
268273 v = int (_point_value (point ))
@@ -277,7 +282,7 @@ def _attach_capacity_scalar(results, table, key_name="MaxMemory"):
277282 nodes [node_id ][key_name ] = cap_by_inst [inst_key ]
278283
279284
280- def _attach_node_role (results , table ):
285+ def _attach_node_role (results , table , project_id = "" ):
281286 """Set NodeRole using the dedicated replication/role metric.
282287
283288 The 'role' label on commands/calls is metadata — not its purpose to report
@@ -289,8 +294,8 @@ def _attach_node_role(results, table):
289294 """
290295 for ts in results :
291296 rlabels = dict (ts .resource .labels )
292- inst_key = rlabels . get ( "instance_id" ) or "unknown"
293- node_id = rlabels .get ("node_id" ) or "unknown"
297+ inst_key = _resolve_inst_key ( rlabels , project_id )
298+ node_id = rlabels .get ("node_id" ) or rlabels . get ( "shard_id" ) or "unknown"
294299 if inst_key not in table or node_id not in table [inst_key ]:
295300 continue
296301
@@ -350,7 +355,7 @@ def collect_for_product(
350355 )
351356 except Exception :
352357 mem_results = []
353- _attach_memory_usage (mem_results , table )
358+ _attach_memory_usage (mem_results , table , project_id = project_id )
354359 for inst_key , nodes in table .items ():
355360 for node_id , entry in nodes .items ():
356361 entry ["InstanceType" ] = instance_type_label
@@ -361,14 +366,16 @@ def collect_for_product(
361366 mem_results = _list_ts (
362367 client , project_name , metric_map ["memory_usage" ], interval
363368 )
364- _attach_memory_usage (mem_results , table )
369+ _attach_memory_usage (mem_results , table , project_id = project_id )
365370 except Exception :
366371 pass
367372
368373 # Capacity (MaxMemory) - instance/cluster level
369374 try :
370375 cap_results = _list_ts (client , project_name , metric_map ["max_memory" ], interval )
371- _attach_capacity_scalar (cap_results , table , key_name = "MaxMemory" )
376+ _attach_capacity_scalar (
377+ cap_results , table , project_id = project_id , key_name = "MaxMemory"
378+ )
372379 except Exception :
373380 pass
374381
@@ -378,7 +385,7 @@ def collect_for_product(
378385 role_results = _list_ts (
379386 client , project_name , metric_map ["replication_role" ], interval
380387 )
381- _attach_node_role (role_results , table )
388+ _attach_node_role (role_results , table , project_id = project_id )
382389 except Exception :
383390 pass
384391
0 commit comments