Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 58 additions & 6 deletions src/tools/logs/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,48 @@ export const LOGS_TOOLS: LogsTool[] = [

type LogsToolHandlers = ToolHandlers<LogsToolName>

/**
* 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 => ({
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand Down