Thanks! This is looking good. I appreciate your updates and working with me to get this closer to what I’m hoping it will be. The shape of the TelemetryEmitter looks great.
Assuming that you’re looking for feedback
…
One thing I ask you to keep in mind that’s not directly telemetry related but more of an overall Monty design direction is the distinction between the runtime and experiment domains. The distinction we are after is that someone could run Monty “for real” without ever knowing anything about experiments, episodes, epochs, etc. @DSchumacher has been doing a lot of work recently on splitting up runtime and experiments. An invariant to keep in mind is that runtime shall not import any experiment code, whereas experiment code can import the runtime code. We aren’t there yet with the existing code, but it’s something we can enforce on new code to make forward progress.
Where this comes up in telemetry is PostEpisodeTelemetry and PostEpisodeTelemetryConsumer. The words “post episode” alone mark those as exclusively experimental concerns. As such, these should end up in tbp.monty.experiment module somewhere (I suggest tbp.monty.experiment.telemetry). Since init_telemetry happens in MontyExperiment, which is … an experiment
, then it can import experiment code without worry.
TelemetryEmitter looks like it’s in the right place
.
Another point of caution of mixing experiment and runtime I’d highlight is in the TelemetrySchema. I don’t think that mode, episode, and step belong there, since they are experimental metadata (maybe step is OK, I’m not sure yet). Note that PostEpisodeTelemetryConsumer is managed by the experiment, which can tell it what mode, episode, and step it is on.
This raises the question of how epoch, episode, and step experiment data will be attached to events if they’re not set at the emit point.
I question if TelemetryStopEvent is needed. It feels to me like injecting a control plane message into the data plane.
I saw your note avoid levels >= 30 (logging.WARNING) (today I learned). I would assume that this behavior is only for the default logger, but neither telemetry nor snapshot loggers propagate to the default logger, so I’m wondering if this is a problem on the telemetry/snapshot side of things.
Are you able to set things up so that we would summon TelemetryEmitter in the same way we do logs?
import logging
import tbp.monty.frameworks.telemetry as tbp_telemetry
# or
from tbp.monty.frameworks.telemetry import getTelemetry
# ...
logger = logging.getLogger(__name__)
telemetry = tbp_telemetry.getTelemetry(__name__)
# or
telemetry = getTelemetry(__name__)
# ...
I still don’t fully understand the use case for deferred/pump.
Thank you again, the code is looking more and more like the interface I’m hoping for.