thermal: Add ereports - #2639
Conversation
| } | ||
| } | ||
|
|
||
| #[derive(microcbor::EncodeFields)] |
There was a problem hiding this comment.
@hawkw I'm particularly open to feedback on what to put in these ereports.
There was a problem hiding this comment.
Right now I'm sending SensorId as id, which on one hand is nice, because that's something that could directly be used to query the fan RPM. On the other hand, it's an unstable generated ID, and does nothing to explain which fan this is.
We could include a more string-y "East South East" name (for sidecar), or some kind of refdes, or something. This was the easiest to do, but I can plumb other info through if we need it.
There was a problem hiding this comment.
Right now I'm sending
SensorIdasid, which on one hand is nice, because that's something that could directly be used to query the fan RPM. On the other hand, it's an unstable generated ID, and does nothing to explain which fan this is.We could include a more string-y "East South East" name (for sidecar), or some kind of refdes, or something. This was the easiest to do, but I can plumb other info through if we need it.
IIUC there is no way currently for the control plane to turn the sensor ID into anything that's actually meaningful to it. While the ID can be used to request fan RPM from Hubris, it cannot be used to query fan speeds that the control plane has previously read from Hubris and stored in Clickhouse by Oximeter, since those timeseries data points are not labeled by the sensor ID (which is on purpose, because as you mentioned, it is not stable across Hubris builds).
Therefore, I think we should probably be including the refdes, as that can be used both for querying historical measurements from Clickhouse and for reading the current value via component-details. Since querying by refdes will give us the metrics for all the sensors associated with that fan controller, we will also need to include the name assigned to that sensor in the app.toml. For instance, on sidecar:
Line 512 in c1328f7
I think that the combination of the refdes and sensor name should be sufficient for the control plane to both retrieve historical measurements from Clickhouse and poll new ones from the SP if it chooses to. I'm on the fence as to whether we ought to also keep the sensor ID or not. It's more or less useless to the control plane, but it's also only a couple bytes, so we may as well throw it in.
I think that it will require a bit more work to plumb through the refdes and sensor names in a way that they can be retrieved from a sensor ID; I started describing that in #2364.
There was a problem hiding this comment.
My abortive PR #2383 included a codegen change for looking up a refdes from a sensor ID. That won't give us the sensor name, as written, but it could be added there. I think the reason I didn't finish that at the time is mostly because I had been hoping to figure out a way to do that that didn't require generating a giant LUT of sensor IDs that would use a lot of flash.
One or both of us could blow some of the dust out of that PR, perhaps pulling out just the codegen-related stuff in there?
There was a problem hiding this comment.
okay, i think #2645 should've added all the requisite codegen :)
|
@hawkw another open question is "should we send ereports on power-on"? Right now on sidecar which has 8 fans, we'll send 8x "fan is/is not present" messages, and 8x "fan is/is not nominal" messages. I can add some more logic that suppresses this if we want. It seems consistent to send them, but also I don't know if we've observed any "mad rush" of this kind of state transmission, and what we should do if the outgoing ereport queue fills up. We also could pay attention to whether |
| #[derive(Encode)] | ||
| #[ereport(class = "hw.fan.rpm.err", version = 0)] | ||
| struct FanRpmReadFailed { | ||
| id: u32, | ||
| } |
There was a problem hiding this comment.
part of me thinks we might really want to have a more general ereport in the shared ereports crate for "trying to read a sensor over I2C failed"?
There was a problem hiding this comment.
I would be open to discuss this! How do we still maintain the context: "this i2c read is specifically for a fan and we are sad we don't have its data"?
This is something I have thought about doing in several places. I think it's not a bad idea, although one deficiency in the way ereports are currently implemented is that the timestamp is always decided by For now, we haven't actually ever dropped ereports due to full buffers, so I haven't been worrying about retries too much yet. |
Do we have a way to reasonably detect when this happens? I can add a little stress and see if we hit it, and back off if not. |
there are ringbuf counters in each task that will tell you precisely how many times it tried and failed to submit an ereport. but, more importantly, the ereport ring buffer code in packrat will create a "loss report" for upstack software that tells it "hey, i have dropped this many ereports, sorry about that". this is part of the same stream as the actual ereports. as far as i know, we have never actually seen such a loss report in a production system.
for what it's worth, such a test is really only going to be interesting if there is a control plane collecting ereports (and therefore draining the buffer); if you run it against a bench system, you will see a bunch of stuff get dropped, but that's kind of anticipated. |
| Fps::TooFast(rpm) => Trace::FanOverspeed(id, rpm), | ||
| Fps::TooSlow(rpm) => Trace::FanUnderspeed(id, rpm), | ||
| let fan_info = || FanInfo { | ||
| name: fan.name, |
There was a problem hiding this comment.
So @hawkw interesting point here:
If I do id.name() here, it ends up inflating the .rodata, likely with the table of all sensor names:
james@fool:~/oxide/hubris git:(james/ereport-thermals) ✗ arm-none-eabi-size -A target/cosmo-b-dev/dist/thermal.elf
target/cosmo-b-dev/dist/thermal.elf :
section size addr
.text 17632 0
.rodata 4640 0
.data 580 0
.bss 2452 0
But with the change to make .name() a const fn, and storing .name in the const-fn constructor of Fan::new(), then we don't pull in the whole array:
james@fool:~/oxide/hubris git:(james/ereport-thermals) ✗ arm-none-eabi-size -A target/cosmo-b-dev/dist/thermal.elf
target/cosmo-b-dev/dist/thermal.elf :
section size addr
.text 17544 0
.rodata 2552 0
.data 628 0
.bss 2452 0
.uninit 0 0
I don't think this is a make or break, a ~2KiB flash difference (on cosmo) isn't really THAT big of a deal, but it does seem lightly footgun-y if you aren't Too Clever about it.
|
@hawkw this should be ready for a fresh look, IMO. |
Adds ereports for the thermal task, as a follow up to #2630
closes #2603