Debugging TypeKro Applications
TypeKro provides comprehensive debugging capabilities to help you troubleshoot composition issues, understand resource references, and optimize deployment performance. This guide covers all debugging tools and techniques.
Environment Variables
TYPEKRO_LOG_LEVEL
Control TypeKro's logging verbosity with the TYPEKRO_LOG_LEVEL
environment variable:
# Available log levels (in order of verbosity)
export TYPEKRO_LOG_LEVEL=trace # Most verbose - all internal operations
export TYPEKRO_LOG_LEVEL=debug # Debug information - recommended for development
export TYPEKRO_LOG_LEVEL=info # General information - default production level
export TYPEKRO_LOG_LEVEL=warn # Warnings only
export TYPEKRO_LOG_LEVEL=error # Errors only
export TYPEKRO_LOG_LEVEL=fatal # Critical errors only
Additional Debugging Variables
# Enable proxy debugging (shows magic proxy operations)
export TYPEKRO_DEBUG=true
# Pretty-print JSON logs for development
export TYPEKRO_LOG_PRETTY=true
# Log to file instead of stdout
export TYPEKRO_LOG_DESTINATION=/tmp/typekro-debug.log
# Enable specific component debugging
export TYPEKRO_DEBUG_COMPONENTS="composition,proxy,serialization"
Development Setup
Recommended Development Configuration
# .env.development
TYPEKRO_LOG_LEVEL=debug
TYPEKRO_LOG_PRETTY=true
TYPEKRO_DEBUG=true
NODE_ENV=development
Production Debugging Configuration
# .env.production
TYPEKRO_LOG_LEVEL=info
TYPEKRO_LOG_PRETTY=false
TYPEKRO_LOG_DESTINATION=/var/log/typekro/app.log
Common Debugging Scenarios
1. Resource Reference Issues
Problem: Cross-resource references not working as expected
// Enable debug logging to see reference resolution
const deployment = Deployment({ name: 'web-app', image: 'nginx:latest', id: 'webApp' });
const service = Service({
name: deployment.metadata.name, // This reference might not work as expected
selector: { app: deployment.metadata.labels.app }
});
Debug Steps:
# Enable detailed proxy logging
export TYPEKRO_DEBUG=true
export TYPEKRO_LOG_LEVEL=debug
# Run your composition
node your-app.js 2>&1 | grep -E "(proxy|reference|serialization)"
Expected Output:
{"level":"debug","component":"factory-proxy","msg":"Proxy created","resourceId":"webApp","basePath":"metadata"}
{"level":"debug","component":"serialization","msg":"Converting reference to CEL","fieldPath":"webApp.metadata.name"}
2. CEL Expression Debugging
Problem: CEL expressions in status builders not evaluating correctly
const webApp = kubernetesComposition(
{ /* schema */ },
(spec) => {
const deployment = Deployment({ /* config */ });
return {
ready: Cel.expr<boolean>(deployment.status.readyReplicas, ' > 0') // Debug this expression
};
}
);
Debug Steps:
# Enable CEL debugging
export TYPEKRO_LOG_LEVEL=debug
export TYPEKRO_DEBUG_COMPONENTS="cel,serialization"
# Check generated CEL expressions
node -e "console.log(JSON.stringify(webApp.toYaml(), null, 2))" | grep -A5 -B5 "cel"
3. Composition Context Issues
Problem: Resources not being auto-captured in kubernetesComposition
const myComposition = kubernetesComposition(
{ /* schema */ },
(spec) => {
// These resources should be auto-captured
const db = Deployment({ name: 'database', image: 'postgres:15' });
const web = Deployment({ name: 'webapp', image: 'nginx:latest' });
return { ready: true };
}
);
Debug Steps:
export TYPEKRO_LOG_LEVEL=debug
export TYPEKRO_DEBUG_COMPONENTS="composition"
Check Logs:
{"level":"debug","component":"composition","msg":"Resource registered","resourceId":"database","kind":"Deployment"}
{"level":"debug","component":"composition","msg":"Resource registered","resourceId":"webapp","kind":"Deployment"}
{"level":"info","component":"composition","msg":"Composition completed","resourceCount":2}
4. Serialization Problems
Problem: Resources not serializing to YAML correctly
const resource = createResource({
apiVersion: 'apps/v1',
kind: 'Deployment',
metadata: { name: 'test' }
});
console.log(resource.toYaml()); // Not producing expected output
Debug Steps:
export TYPEKRO_LOG_LEVEL=trace
export TYPEKRO_DEBUG_COMPONENTS="serialization"
# Enable proxy debugging to see property access
export TYPEKRO_DEBUG=true
Debugging Tools and Methods
1. Resource Inspection
import { getCurrentCompositionContext } from 'typekro';
// Within a composition function
const myComposition = kubernetesComposition(
{ /* schema */ },
(spec) => {
const deployment = Deployment({ name: 'my-app', image: 'nginx:latest' });
// Debug: Check composition context
const context = getCurrentCompositionContext();
if (context) {
console.log('Registered resources:', Object.keys(context.resources));
console.log('Resource count:', context.resourceCounter);
}
// Debug: Inspect Enhanced resource properties
console.log('Resource ID:', deployment.id);
console.log('Resource kind:', deployment.kind);
console.log('Metadata name:', deployment.metadata.name);
return { ready: true };
}
);
2. CEL Expression Testing
import { Cel } from 'typekro';
// Test CEL expressions in isolation
const testExpr = Cel.expr<boolean>('resources.deployment.status.readyReplicas', ' > 0');
console.log('CEL Expression:', JSON.stringify(testExpr));
const testTemplate = Cel.template('https://%s.example.com', 'my-app');
console.log('CEL Template:', JSON.stringify(testTemplate));
3. Readiness Evaluator Testing
import type { ReadinessEvaluator } from 'typekro';
const customEvaluator: ReadinessEvaluator = (liveResource) => {
console.log('Evaluating readiness for:', liveResource.metadata?.name);
console.log('Resource status:', JSON.stringify(liveResource.status, null, 2));
// Your readiness logic here
return { ready: true, message: 'Custom evaluation complete' };
};
const deployment = Deployment({
name: 'debug-app',
image: 'nginx:latest'
}).withReadinessEvaluator(customEvaluator);
Troubleshooting Common Issues
Issue: "Resource not found in composition context"
Symptoms:
Error: Resource with ID 'myResource' not found in composition context
Solutions:
Ensure resource has explicit
id
field:typescriptconst resource = Deployment({ name: 'my-app', image: 'nginx:latest', id: 'myResource' });
Check that resource is created within composition function:
typescriptconst composition = kubernetesComposition( { /* schema */ }, (spec) => { // Resource must be created HERE, not outside const resource = Deployment({ /* config */ }); return { /* status */ }; } );
Issue: "Invalid CEL expression"
Symptoms:
Error: Invalid CEL expression: unexpected token
Solutions:
Check CEL syntax:
typescript// ❌ Wrong Cel.expr(resource.status.ready == true) // ✅ Correct Cel.expr<boolean>(resource.status.ready, ' == true')
Verify resource references:
typescript// ❌ Wrong - using undefined resource Cel.expr<boolean>(undefinedResource.status.ready, ' == true') // ✅ Correct - using defined resource const deployment = Deployment({ /* config */ }); Cel.expr<boolean>(deployment.status.readyReplicas, ' > 0')
Issue: "Cross-resource references not working"
Symptoms: Resources reference each other but values are not passed correctly
Solutions:
Ensure resources are Enhanced proxies:
typescriptconst deployment = Deployment({ name: 'web', image: 'nginx:latest' }); const service = Service({ name: deployment.metadata.name, // This creates a KubernetesRef selector: deployment.spec.selector.matchLabels });
Check serialization output:
bashexport TYPEKRO_LOG_LEVEL=debug node -e "console.log(service.toYaml())" | grep -E "cel|ref"
Performance Debugging
Memory Usage
# Monitor memory usage during composition
node --max-old-space-size=8192 --expose-gc your-app.js
# In your application
if (global.gc) {
console.log('Memory before:', process.memoryUsage());
global.gc();
console.log('Memory after GC:', process.memoryUsage());
}
Timing Analysis
import { performance } from 'perf_hooks';
const start = performance.now();
const composition = kubernetesComposition(
{ /* schema */ },
(spec) => {
const compositionStart = performance.now();
// Your composition logic
const resources = createMyResources(spec);
const compositionEnd = performance.now();
console.log(`Composition took ${compositionEnd - compositionStart}ms`);
return { ready: true };
}
);
const yaml = composition.toYaml();
const end = performance.now();
console.log(`Total execution time: ${end - start}ms`);
Log Analysis
Filtering Logs by Component
# View only composition-related logs
tail -f /var/log/typekro/app.log | jq 'select(.component == "composition")'
# View proxy operations
tail -f /var/log/typekro/app.log | jq 'select(.component == "factory-proxy")'
# View serialization details
tail -f /var/log/typekro/app.log | jq 'select(.component == "serialization")'
Error Correlation
# Find errors and their context (5 lines before/after)
grep -C 5 '"level":"error"' /var/log/typekro/app.log | jq .
Best Practices for Debugging
1. Structured Logging in Custom Code
import { getComponentLogger } from 'typekro';
const logger = getComponentLogger('my-factory');
export function myCustomFactory(config: Config) {
const functionLogger = logger.child({
factoryName: 'myCustomFactory',
resourceName: config.name
});
functionLogger.debug('Starting factory creation', { config });
try {
const resource = createResource({ /* config */ });
functionLogger.info('Factory resource created successfully');
return resource;
} catch (error) {
functionLogger.error('Factory creation failed', error);
throw error;
}
}
2. Development vs Production Debugging
const isDevelopment = process.env.NODE_ENV === 'development';
if (isDevelopment) {
// Enable verbose debugging in development
process.env.TYPEKRO_LOG_LEVEL = 'debug';
process.env.TYPEKRO_DEBUG = 'true';
process.env.TYPEKRO_LOG_PRETTY = 'true';
}
3. Conditional Debug Output
const DEBUG = process.env.TYPEKRO_DEBUG === 'true';
function debugComposition(resources: Record<string, any>) {
if (!DEBUG) return;
console.log('=== DEBUG: Composition Resources ===');
for (const [key, resource] of Object.entries(resources)) {
console.log(`${key}:`, {
id: resource.id,
kind: resource.kind,
name: resource.metadata?.name
});
}
console.log('=== END DEBUG ===');
}
This comprehensive debugging guide should help developers troubleshoot issues effectively and understand TypeKro's internal operations during development and production.