☕ @debug - Debug Mode in Java
@debug - Debug Mode in Java
The @debug
operator provides comprehensive debugging capabilities for Java applications, integrating with Spring Boot's logging system, JVM debugging tools, and enterprise monitoring solutions.
Basic Syntax
// TuskLang configuration
debug_mode: @debug.enabled()
debug_level: @debug.level() // "trace", "debug", "info", "warn", "error"
debug_output: @debug.output() // "console", "file", "remote"
// Java Spring Boot integration
@Configuration
@EnableTuskDebug
public class DebugConfig {
@Bean
public TuskDebugService tuskDebugService() {
return TuskDebugService.builder()
.enabled(true)
.level(LogLevel.DEBUG)
.output(DebugOutput.CONSOLE)
.build();
}
}
Debug Configuration
// application.yml
tusk:
debug:
enabled: true
level: DEBUG
output: CONSOLE
file:
path: "/var/log/tusk-debug.log"
max-size: "100MB"
max-files: 10
remote:
host: "debug.tuskt.sk"
port: 8080
api-key: "${DEBUG_API_KEY}"
// TuskLang configuration with debug settings
app_config: {
debug: @debug.enabled()
# Debug levels
trace_enabled: @debug.level("trace")
debug_enabled: @debug.level("debug")
info_enabled: @debug.level("info")
# Debug outputs
console_debug: @debug.output("console")
file_debug: @debug.output("file")
remote_debug: @debug.output("remote")
# Debug file settings
debug_file: @debug.file.path()
debug_max_size: @debug.file.max_size()
debug_max_files: @debug.file.max_files()
}
Debug Logging
// Java logging with TuskLang debug integration
@Component
public class UserService {
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
@Autowired
private TuskDebugService debugService;
public User createUser(UserDto userDto) {
// Debug logging
if (debugService.isEnabled()) {
logger.debug("Creating user: {}", userDto);
debugService.log("user_creation", Map.of(
"email", userDto.getEmail(),
"timestamp", Instant.now()
));
}
try {
User user = userRepository.save(userDto.toEntity());
if (debugService.isEnabled()) {
logger.debug("User created successfully: {}", user.getId());
debugService.log("user_created", Map.of(
"user_id", user.getId(),
"duration_ms", System.currentTimeMillis()
));
}
return user;
} catch (Exception e) {
if (debugService.isEnabled()) {
logger.error("Failed to create user: {}", e.getMessage(), e);
debugService.log("user_creation_error", Map.of(
"error", e.getMessage(),
"stack_trace", Arrays.toString(e.getStackTrace())
));
}
throw e;
}
}
}
// TuskLang debug logging
create_user: (user_data) => {
# Debug logging
@debug.log("user_creation_start", {
email: @user_data.email
timestamp: @date.now()
})
# Create user
user: @User.create(@user_data)
# Debug success
@debug.log("user_creation_success", {
user_id: @user.id
duration_ms: @debug.timer("user_creation")
})
return @user
}
Debug Timers
// Java timer integration
@Component
public class PerformanceService {
@Autowired
private TuskDebugService debugService;
public void expensiveOperation() {
String timerId = debugService.startTimer("expensive_operation");
try {
// Perform expensive operation
Thread.sleep(1000);
debugService.stopTimer(timerId);
debugService.log("operation_completed", Map.of(
"duration_ms", debugService.getTimerDuration(timerId)
));
} catch (Exception e) {
debugService.stopTimer(timerId);
debugService.log("operation_failed", Map.of(
"error", e.getMessage(),
"duration_ms", debugService.getTimerDuration(timerId)
));
throw e;
}
}
}
// TuskLang debug timers
process_data: (data) => {
# Start timer
@debug.timer.start("data_processing")
# Process data
result: @process(@data)
# Stop timer and log
duration: @debug.timer.stop("data_processing")
@debug.log("data_processed", {
input_size: @data.length
output_size: @result.length
duration_ms: @duration
})
return @result
}
Debug Variables
// Java debug variable tracking
@Component
public class DebugVariableService {
@Autowired
private TuskDebugService debugService;
public void trackVariables(String operation, Map<String, Object> variables) {
if (debugService.isEnabled()) {
debugService.setVariable(operation, variables);
}
}
public Map<String, Object> getVariables(String operation) {
return debugService.getVariables(operation);
}
}
// TuskLang debug variables
calculate_tax: (amount, rate) => {
# Set debug variables
@debug.variable("tax_calculation", {
amount: @amount
rate: @rate
timestamp: @date.now()
})
# Calculate tax
tax: @amount * @rate
# Update debug variables
@debug.variable("tax_calculation", {
amount: @amount
rate: @rate
tax: @tax
timestamp: @date.now()
})
return @tax
}
Debug Breakpoints
// Java debug breakpoints
@Component
public class DebugBreakpointService {
@Autowired
private TuskDebugService debugService;
public void setBreakpoint(String name, String condition) {
debugService.setBreakpoint(name, condition);
}
public void checkBreakpoint(String name, Map<String, Object> context) {
if (debugService.shouldBreak(name, context)) {
// Trigger breakpoint
debugService.break(name, context);
}
}
}
// TuskLang debug breakpoints
validate_user: (user) => {
# Set breakpoint for invalid users
@debug.breakpoint("invalid_user", @user.email == "" || @user.email == null)
# Check breakpoint
@debug.break("user_validation", {
user_id: @user.id
email: @user.email
valid: @user.email != "" && @user.email != null
})
# Continue processing
return @user.email != "" && @user.email != null
}
Debug Memory Tracking
// Java memory debugging
@Component
public class MemoryDebugService {
@Autowired
private TuskDebugService debugService;
public void trackMemory(String operation) {
Runtime runtime = Runtime.getRuntime();
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
debugService.log("memory_usage", Map.of(
"operation", operation,
"used_mb", usedMemory / 1024 / 1024,
"total_mb", runtime.totalMemory() / 1024 / 1024,
"free_mb", runtime.freeMemory() / 1024 / 1024
));
}
}
// TuskLang memory debugging
process_large_data: (data) => {
# Track memory before processing
@debug.memory.track("before_processing")
# Process data
result: @process(@data)
# Track memory after processing
@debug.memory.track("after_processing")
# Log memory difference
@debug.log("memory_usage", {
before_mb: @debug.memory.get("before_processing")
after_mb: @debug.memory.get("after_processing")
difference_mb: @debug.memory.diff("before_processing", "after_processing")
})
return @result
}
Debug Profiling
// Java profiling integration
@Component
public class ProfilingService {
@Autowired
private TuskDebugService debugService;
public void profileOperation(String operation, Runnable task) {
long startTime = System.nanoTime();
long startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
try {
task.run();
} finally {
long endTime = System.nanoTime();
long endMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
debugService.log("profile", Map.of(
"operation", operation,
"duration_ns", endTime - startTime,
"memory_delta_bytes", endMemory - startMemory,
"cpu_usage", getCpuUsage()
));
}
}
private double getCpuUsage() {
// Implementation for CPU usage tracking
return 0.0;
}
}
// TuskLang profiling
profile_function: (function_name, function) => {
# Start profiling
@debug.profile.start(@function_name)
# Execute function
result: @function()
# Stop profiling
profile_data: @debug.profile.stop(@function_name)
# Log profile data
@debug.log("function_profile", {
function: @function_name
duration_ms: @profile_data.duration
memory_mb: @profile_data.memory
cpu_percent: @profile_data.cpu
})
return @result
}
Debug Remote Monitoring
// Java remote debugging
@Component
public class RemoteDebugService {
@Autowired
private TuskDebugService debugService;
public void sendToRemote(String event, Map<String, Object> data) {
if (debugService.isRemoteEnabled()) {
debugService.sendRemote(event, data);
}
}
public void enableRemoteDebugging(String host, int port, String apiKey) {
debugService.configureRemote(host, port, apiKey);
}
}
// TuskLang remote debugging
remote_debug: {
# Configure remote debugging
@debug.remote.enable("debug.tuskt.sk", 8080, @env.DEBUG_API_KEY)
# Send debug events
@debug.remote.send("app_started", {
version: @app.version
environment: @env.NODE_ENV
timestamp: @date.now()
})
# Send performance metrics
@debug.remote.send("performance_metrics", {
memory_usage: @debug.memory.current()
cpu_usage: @debug.cpu.current()
active_connections: @debug.connections.active()
})
}
Debug Configuration Examples
// Development environment
dev_debug: {
enabled: true
level: "debug"
output: "console"
file: {
path: "/tmp/tusk-debug.log"
max_size: "50MB"
max_files: 5
}
remote: {
enabled: false
}
}// Production environment
prod_debug: {
enabled: false
level: "error"
output: "file"
file: {
path: "/var/log/tusk-debug.log"
max_size: "100MB"
max_files: 10
}
remote: {
enabled: true
host: "monitoring.tuskt.sk"
port: 8080
api_key: @env.DEBUG_API_KEY
}
}
// Testing environment
test_debug: {
enabled: true
level: "trace"
output: "console"
file: {
path: "/tmp/test-debug.log"
max_size: "10MB"
max_files: 1
}
remote: {
enabled: false
}
}
Debug Testing
// JUnit test with debug integration
@SpringBootTest
class DebugServiceTest {
@Autowired
private TuskDebugService debugService;
@Test
void testDebugLogging() {
// Enable debug for test
debugService.setEnabled(true);
debugService.setLevel(LogLevel.DEBUG);
// Test debug logging
debugService.log("test_event", Map.of("test", true));
// Verify log was created
List<DebugLog> logs = debugService.getLogs();
assertThat(logs).hasSize(1);
assertThat(logs.get(0).getEvent()).isEqualTo("test_event");
}
@Test
void testDebugTimer() {
String timerId = debugService.startTimer("test_timer");
// Simulate work
Thread.sleep(100);
long duration = debugService.stopTimer(timerId);
assertThat(duration).isGreaterThan(0);
}
}
// TuskLang debug testing
test_debug: {
# Enable debug for testing
@debug.enable()
@debug.level("trace")
# Test debug logging
@debug.log("test_event", { test: true })
# Test debug timer
@debug.timer.start("test_timer")
@sleep(100) # Simulate work
duration: @debug.timer.stop("test_timer")
# Verify results
assert(@duration > 0, "Timer should record duration")
assert(@debug.logs.count() > 0, "Should have debug logs")
}
Best Practices
1. Environment-Specific Debugging
// Use different debug levels per environment
@Configuration
public class EnvironmentDebugConfig {
@Bean
@Profile("dev")
public TuskDebugService devDebugService() {
return TuskDebugService.builder()
.enabled(true)
.level(LogLevel.DEBUG)
.output(DebugOutput.CONSOLE)
.build();
}
@Bean
@Profile("prod")
public TuskDebugService prodDebugService() {
return TuskDebugService.builder()
.enabled(false)
.level(LogLevel.ERROR)
.output(DebugOutput.FILE)
.build();
}
}
2. Performance-Safe Debugging
// Use conditional debugging to avoid performance impact
@Component
public class PerformanceSafeDebugService {
public void debugIfEnabled(String event, Supplier<Map<String, Object>> dataSupplier) {
if (isDebugEnabled()) {
Map<String, Object> data = dataSupplier.get();
log(event, data);
}
}
private boolean isDebugEnabled() {
return debugService.isEnabled() && debugService.getLevel().ordinal() <= LogLevel.DEBUG.ordinal();
}
}
3. Structured Debug Data
// Use structured debug data for better analysis
@Component
public class StructuredDebugService {
public void logStructured(String event, String operation, Map<String, Object> context) {
Map<String, Object> structuredData = Map.of(
"event", event,
"operation", operation,
"timestamp", Instant.now(),
"context", context,
"thread", Thread.currentThread().getName(),
"memory_usage", getCurrentMemoryUsage()
);
debugService.log(event, structuredData);
}
}
Integration with Monitoring Tools
// Integration with Micrometer for metrics
@Component
public class MicrometerDebugIntegration {
@Autowired
private MeterRegistry meterRegistry;
@EventListener
public void handleDebugEvent(DebugEvent event) {
// Convert debug events to metrics
Counter.builder("tusk.debug.events")
.tag("event", event.getEvent())
.tag("level", event.getLevel().toString())
.register(meterRegistry)
.increment();
}
}
// Integration with ELK stack
@Component
public class ELKDebugIntegration {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@EventListener
public void handleDebugEvent(DebugEvent event) {
// Send debug events to Elasticsearch
DebugLogDocument logDoc = DebugLogDocument.builder()
.event(event.getEvent())
.level(event.getLevel())
.data(event.getData())
.timestamp(event.getTimestamp())
.build();
elasticsearchTemplate.save(logDoc);
}
}
The @debug
operator in Java provides enterprise-grade debugging capabilities that integrate seamlessly with Spring Boot, JVM tools, and monitoring systems. It enables comprehensive application introspection while maintaining performance and security standards.