-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat: Add logs
option to CLI to print / tail logs from deployed agends
#192
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis update introduces a new feature that enables the retrieval of logs from deployed flatfile agents within the system. It enhances the command-line interface (CLI) by adding a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI
participant API
participant Agent
User->>CLI: Execute logs command
CLI->>API: Authenticate user
API-->>CLI: Return credentials
CLI->>API: Fetch agents
API-->>CLI: List of agents
CLI->>User: Prompt for agent selection
User->>CLI: Select agent
CLI->>API: Retrieve logs for selected agent
API-->>CLI: Return logs
CLI->>Agent: Filter and format logs
Agent-->>CLI: Display logs to user
alt Tail logs option selected
CLI->>API: Poll for new logs
API-->>CLI: Return new logs
CLI->>Agent: Update displayed logs
end
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Files selected for processing (3)
- .changeset/clean-news-arrive.md (1 hunks)
- packages/cli/src/index.ts (3 hunks)
- packages/cli/src/x/actions/logs.action.ts (1 hunks)
Files skipped from review due to trivial changes (1)
- .changeset/clean-news-arrive.md
Additional comments not posted (5)
packages/cli/src/index.ts (1)
66-91
: LGTM!The new
logs
command is implemented correctly and aligns with the PR objectives. The command definition, options, and action integration are all in place.Key points:
- The command is defined using the
program.command('logs')
syntax.- Relevant options are added to customize the log display, such as project slug, continuous tailing, log limit, authentication token, and API URL.
- The
action
method correctly specifies thelogsAction
function to be invoked when the command is executed.The addition of this command enhances the CLI functionality by providing users with a convenient way to view and tail logs from deployed agents.
packages/cli/src/x/actions/logs.action.ts (4)
19-25
: LGTM!The function logic is correct, and the implementation looks good.
36-61
: LGTM!The function handles agent selection correctly, covering all possible scenarios:
- When a slug is provided or there's no data.
- When there are multiple agents to choose from.
- When there is only one agent and no slug is provided.
The implementation looks good.
70-105
: LGTM!The function correctly parses and prints the logs from an array of agent logs:
- It handles error logs by printing them with an "ERROR" prefix in red color.
- For successful logs, it filters out empty lines and status lines, reverses the order, and extracts the relevant parts (timestamp, level, message).
- It color-codes the log level for better readability.
- The formatted log lines are printed with the timestamp, level, and message.
The implementation looks good and effectively handles the parsing and formatting of logs.
136-153
: LGTM!The function correctly fetches and returns the logs for an agent:
- It calls the appropriate API method (
getAgentLogs
) to fetch the logs for the specified agent and environment.- If
sinceEvent
is not provided, it directly returns the fetched logs.- If
sinceEvent
is provided, it filters the logs to include only those created after thesinceEvent
timestamp and excludes the log with the same event ID assinceEvent
.The implementation looks good and effectively handles the fetching and filtering of logs based on the provided parameters.
apiUrl: string | ||
token: string | ||
number: number | ||
tail: boolean | ||
}> | ||
): Promise<void> { | ||
let authRes | ||
try { | ||
authRes = await getAuth(options) | ||
} catch (e) { | ||
return program.error(messages.error(e)) | ||
} | ||
|
||
const { apiKey, apiUrl, environment } = authRes | ||
const slug = options?.slug || process.env.FLATFILE_AGENT_SLUG | ||
const apiClient = apiKeyClient({ apiUrl, apiKey: apiKey! }) | ||
|
||
/** | ||
* fetchLogs | ||
* | ||
* Fetchs and returns the logs for an agent. Optionally, fetch logs since a given ID. | ||
* | ||
* @param {Flatfile.AgentId} agentId - the ID of the agent to fetch logs for | ||
* @param {Flatfile.EventId} sinceEventId - the ID of the event log to fetch logs since | ||
* @returns {Promise<Flatfile.AgentLog[]>} - the logs | ||
*/ | ||
const fetchLogs = async ( | ||
agentId: Flatfile.AgentId, | ||
sinceEvent?: Flatfile.AgentLog | ||
): Promise<Flatfile.AgentLog[]> => { | ||
const { data: logs = [] } = await apiClient.agents.getAgentLogs(agentId, { | ||
environmentId: environment.id!, | ||
}) | ||
|
||
if (!sinceEvent) return logs | ||
|
||
const filtered = logs.filter( | ||
(log) => | ||
log.createdAt >= sinceEvent.createdAt && | ||
log.eventId !== sinceEvent.eventId | ||
) | ||
|
||
return filtered | ||
} | ||
|
||
try { | ||
const agentSpinner = ora({ | ||
text: `Select agent to display logs for...`, | ||
}).start() | ||
const { data } = await apiClient.agents.list({ | ||
environmentId: environment.id!, | ||
}) | ||
const selectedAgent = await handleAgentSelection(data, slug) | ||
|
||
if (!selectedAgent) { | ||
const errorMessage = slug | ||
? `Agent with slug ${chalk.cyan(slug)} not found` | ||
: 'No agents found' | ||
|
||
agentSpinner.fail(errorMessage) | ||
process.exit(1) | ||
} | ||
|
||
const agentName = selectedAgent.slug || selectedAgent.id | ||
agentSpinner.succeed(`Selected agent: ${chalk.cyan(agentName)}`) | ||
|
||
const logs = await fetchLogs(selectedAgent.id) | ||
const maxLogs = options?.number || logs.length | ||
const initialLogs = logs.slice(0, maxLogs).reverse() | ||
|
||
// Print the intially requested logs | ||
printLogs(initialLogs) | ||
|
||
if (options?.tail) { | ||
let lastEvent = initialLogs[initialLogs.length - 1] | ||
let timer: ReturnType<typeof setTimeout> | ||
|
||
// The logs endpoint does not support streaming responses, so we need to poll every few seconds. | ||
const poll = async () => { | ||
const newLogs = (await fetchLogs(selectedAgent.id, lastEvent)).reverse() | ||
|
||
if (newLogs.length > 0) { | ||
printLogs(newLogs) | ||
lastEvent = newLogs[newLogs.length - 1] | ||
} | ||
|
||
timer = setTimeout(poll, 2500) | ||
} | ||
|
||
poll() | ||
|
||
process.on('SIGINT', () => { | ||
if (timer) clearTimeout(timer) | ||
process.exit() | ||
}) | ||
} | ||
} catch (e) { | ||
return program.error(messages.error(e)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider refactoring the function to improve readability and maintainability.
The logsAction
function is quite large and has multiple responsibilities. To improve readability and maintainability, consider the following suggestions:
- Extract the authentication logic into a separate function.
- Extract the agent selection logic into a separate function.
- Extract the log fetching and printing logic into separate functions.
- Extract the polling logic into a separate function.
By breaking down the function into smaller, focused functions, the code will become more modular and easier to understand and maintain.
This PR adds support for a new
flatfile logs
command that will allow users to view and tail the logs from their deployed agents.https://www.loom.com/share/833c08b93a0a4b78b7e8d40294d882f1?sid=fb179235-4482-4c2b-98ce-7b23357e97b4