Skip to content

Commit 662a494

Browse files
IlyaasKclaude
andcommitted
Address review feedback on telemetry events command
- Use the shared addJSONOutputFlag for `browsers telemetry events` instead of a hand-rolled --output flag (consistency with extensions get). [Bugbot] - Don't send --since/--until when --offset is set: offset is an opaque X-Next-Offset cursor that already encodes the query window, so the window flags are ignored when paging. Aligns behavior with the flag help and updates --until's help to match --since. Added a test. [Bugbot] - Surface the pagination cursor in JSON mode: `--output json` now emits {"events": [...], "next_offset": "..."} so scripted callers can paginate (table mode already printed the hint). Updated the empty-JSON test. [Bugbot] - README: document `extensions get`, `browsers telemetry events`, and the `--replay` flag on `telemetry stream`. [review] Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent d187a2d commit 662a494

4 files changed

Lines changed: 68 additions & 13 deletions

File tree

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,8 +317,14 @@ Per-category updates are partial — only categories you name are changed; other
317317
- `--categories <list>` - Filter by event category (`console`, `network`, `page`, `interaction`, `control`, `connection`, `system`, `screenshot`, `captcha`, `monitor`)
318318
- `--types <list>` - Filter by event type (e.g. `network_response`, `console_error`)
319319
- `--seq <n>` - Resume after sequence number N (Last-Event-ID); replays events with `seq > N`. Omit to stream from now.
320+
- `--replay all` - Replay buffered events on connect, starting from the oldest retained event (mutually exclusive with `--seq`)
320321
- `-o, --output json` - Output newline-delimited JSON envelopes
321322
- Default output: tab-separated `<time>\t[<category>]\t<type>`, e.g. `15:04:05 [network] network_response`
323+
- `kernel browsers telemetry events <id>` - Read historical telemetry events (paged)
324+
- `--limit <n>` - Maximum number of events per page (default 20)
325+
- `--offset <cursor>` - Pagination cursor: pass the `X-Next-Offset` from a previous response
326+
- `--since <ts|dur>` / `--until <ts|dur>` - Time window (RFC-3339 timestamp or duration like `5m`); ignored when `--offset` is set
327+
- `-o, --output json` - Output `{ "events": [...], "next_offset": "..." }` (omit `next_offset` when there is no next page)
322328

323329
### Browser Process Control
324330

@@ -444,6 +450,8 @@ Per-category updates are partial — only categories you name are changed; other
444450

445451
- `kernel extensions list` - List all uploaded extensions
446452
- `--output json`, `-o json` - Output raw JSON array
453+
- `kernel extensions get <id-or-name>` - Show extension metadata (id, name, created, size, last used)
454+
- `--output json`, `-o json` - Output raw JSON object
447455
- `kernel extensions upload <directory>` - Upload an unpacked browser extension directory
448456
- `--name <name>` - Optional unique extension name
449457
- `--output json`, `-o json` - Output raw JSON object

cmd/browsers.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2756,8 +2756,8 @@ followed automatically by Chromium.`,
27562756
telemetryEvents.Flags().Int64("limit", 0, "Maximum number of events per page (default 20)")
27572757
telemetryEvents.Flags().Int64("offset", 0, "Pagination cursor: pass the X-Next-Offset from a previous response")
27582758
telemetryEvents.Flags().String("since", "", "Window start: RFC-3339 timestamp or a duration like 5m (default 5m). Ignored when --offset is set")
2759-
telemetryEvents.Flags().String("until", "", "Window end (exclusive): RFC-3339 timestamp or a duration like 5m")
2760-
telemetryEvents.Flags().StringP("output", "o", "", "Output format: json")
2759+
telemetryEvents.Flags().String("until", "", "Window end (exclusive): RFC-3339 timestamp or a duration like 5m. Ignored when --offset is set")
2760+
addJSONOutputFlag(telemetryEvents)
27612761
telemetryRoot.AddCommand(telemetryEvents)
27622762
browsersCmd.AddCommand(telemetryRoot)
27632763

cmd/browsers_telemetry.go

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"context"
5+
"encoding/json"
56
"errors"
67
"fmt"
78
"net/http"
@@ -272,13 +273,16 @@ func (b BrowsersCmd) TelemetryEvents(ctx context.Context, in BrowsersTelemetryEv
272273
params.Limit = kernel.Opt(in.Limit)
273274
}
274275
if in.Offset > 0 {
276+
// Offset is an opaque cursor (X-Next-Offset) that already encodes the
277+
// query window, so since/until are ignored when paging by offset.
275278
params.Offset = kernel.Opt(in.Offset)
276-
}
277-
if in.Since != "" {
278-
params.Since = kernel.Opt(in.Since)
279-
}
280-
if in.Until != "" {
281-
params.Until = kernel.Opt(in.Until)
279+
} else {
280+
if in.Since != "" {
281+
params.Since = kernel.Opt(in.Since)
282+
}
283+
if in.Until != "" {
284+
params.Until = kernel.Opt(in.Until)
285+
}
282286
}
283287

284288
var raw *http.Response
@@ -293,11 +297,32 @@ func (b BrowsersCmd) TelemetryEvents(ctx context.Context, in BrowsersTelemetryEv
293297
}
294298

295299
if in.Output == "json" {
296-
if len(items) == 0 {
297-
fmt.Println("[]")
298-
return nil
300+
// Surface the X-Next-Offset cursor in JSON mode too, so scripted callers
301+
// can paginate (table mode prints it as a hint below).
302+
nextOffset := ""
303+
if raw != nil {
304+
if n := raw.Header.Get("X-Next-Offset"); n != "" && n != "0" {
305+
nextOffset = n
306+
}
299307
}
300-
return util.PrintPrettyJSONSlice(items)
308+
events := make([]json.RawMessage, 0, len(items))
309+
for _, it := range items {
310+
r := it.RawJSON()
311+
if r == "" {
312+
r = "{}"
313+
}
314+
events = append(events, json.RawMessage(r))
315+
}
316+
payload := struct {
317+
Events []json.RawMessage `json:"events"`
318+
NextOffset string `json:"next_offset,omitempty"`
319+
}{Events: events, NextOffset: nextOffset}
320+
data, err := json.MarshalIndent(payload, "", " ")
321+
if err != nil {
322+
return err
323+
}
324+
fmt.Println(string(data))
325+
return nil
301326
}
302327

303328
if len(items) == 0 {

cmd/browsers_telemetry_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,5 +400,27 @@ func TestTelemetryEvents_EmptyJSON(t *testing.T) {
400400
err := b.TelemetryEvents(context.Background(), BrowsersTelemetryEventsInput{Identifier: "br-1", Output: "json"})
401401
assert.NoError(t, err)
402402
})
403-
assert.Equal(t, "[]\n", out)
403+
// JSON mode emits an envelope so scripted callers can read the pagination
404+
// cursor; with no events and no next page it is just an empty events list.
405+
assert.JSONEq(t, `{"events":[]}`, out)
406+
}
407+
408+
func TestTelemetryEvents_OffsetIgnoresWindow(t *testing.T) {
409+
buf := capturePtermOutput(t)
410+
fakeBrowsers := &FakeBrowsersService{GetFunc: func(ctx context.Context, id string, query kernel.BrowserGetParams, opts ...option.RequestOption) (*kernel.BrowserGetResponse, error) {
411+
return &kernel.BrowserGetResponse{SessionID: "sess-1"}, nil
412+
}}
413+
fakeTelemetry := &FakeBrowserTelemetryService{
414+
EventsFunc: func(ctx context.Context, id string, query kernel.BrowserTelemetryEventsParams, opts ...option.RequestOption) (*pagination.OffsetPagination[kernel.BrowserTelemetryEventsResponse], error) {
415+
// When paging by the opaque offset cursor, since/until must not be sent.
416+
assert.True(t, query.Offset.Valid(), "offset should be forwarded")
417+
assert.False(t, query.Since.Valid(), "since must be omitted when --offset is set")
418+
assert.False(t, query.Until.Valid(), "until must be omitted when --offset is set")
419+
return &pagination.OffsetPagination[kernel.BrowserTelemetryEventsResponse]{}, nil
420+
},
421+
}
422+
b := BrowsersCmd{browsers: fakeBrowsers, telemetry: fakeTelemetry}
423+
err := b.TelemetryEvents(context.Background(), BrowsersTelemetryEventsInput{Identifier: "br-1", Offset: 5, Since: "5m", Until: "1m"})
424+
assert.NoError(t, err)
425+
_ = buf
404426
}

0 commit comments

Comments
 (0)