Node Function Tracing
Maximum flexibility for programmatic tracing. Node function tracing allows you to trace any function call with complete control over when and how the tracing happens, perfect for custom tracking patterns, dynamic function calls, and integrating tracing into existing codebases.
This approach gives you the ultimate flexibility to trace functions programmatically, including functions you canāt modify directly or need conditional tracing.
Node function tracing gives you the most flexibility to trace functions programmatically, including functions you canāt modify directly or need conditional tracing.
How It Works
Node function tracing provides programmatic control through:
- Programmatic control - Call tracing functions directly in your code
- Dynamic tracing - Decide at runtime what to trace
- Custom keys - Use custom identifiers for tracking
- Flexible input handling - Works with any function signature
- Error capture - Automatically handles and reports errors
Implementation
Python: trace_agent_node_func
& trace_agent_node_func_sync
JavaScript: captureAgentNode
const { config, captureAgentNode } = require('handit-sdk');
config({ apiKey: 'your-api-key' });
// Example: Dynamic function tracing
async function processUserRequest(userId, requestType, data) {
let result;
if (requestType === 'analysis') {
// Trace the analysis function
const analysisResult = await analyzeData(data);
// Manually capture the execution
await captureAgentNode({
agentNodeSlug: 'data-analysis',
requestBody: { userId, data },
responseBody: analysisResult
});
result = analysisResult;
} else if (requestType === 'recommendation') {
// Trace with custom key based on user
const recommendations = await generateRecommendations(userId, data);
await captureAgentNode({
agentNodeSlug: `recommendations-${userId}`,
requestBody: { userId, preferences: data },
responseBody: recommendations
});
result = recommendations;
} else if (requestType === 'search') {
// Trace with error handling
try {
const searchResults = await searchKnowledgeBase(data.query, data.filters);
await captureAgentNode({
agentNodeSlug: 'knowledge-search',
requestBody: { query: data.query, filters: data.filters, userId },
responseBody: searchResults,
error: false
});
result = searchResults;
} catch (error) {
// Capture error case
await captureAgentNode({
agentNodeSlug: 'knowledge-search',
requestBody: { query: data.query, filters: data.filters, userId },
responseBody: { error: error.message },
error: true
});
throw error;
}
}
return result;
}
// Example: Tracing external API calls
async function callExternalService(endpoint, payload) {
const startTime = Date.now();
try {
const response = await fetch(`https://api.external-service.com/${endpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
const result = await response.json();
const duration = Date.now() - startTime;
// Capture successful API call
await captureAgentNode({
agentNodeSlug: `external-api-${endpoint}`,
requestBody: { endpoint, payload, timestamp: startTime },
responseBody: { ...result, duration, status: response.status }
});
return result;
} catch (error) {
const duration = Date.now() - startTime;
// Capture failed API call
await captureAgentNode({
agentNodeSlug: `external-api-${endpoint}`,
requestBody: { endpoint, payload, timestamp: startTime },
responseBody: {
error: error.message,
duration,
failed: true
},
error: true
});
throw error;
}
}
// Example functions
async function analyzeData(data) {
// Complex analysis logic
const analysis = await performComplexAnalysis(data);
return { analysis, confidence: 0.95 };
}
async function generateRecommendations(userId, preferences) {
const userProfile = await getUserProfile(userId);
const recommendations = await mlRecommendationEngine(userProfile, preferences);
return recommendations;
}
async function searchKnowledgeBase(query, filters) {
const results = await vectorSearch(query, filters);
return { results, count: results.length };
}
Advanced Use Cases
Conditional Tracing Based on Context
Tracing Third-Party Libraries
Best Practices
When to Use Node Function Tracing:
Use Case | Why Node Function Tracing |
---|---|
Dynamic function selection | Choose which functions to trace based on runtime conditions |
Third-party library integration | Trace external libraries and APIs without modifying their code |
Conditional tracing logic | Implement complex tracing rules based on environment or user context |
Custom tracking patterns | Create specialized tracing workflows for unique requirements |
Error-specific tracing | Focus tracing on error scenarios and edge cases |
Implementation Guidelines:
- Use descriptive keys for tracking - Choose meaningful identifiers that help with debugging and analysis
- Include relevant context in captures - Add metadata that provides useful debugging information
- Handle errors explicitly - Implement proper error handling and capture error scenarios
- Consider performance impact - Balance tracing detail with system performance requirements
- Add metadata for debugging - Include timing, user context, and other relevant information
Node function tracing requires more manual work but provides maximum flexibility. Use it when decorators and wrappers donāt fit your use case.
Node function tracing is perfect for integrating Handit.ai into existing codebases without major refactoring.
Next Steps
- Learn about Agent Wrapper/Decorator for simpler automation
- Explore Node Wrapper/Decorator for function-level tracing
- Check Manual Agent Tracing for complete control