diff --git a/src/tools/logs/tool.ts b/src/tools/logs/tool.ts index 322a7f7..308580c 100644 --- a/src/tools/logs/tool.ts +++ b/src/tools/logs/tool.ts @@ -21,6 +21,48 @@ export const LOGS_TOOLS: LogsTool[] = [ type LogsToolHandlers = ToolHandlers +/** + * Validates timestamp parameters to prevent common errors + * @throws Error if timestamps are invalid + */ +function validateTimestamps(from: number, to: number): void { + const now = Math.floor(Date.now() / 1000) // Current time in epoch seconds + const futureBuffer = 300 // Allow 5 minutes buffer for clock skew + + // Check if timestamps are valid numbers + if (!Number.isFinite(from) || !Number.isFinite(to)) { + throw new Error('Invalid timestamps: from and to must be valid numbers') + } + + // Check if 'from' is before 'to' + if (from >= to) { + throw new Error( + `Invalid time range: 'from' (${new Date(from * 1000).toISOString()}) must be before 'to' (${new Date(to * 1000).toISOString()})`, + ) + } + + // Check if timestamps are in the future (with buffer for clock skew) + if (from > now + futureBuffer) { + throw new Error( + `Invalid 'from' timestamp: ${new Date(from * 1000).toISOString()} is in the future. Current time: ${new Date(now * 1000).toISOString()}. Please check your timestamp calculation.`, + ) + } + + if (to > now + futureBuffer) { + throw new Error( + `Invalid 'to' timestamp: ${new Date(to * 1000).toISOString()} is in the future. Current time: ${new Date(now * 1000).toISOString()}. Please check your timestamp calculation.`, + ) + } + + // Warn if timestamps are very old (more than 1 year ago) + const oneYearAgo = now - 31536000 // 365 days in seconds + if (to < oneYearAgo) { + console.warn( + `Warning: Querying very old logs. 'to' timestamp is ${new Date(to * 1000).toISOString()}, which is more than 1 year ago.`, + ) + } +} + export const createLogsToolHandlers = ( apiInstance: v2.LogsApi, ): LogsToolHandlers => ({ @@ -29,13 +71,18 @@ export const createLogsToolHandlers = ( request.params.arguments, ) + // Validate timestamps before making the API call + validateTimestamps(from, to) + + const fromISO = new Date(from * 1000).toISOString() + const toISO = new Date(to * 1000).toISOString() + const response = await apiInstance.listLogs({ body: { filter: { query, - // `from` and `to` are in epoch seconds, but the Datadog API expects milliseconds - from: `${from * 1000}`, - to: `${to * 1000}`, + from: fromISO, + to: toISO, }, page: { limit, @@ -63,13 +110,18 @@ export const createLogsToolHandlers = ( request.params.arguments, ) + // Validate timestamps before making the API call + validateTimestamps(from, to) + + const fromISO = new Date(from * 1000).toISOString() + const toISO = new Date(to * 1000).toISOString() + const response = await apiInstance.listLogs({ body: { filter: { query, - // `from` and `to` are in epoch seconds, but the Datadog API expects milliseconds - from: `${from * 1000}`, - to: `${to * 1000}`, + from: fromISO, + to: toISO, }, page: { limit,