/* * Scenario 6: USDT Probes - Custom Instrumentation * ================================================= * This program demonstrates User Statically Defined Tracepoints (USDT). * USDT probes allow you to add custom tracing points to your code * that have near-zero overhead when not actively traced. * * Compile: * gcc -O2 -g -o server server.c * * The probes use sys/sdt.h which is provided by systemtap-sdt-dev on Ubuntu. * Install: sudo apt install systemtap-sdt-dev * * EXERCISES: * 1. Run normally: ./server * 2. List probes: perf probe -x ./server --list * 3. Trace probes: See README.md for bpftrace examples */ #include #include #include #include #include /* * USDT probe macros from systemtap-sdt-dev * If not available, we define dummy macros */ #ifdef HAVE_SDT #include #else /* Dummy macros when SDT isn't available */ #define DTRACE_PROBE(provider, name) #define DTRACE_PROBE1(provider, name, arg1) #define DTRACE_PROBE2(provider, name, arg1, arg2) #define DTRACE_PROBE3(provider, name, arg1, arg2, arg3) #endif /* Simulated request structure */ struct request { int id; int type; /* 0=read, 1=write, 2=delete */ int size; /* payload size */ char data[64]; }; /* Statistics */ static unsigned long total_requests = 0; static unsigned long total_errors = 0; /* * Process a single request * We add USDT probes at entry, exit, and error points */ int process_request(struct request *req) { /* Probe: request processing started */ DTRACE_PROBE2(myserver, request_start, req->id, req->type); total_requests++; /* Simulate variable processing time based on request type */ int delay_ms; switch (req->type) { case 0: delay_ms = 10 + (rand() % 20); break; /* read: 10-30ms */ case 1: delay_ms = 50 + (rand() % 50); break; /* write: 50-100ms */ case 2: delay_ms = 5 + (rand() % 10); break; /* delete: 5-15ms */ default: delay_ms = 100; } /* Simulate some work */ usleep(delay_ms * 1000); /* Simulate occasional errors (10% chance) */ if (rand() % 10 == 0) { DTRACE_PROBE2(myserver, request_error, req->id, -1); total_errors++; return -1; } /* Probe: request completed successfully */ DTRACE_PROBE3(myserver, request_end, req->id, req->type, delay_ms); return 0; } /* * Batch processing function */ void process_batch(int batch_id, int count) { DTRACE_PROBE2(myserver, batch_start, batch_id, count); printf("Processing batch %d with %d requests...\n", batch_id, count); struct request req; for (int i = 0; i < count; i++) { req.id = batch_id * 1000 + i; req.type = rand() % 3; req.size = 64; snprintf(req.data, sizeof(req.data), "request_%d", req.id); process_request(&req); } DTRACE_PROBE1(myserver, batch_end, batch_id); } int main(int argc, char *argv[]) { int num_batches = 5; int requests_per_batch = 20; if (argc > 1) num_batches = atoi(argv[1]); if (argc > 2) requests_per_batch = atoi(argv[2]); srand(time(NULL)); printf("USDT Probe Demo Server\n"); printf("======================\n"); printf("Batches: %d, Requests per batch: %d\n\n", num_batches, requests_per_batch); #ifndef HAVE_SDT printf("Note: Compiled without USDT support.\n"); printf("To enable probes: sudo apt install systemtap-sdt-dev\n"); printf("Then compile with: gcc -DHAVE_SDT -O2 -g -o server server.c\n\n"); #endif DTRACE_PROBE(myserver, server_start); for (int i = 0; i < num_batches; i++) { process_batch(i, requests_per_batch); } DTRACE_PROBE(myserver, server_stop); printf("\n=== Summary ===\n"); printf("Total requests: %lu\n", total_requests); printf("Total errors: %lu (%.1f%%)\n", total_errors, 100.0 * total_errors / total_requests); return 0; }