Repository navigation
Add nh device logs for reading device log lines - #7
Conversation
Support for the device log APIs added in nerves-hub/nerves_hub_web#2939: GET /orgs/:org/products/:product/devices/:identifier/logs - internal/api: LogLine and ListDeviceLogs, with a filter for level, since, before, limit and order. Unset fields are omitted so the server applies its own defaults (100 lines, newest first). - cmd: `nh device logs <identifier>`, rendering a table by default and the full lines under -o json. Metadata is hidden unless --meta is passed, since it is often long and the message is what is being scanned for. --since and --before also accept an offset from now (30m, 2h, 3d) rather than only ISO 8601, because that is how a log window is usually described. Offsets resolve to absolute timestamps client-side. --order and --limit are validated locally against the server's own rules so a typo fails immediately. Meta is decoded as map[string]any rather than map[string]string: the server documents string values, but a permissive type cannot fail the whole response if that ever varies. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The API has no streaming endpoint, so following is polling: print the most recent page, then ask for anything newer every --interval (2s by default) until interrupted. - The first page is fetched newest-first so it is the most recent lines, then reversed — a tail reads oldest to newest. Polls then ask oldest-first from the last timestamp seen. - `since` is inclusive, so the boundary line comes back on every poll. Rather than nudging the timestamp forward, which would silently drop a line sharing the same microsecond, the lines already printed at that exact timestamp are remembered and skipped. Only the boundary is tracked, so memory stays flat however long the tail runs. - With no history there is nothing to resume from, so following starts at now rather than replaying the oldest page. - A full page means more is probably waiting, so the next poll happens immediately instead of pacing behind the interval. - Ctrl-C ends the tail cleanly. Signal handling is scoped to the loop, leaving the rest of the CLI as it was. - JSON is emitted one object per line while following, since a stream has no end at which to close an array. One-shot output stays an indented array. - --order and --before contradict --follow and are refused, as is --interval without --follow. resetState now clears each command's context between tests. PersistentPreRunE stores config on the context, and cobra only inherits the root's context when a command's own is nil, so a command kept the previous test's context and ignored the one passed to ExecuteContext — which hung the follow tests when they ran after any other test in the package. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Added nh device logs thermostat-4021 --follow
nh device logs thermostat-4021 -f --level error --interval 5sHow it works: the first page is fetched newest-first (so it's the most recent lines), then reversed — a tail reads oldest to newest. Polls then ask oldest-first from the last timestamp seen. The subtle part — Other behaviour:
Test-infrastructure fix included. Full suite green, including under |
Support for the search param added to nerves-hub/nerves_hub_web#2939: keep only lines whose message contains the given text, ignoring case. The term is passed through untouched. The server matches it literally, so % and _ are searched for rather than treated as wildcards, and escaping them here would stop a device that logs "100%" being found by searching for it. A blank term is not a filter and is omitted rather than sent as an empty value. Search applies to every request a --follow tail makes, not just the first page. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Added nh device logs thermostat-4021 --search "sensor bus"
nh device logs thermostat-4021 -f --search timeout --level errorNotes on the implementation:
Full suite green. |
What
CLI support for the device log APIs added in nerves-hub/nerves_hub_web#2939:
Changes
internal/api—LogLineplusListDeviceLogswith aDeviceLogsFilter(level, since, before, limit, order). Unset fields are omitted entirely so the server applies its own defaults (100 lines, newest first). Repeated--levelis joined into the comma-separated list the API expects.cmd—nh device logs <identifier>: aTIMESTAMP / LEVEL / MESSAGEtable by default, full lines under-o json.Choices worth a look
Offsets as well as timestamps.
--since/--beforetake ISO 8601 or an offset from now (30m,2h,3d), resolved client-side to absolute timestamps. A log window is usually described relatively, and lines are only kept three days, so--since 2his the common case.3dis handled explicitly sincetime.ParseDurationhas no day unit.Metadata behind
--meta. It's often long and the message is what you're scanning for, so it's hidden by default and always present in-o json. When shown it's sortedkey=valuepairs, so repeated runs read the same.Local validation.
--orderand--limit(1–1000) are checked against the server's own rules before any request, so a typo fails immediately instead of costing a round trip and a 422. Levels are deliberately not validated — the server matches them as given, since a device may log at any level.metatyped asmap[string]any. The server documents string values, but a permissive type can't fail the whole response if that ever varies.