Skip to content

Standardize <invalid:VALUE> across __str__ #251

Description

@llucax

What's needed?

After #241, InvalidDeliveryArea.__str__ uses an explicit <invalid:VALUE> marker to flag invariant-violating fields (empty code, code_type=0). The same convention is being adopted in #248 (InvalidLatitude/Longitude/CountryCode, tracked via review comment r3589470688).

Several other wrapper types across the library carry malformed / unspecified / unrecognized data but don't yet follow this convention. They should be updated so grep '<invalid:' on logs finds every invariant violation regardless of which type produced it.

Rationale for the <invalid:VALUE> marker (over ! prefix/suffix, , class-name-only, or bare repr()): ASCII + greppable, composes per field, no collision with legitimate content. Full write-up at r3589470688 and reference implementation at commit 5688575.

Proposed solution

Existing wrapper types in this repo (no active PR):

Class File Current Needs
MetricConnection.__str__ src/frequenz/client/common/metrics/_sample.py Renders raw int bare for unspecified/unknown category, though get_category() raises on 0 | MetricConnectionCategory.UNSPECIFIED. The existing wrapping on the known case uses <CATEGORY=NAME> (uppercase =), inconsistent with the new <invalid:VALUE> (lowercase :). Render <invalid:0> for 0 | MetricConnectionCategory.UNSPECIFIED to match get_category(); normalize (or drop) the <CATEGORY=NAME> wrapping on the known case.
UnrecognizedElectricalComponent src/frequenz/client/common/microgrid/electrical_components/_problematic.py Carries category: int from the wire; not visible in the inherited ElectricalComponent.__str__ (only the class name signals the problem). Override __str__ to expose the raw value as <invalid:{category}>.
MismatchedCategoryElectricalComponent src/frequenz/client/common/microgrid/electrical_components/_problematic.py Same. Same.
UnrecognizedBattery src/frequenz/client/common/microgrid/electrical_components/_battery.py Carries type: int; not visible in inherited __str__. Override __str__ to expose the raw value as <invalid:{type}>.
UnrecognizedEvCharger src/frequenz/client/common/microgrid/electrical_components/_ev_charger.py Same. Same.
UnrecognizedInverter src/frequenz/client/common/microgrid/electrical_components/_inverter.py Same. Same.

In-flight PR needing alignment:

  • InvalidLifetime (Improve Lifetime validation and error handling #249 err-lifetime branch) — needs a design decision. Unlike the per-field violations above, InvalidLifetime's invariant is relational (start > end), not per-field. Suggested: add a __str__ on BaseLifetime rendering [{start_time}, {end_time}], override on InvalidLifetime to wrap the whole rendering: <invalid:[{start_time}, {end_time}]>.

Tests for the classes above need updating to match the new __str__ outputs.

Use cases

  • Log triage: grep '<invalid:' across logs finds every invariant violation regardless of type. Currently readers need to know each wrapper's convention (or that a bare 0 in MetricConnection[0] means "unspecified" rather than "category-0").
  • Consistency for downstream users: application code that formats or logs any of these types sees the same shape of invalid marker regardless of what produced it.

Alternatives and workarounds

Considered ! prefix/suffix, emoji, class-name-only marker, and bare repr() fallback. Full comparison and rationale: PR #248 r3589470688.

Additional context

Metadata

Metadata

Assignees

Labels

part:metricsAffects the metrics protobuf definitionspart:microgridAffects the microgrid protobuf definitionspriority:lowThis should be addressed only if there is nothing else on the tabletype:enhancementNew feature or enhancement visitble to users

Type

No type

Fields

Priority

None yet

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions