Events 'collect-app-status' and 'collect-unit-status'

Event > List of events > Ops events > collect-app-status and collect-unit-status

Source: CollectStatusEvent

The collect-app-status and collect-unit-status events are produced not by Juju but Ops.

The events are emitted on the charm, starting from ops 2.7, before the framework exits. The goal is to offer the charm a chance to uniformly set the application or unit status based on its internal state after processing the Juju event that triggered this execution.

Contents:

Emission sequence

The collect-app-status and collect-unit-status events are fired once by the framework after any Juju event is emitted, and before any other framework event is emitted. The -app-status event is for setting application status, and the -unit-status event for setting unit status.

For example, if the unit is processing a config-changed event, the charm will see:

config-changedcollect-unit-statuspre-commitcommit

Observing these events in Ops

To observe the collect-unit-status event:

# in MyCharm.__init__
self.framework.observe(self.on.collect_unit_status, self._on_collect_unit_status)

This will observe the event uniformly across the units of the charm.

To observe the collect-app-status event:

# in MyCharm.__init__
self.framework.observe(self.on.collect_app_status, self._on_collect_app_status)

This will ensure that only the leader unit processes it, and the result becomes the overall application status.

A CollectStatusEvent instance does not expose any specific attributes but exposes an add_status method to automatically manage statuses with different priorities. Read the API reference docs for more information and examples.

1 Like

@benhoyt @tony-meyer I see a challenge in documenting these events: there’s a clear discrepancy with how these work and how all other events work.

All other events in ops follow the same pattern: you observe the event in the charm’s __init__, and you can be assured that this unit will be notified of that event, no matter what. If you only want the leader unit to process the event (e.g. it’s only interesting for the leader) you have one choice:

def _on_my_event(self, e):
    if self.unit.is_leader():
        self._process(e)
    return

(or you can, in __init__, do: if self.unit.is_leader(): framework.observe(...) but that’s ugly.)

In the case of collect-status, the event does that distinction for you. Listen to collect-app-status: that method will only be called if this unit is leader.

Can you elaborate on the rationale behind this choice? And maybe some thoughts on how to make this behaviour clear in the docs, at the moment I feel it might be hard to take in.

It’s a good point. The rationale is simply that you can only set application status from the leader unit, so it only makes sense for the framework to collect app statuses on the leader. I don’t think it’s particularly hard to document, see for example https://ops.readthedocs.io/en/latest/#ops.CollectStatusEvent