Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
tsoc
hg-misc-tools
Commits
a72f012f
Commit
a72f012f
authored
Mar 24, 2026
by
one
Browse files
[xcl-lens] Improve topo mapping report
parent
a4e38ce1
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
88 additions
and
75 deletions
+88
-75
projects/xcl-lens/src/xcl_lens/parser/rccl.py
projects/xcl-lens/src/xcl_lens/parser/rccl.py
+88
-75
No files found.
projects/xcl-lens/src/xcl_lens/parser/rccl.py
View file @
a72f012f
...
...
@@ -113,8 +113,28 @@ class RcclLogParser:
print
(
f
"
{
field
}
:
{
values
[
0
]
}
"
)
continue
print
(
f
"
{
field
}
: (WARNING: Different values across ranks)"
)
for
(
host
,
rank
),
field_values
in
sorted
(
entries
.
items
()):
host_values
=
{}
host_has_rank_conflict
=
set
()
for
(
host
,
_rank
),
field_values
in
entries
.
items
():
host_values
.
setdefault
(
host
,
set
()).
update
(
field_values
)
if
len
(
field_values
)
>
1
:
host_has_rank_conflict
.
add
(
host
)
for
host
,
field_values
in
host_values
.
items
():
if
len
(
field_values
)
>
1
:
host_has_rank_conflict
.
add
(
host
)
warning_scope
=
"nodes"
if
len
(
host_values
)
>
1
else
"ranks"
print
(
f
"
{
field
}
: (WARNING: Different values across
{
warning_scope
}
)"
)
for
host
in
sorted
(
host_values
):
if
host
not
in
host_has_rank_conflict
:
joined
=
" | "
.
join
(
sorted
(
host_values
[
host
]))
print
(
f
"
{
host
}
:
{
joined
}
"
)
continue
for
(
entry_host
,
rank
),
field_values
in
sorted
(
entries
.
items
()):
if
entry_host
!=
host
:
continue
joined
=
" | "
.
join
(
sorted
(
field_values
))
print
(
f
"
{
host
}
rank
{
rank
}
:
{
joined
}
"
)
print
()
...
...
@@ -448,88 +468,81 @@ class RcclLogParser:
print
(
df
.
to_string
(
index
=
False
))
print
()
def
_report_aggregated_info
(
self
,
title
:
str
,
filter_func
,
patterns
:
list
,
accumulate_fields
:
set
,
col_order
:
list
,
):
"""
Generic method for sections where multiple log lines contribute different
fields to a single per-(host, rank) record.
Unlike _extract_and_print (one line → all fields), this aggregates
across lines: each line may fill one field of the record.
Args:
title: Section title.
filter_func: Pre-filter for log content (content -> bool).
patterns: List of (search_pattern, field, group_idx, literal).
accumulate_fields: Fields that collect values across multiple lines (stored as set).
col_order: Preferred column display order.
"""
print
(
f
"===>
{
title
}
:
\n
"
)
def
_report_topo_mapping_info
(
self
):
print
(
"===> Topology Mapping File Info:
\n
"
)
records
:
dict
[
tuple
,
dict
]
=
{}
topo_mapping_patterns
=
[
(
r
"No topo mapping file"
,
"status"
,
None
,
"no_file"
),
(
r
"environmental key word is (\S+)"
,
"fingerprint"
,
1
,
None
),
(
r
"Loading topology mapping file (\S+)"
,
"loaded"
,
1
,
None
),
(
r
"(?:parseing|parsing) topology mapping group[:\s]*(.*)"
,
"parsed"
,
1
,
None
),
(
r
"skip topology mapping group:\s*([^,]+)"
,
"skipped"
,
1
,
None
),
]
records
=
{}
for
host
,
rank
,
content
in
self
.
log_entries
:
if
not
filter_func
(
content
):
if
not
any
(
s
in
content
.
lower
()
for
s
in
(
"topo mapping"
,
"topology mapping"
,
"environmental key word"
)
):
continue
for
pattern
,
field
,
group_idx
,
literal
in
patterns
:
for
pattern
,
field
,
group_idx
,
literal
in
topo_mapping_
patterns
:
m
=
re
.
search
(
pattern
,
content
,
re
.
IGNORECASE
)
if
m
:
key
=
(
host
,
rank
)
rec
=
records
.
setdefault
(
key
,
{
"host"
:
host
,
"rank"
:
rank
})
if
not
m
:
continue
rec
=
records
.
setdefault
(
(
host
,
rank
)
,
{
"host"
:
host
,
"rank"
:
rank
})
value
=
(
literal
if
group_idx
is
None
else
m
.
group
(
group_idx
).
strip
())
or
"-"
if
field
in
accumulate_fields
:
if
field
in
{
"parsed"
,
"skipped"
}
:
rec
.
setdefault
(
field
,
set
()).
add
(
value
)
else
:
rec
[
field
]
=
value
break
# each line matches at most one pattern
break
if
not
records
:
print
(
" (No data found)
\n
"
)
return
# Flatten accumulated sets → sorted string
for
rec
in
records
.
values
():
for
field
in
accumulate_fields
:
for
field
in
(
"parsed"
,
"skipped"
)
:
if
field
in
rec
:
rec
[
field
]
=
" | "
.
join
(
sorted
(
rec
[
field
]))
df
=
pd
.
DataFrame
(
list
(
records
.
values
()))
df
.
sort_values
(
by
=
[
"host"
,
"rank"
],
inplace
=
True
)
ordered
=
[
c
for
c
in
col_order
if
c
in
df
.
columns
]
remaining
=
[
c
for
c
in
df
.
columns
if
c
not
in
ordered
]
df
=
df
[
ordered
+
remaining
]
print
(
df
.
fillna
(
"-"
).
to_string
(
index
=
False
))
rec
[
field
]
=
sorted
(
rec
[
field
])
if
rec
.
get
(
"status"
)
==
"no_file"
:
continue
if
rec
.
get
(
"parsed"
):
rec
[
"status"
]
=
"parsed"
elif
rec
.
get
(
"skipped"
):
rec
[
"status"
]
=
"skipped"
else
:
rec
[
"status"
]
=
"-"
by_host
=
{}
for
(
host
,
rank
),
rec
in
records
.
items
():
by_host
.
setdefault
(
host
,
[]).
append
((
rank
,
rec
))
field_order
=
[
"status"
,
"fingerprint"
,
"loaded"
,
"parsed"
,
"skipped"
]
for
host
in
sorted
(
by_host
):
print
(
host
)
host_records
=
sorted
(
by_host
[
host
],
key
=
lambda
item
:
item
[
0
])
normalized
=
[
{
field
:
rec
.
get
(
field
,
"-"
)
for
field
in
field_order
}
for
_
,
rec
in
host_records
]
if
len
({
repr
(
item
)
for
item
in
normalized
})
==
1
:
self
.
_print_topo_record
(
normalized
[
0
],
indent
=
" "
)
print
()
continue
def
_report_topo_mapping_info
(
self
):
# (search_pattern, field_name, capture_group_index_or_None, literal_value_or_None)
# - capture_group_index: int → get regex group, None → use literal_value
# - accumulate: True → this field may come from multiple lines, append rather than overwrite
topo_mapping_patterns
=
[
(
r
"No topo mapping file"
,
"status"
,
None
,
"no_file"
),
(
r
"environmental key word is (\S+)"
,
"fingerprint"
,
1
,
None
),
(
r
"Loading topology mapping file (\S+)"
,
"loaded"
,
1
,
None
),
(
r
"(?:parseing|parsing) topology mapping group[:\s]*(.*)"
,
"parsed"
,
1
,
None
),
(
r
"skip topology mapping group:\s*([^,]+)"
,
"skipped"
,
1
,
None
),
]
# Fields that should accumulate across multiple matching lines (per host/rank)
topo_mapping_accumulate_fields
=
{
"skipped"
,
"parsed"
}
for
rank
,
rec
in
host_records
:
print
(
f
" rank
{
rank
}
"
)
self
.
_print_topo_record
(
rec
,
indent
=
" "
)
print
()
self
.
_report_aggregated_info
(
title
=
"Topology Mapping File Info"
,
filter_func
=
lambda
c
:
any
(
s
in
c
.
lower
(
)
for
s
in
(
"
topo mapping"
,
"topology mapping"
,
"environmental key wor
d"
)
),
patterns
=
topo_mapping_patterns
,
accumulate_fields
=
topo_mapping_accumulate_
field
s
,
col_order
=
[
"host"
,
"rank"
,
"status"
,
"fingerprint"
,
"loaded"
,
"parsed"
,
"skipped"
],
)
def
_print_topo_record
(
self
,
record
,
indent
):
for
field
in
(
"status"
,
"fingerprint"
,
"loaded"
):
if
field
in
record
:
print
(
f
"
{
indent
}{
field
}
:
{
record
[
field
]
}
"
)
for
field
in
(
"
parsed"
,
"skippe
d"
)
:
if
field
not
in
record
:
continue
print
(
f
"
{
indent
}{
field
}
:"
)
for
value
in
record
[
field
]:
print
(
f
"
{
indent
}
{
value
}
"
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment