Skip to content

Commit 419df00

Browse files
committed
fix: address bot review feedback for time-range support
- Fix statsPeriod/start+end conflict: API functions with fallback statsPeriod defaults now guard with start/end presence check - Fix normalizeDateOnly day arithmetic: use local setDate/setHours instead of UTC round-trip to prevent date shift in extreme timezones - Reject all absolute ranges with --follow, not just end-bounded
1 parent 02fa3c4 commit 419df00

File tree

4 files changed

+35
-19
lines changed

4 files changed

+35
-19
lines changed

src/commands/log/list.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -689,12 +689,12 @@ export const listCommand = buildListCommand(
689689
: DEFAULT_PROJECT_PERIOD);
690690
const timeRange = parsePeriod(effectivePeriod);
691691

692-
// Follow mode cannot be used with an end-bounded absolute range
693-
// streaming polls for new events, but an end date caps the window.
694-
if (flags.follow && timeRange.type === "absolute" && timeRange.end) {
692+
// Follow mode streams live events via short polling intervals
693+
// absolute date ranges are silently ignored, so reject them entirely.
694+
if (flags.follow && timeRange.type === "absolute") {
695695
throw new ValidationError(
696-
"--follow cannot be used with an end date boundary. " +
697-
"Remove the end date to stream new events.",
696+
"--follow cannot be used with an absolute date range. " +
697+
"Use a relative duration (e.g., --period 1h) or omit --period.",
698698
"period"
699699
);
700700
}

src/lib/api/logs.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,10 @@ export async function listLogs(
101101
project: isNumericProject ? [Number(projectSlug)] : undefined,
102102
query: fullQuery || undefined,
103103
per_page: options.limit || API_MAX_PER_PAGE,
104-
statsPeriod: options.statsPeriod ?? "30d",
104+
statsPeriod:
105+
options.start || options.end
106+
? undefined
107+
: (options.statsPeriod ?? "30d"),
105108
start: options.start,
106109
end: options.end,
107110
sort: toApiSort(options.sort),
@@ -250,7 +253,10 @@ export async function listTraceLogs(
250253
{
251254
params: {
252255
traceId,
253-
statsPeriod: options.statsPeriod ?? "14d",
256+
statsPeriod:
257+
options.start || options.end
258+
? undefined
259+
: (options.statsPeriod ?? "14d"),
254260
start: options.start,
255261
end: options.end,
256262
per_page: options.limit ?? API_MAX_PER_PAGE,

src/lib/api/traces.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,10 @@ export async function listTransactions(
235235
// omitting the parameter.
236236
query: fullQuery || undefined,
237237
per_page: options.limit || 10,
238-
statsPeriod: options.statsPeriod ?? "7d",
238+
statsPeriod:
239+
options.start || options.end
240+
? undefined
241+
: (options.statsPeriod ?? "7d"),
239242
start: options.start,
240243
end: options.end,
241244
sort:
@@ -323,7 +326,10 @@ export async function listSpans(
323326
project: isNumericProject ? projectSlug : undefined,
324327
query: fullQuery || undefined,
325328
per_page: options.limit || 10,
326-
statsPeriod: options.statsPeriod ?? "7d",
329+
statsPeriod:
330+
options.start || options.end
331+
? undefined
332+
: (options.statsPeriod ?? "7d"),
327333
start: options.start,
328334
end: options.end,
329335
sort: options.sort === "duration" ? "-span.duration" : "-timestamp",

src/lib/time-range.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ export function parseDate(raw: string, position: DatePosition): string {
147147
*
148148
* Constructs datetimes without "Z" so `new Date()` interprets them as local time,
149149
* then converts to UTC via `.toISOString()`.
150+
*
151+
* Day arithmetic for "after"/"before" uses local Date methods (setDate/setHours)
152+
* to avoid UTC/local mismatches in extreme timezones.
150153
*/
151154
function normalizeDateOnly(dateStr: string, position: DatePosition): string {
152155
// Validate the date is parseable
@@ -159,17 +162,18 @@ function normalizeDateOnly(dateStr: string, position: DatePosition): string {
159162
return new Date(`${dateStr}T23:59:59.999`).toISOString();
160163
}
161164
if (position === "after") {
162-
// Exclusive start (>): next day's local midnight
163-
const nextDay = new Date(`${dateStr}T12:00:00`);
164-
nextDay.setDate(nextDay.getDate() + 1);
165-
const nextStr = nextDay.toISOString().slice(0, 10);
166-
return new Date(`${nextStr}T00:00:00`).toISOString();
165+
// Exclusive start (>): next day's local midnight.
166+
// Use local Date methods throughout to avoid UTC/local day mismatch.
167+
const d = new Date(`${dateStr}T00:00:00`);
168+
d.setDate(d.getDate() + 1);
169+
d.setHours(0, 0, 0, 0);
170+
return d.toISOString();
167171
}
168-
// position === "before": Exclusive end (<): previous day's local end-of-day
169-
const prevDay = new Date(`${dateStr}T12:00:00`);
170-
prevDay.setDate(prevDay.getDate() - 1);
171-
const prevStr = prevDay.toISOString().slice(0, 10);
172-
return new Date(`${prevStr}T23:59:59.999`).toISOString();
172+
// position === "before": Exclusive end (<): previous day's local end-of-day.
173+
const d = new Date(`${dateStr}T23:59:59.999`);
174+
d.setDate(d.getDate() - 1);
175+
d.setHours(23, 59, 59, 999);
176+
return d.toISOString();
173177
}
174178

175179
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)