In the previous chapter, Input Sanitization, we ensured that the data entering our system was clean and safe. Our application is now fully functional: it registers commands, shows a UI, manages state, and handles data safely.
However, as a developer, you are now flying blind. You know the code works, but you don't know how people are using it.
In this final chapter, we will explore Event Telemetry.
Imagine you own a coffee shop.
Event Telemetry is like having a manager in the lobby taking notes. It helps you answer questions like:
tag feature?"By tracking these Events, we can make data-driven decisions to improve the tool.
logEvent
To record these interactions, we use a helper function called logEvent. It takes two arguments:
command_started).{ duration: 500 }).
In our tag.tsx file, we import the logger from our analytics service.
import { logEvent } from '../../services/analytics/index.js';
When a user successfully adds a tag, we want to record it. We also want to know if they were overwriting an existing tag or creating a brand new one.
// Inside the logic where we save the tag
const isReplacing = !!currentTag; // true if a tag already existed
// 1. Log the event name
// 2. Pass context: are they replacing an old tag?
logEvent('tengu_tag_command_add', {
is_replacing: isReplacing
});
await saveTag(id, normalizedTag, fullPath);
Explanation:
tengu_tag_command_add. This is the key we will look for in our dashboard later.{ is_replacing: true/false }. This helps us understand if users are "switching" contexts often.In React-based Terminal UI, we created a confirmation dialog. This is a critical moment in the User Experience (UX). We want to know what users choose.
Scenario A: The User Confirms
// Inside the 'Yes, remove tag' callback
onConfirm: async () => {
// Track that the user said YES
logEvent('tengu_tag_command_remove_confirmed', {});
await saveTag(sessionId, '', fullPath);
onDone('Tag removed');
}
Scenario B: The User Cancels
// Inside the 'No, keep tag' callback
onCancel: () => {
// Track that the user said NO
logEvent('tengu_tag_command_remove_cancelled', {});
onDone('Action cancelled');
}
Why track cancellation? If 90% of users click "Cancel", it might mean our UI is confusing or that we are triggering the confirmation dialog too aggressively!
You might be wondering: "Does sending this data slow down my CLI?"
Good telemetry systems are designed to be Non-Blocking. They work like a postbox: you drop the letter in, and you walk away immediately. You don't wait for the postman to actually drive the letter to the destination.
logEvent.
While the specific code for services/analytics isn't shown in our tag.tsx file, a typical implementation looks like this (simplified):
// services/analytics/index.js (Simplified Concept)
const eventQueue = [];
export function logEvent(name, properties) {
// 1. Add timestamp
const event = {
name,
properties,
timestamp: Date.now()
};
// 2. Push to local array (Fast!)
eventQueue.push(event);
// 3. We don't await the network request here!
}
Then, a separate "flush" function runs right before the CLI process exits to ensure the data is sent.
// At the end of the application lifecycle
process.on('exit', () => {
// Send whatever is in eventQueue to the server
sendTelemetry(eventQueue);
});
In this final chapter, we learned:
logEvent is designed to be fast and non-blocking, queuing data locally before sending it.Congratulations! You have completed the tag project tutorial. You have walked through the entire lifecycle of a modern CLI feature:
You now possess the building blocks to create powerful, safe, and measurable command-line tools. Happy coding!
Generated by Code IQ