Debugging Course Enrollments (Tracing, Logs)
We can search for courses now! But now when we try to enroll, we’re getting some unresponsive controls.

In Sentry, we’re seeing the error pop up - and as we’ve shown previously, we can use Tracing and Logs to help troubleshoot the issue quicker.

Learning Objectives
By the end of this module, you will:
- Create custom spans to track the course enrollment flow
- Use Trace Explorer to search for specific spans that show the enrollment flow and course information
- Understand how to resolve the issues with enrollment in the application
- Extend our logs to include context around the enrollment issues in the application
Frontend Implementation
Let’s start by instrumenting the frontend enrollment functionality to track enrollment requests and user data being sent to the backend.
-
Replace the Complete Frontend Enrollment Method
Navigate to the
/apps/frontend/src/services/api.ts
file and replace thecreate
method in theenrollments
object with this instrumented version:create: (courseId: string, userId: string | undefined) =>Sentry.startSpan({name: 'enrollment.create.frontend',op: 'http.client',attributes: {'enrollment.course_id': courseId,'enrollment.user_id': userId || 'undefined','enrollment.user_id_provided': !!userId,},},() => {logger.info(logger.fmt`Creating enrollment for course: ${courseId}, user: ${userId || 'undefined'}`);return fetchApi<any>('/enrollments', {method: 'POST',body: JSON.stringify({ courseId }),});}), -
Test Enrollment Tracing
Try enrolling in courses again. Navigate to Explore > Traces in Sentry’s left navigation menu, and search using the
span.description
filter to find your enrollment-related spans using theenrollment.create.server
value. -
Examine the Trace
Clicking into one of the spans will show you the trace waterfall where you can examine the properties of any of the spans submitted.
-
Examine the Logs
Check the Explore > Logs tab for the log entries created by
logger.info
calls.
Backend Implementation
Now let’s instrument the backend enrollment functionality to trace server-side processing and identify the missing user ID issue.
-
Add Sentry Import to Backend Enrollment Routes
Navigate to the
/apps/server/src/modules/enrollments/routes.ts
file and add the Sentry import at the top:import * as Sentry from '@sentry/node'; -
Set Up Backend Enrollment Logging
Add the logger destructuring after your imports:
const { logger } = Sentry -
Replace the Complete Enrollment Route
Replace the entire
enrollmentRoutes.post('/enrollments', async (req, res)
route with this instrumented version:enrollmentRoutes.post('/enrollments', async (req, res) => {try {const { userId, courseId } = req.body;await Sentry.startSpan({name: 'enrollment.create.server',op: 'enrollment.process',attributes: {'enrollment.course_id': courseId || 'undefined','enrollment.user_id': userId || 'undefined','enrollment.user_id_provided': !!userId,},},async (span) => {console.log('🔍 Checking enrollment request:', { userId, courseId });logger.info(logger.fmt`Processing enrollment request for course: ${courseId || 'undefined'}, user: ${userId || 'undefined'}`);// Add initial request validation attributesspan.setAttributes({'enrollment.request.course_id_provided': !!courseId,'enrollment.request.user_id_provided': !!userId,});// First: Validate course ID is providedif (!courseId) {span.setAttributes({'enrollment.validation.course_id': 'missing','enrollment.validation.result': 'failed','enrollment.error': 'course_id_required',});console.error('❌ Course ID is missing');res.status(400).json({ error: 'Course ID is required.' });return;}logger.info(logger.fmt`Verifying course exists: ${courseId}`);const courseCheck = await db.select().from(courses).where(eq(courses.id, courseId)).limit(1);logger.info('📚 Course check result:', courseCheck);if (courseCheck.length === 0) {span.setAttributes({'enrollment.validation.course_exists': false,'enrollment.validation.result': 'failed','enrollment.error': 'course_not_found',});console.error('❌ Course not found:', courseId);res.status(404).json({ error: `Course with id ${courseId} not found` });return;}// Add course details to spanconst course = courseCheck[0];span.setAttributes({'enrollment.validation.course_exists': true,'enrollment.course.title': course.title,'enrollment.course.category': course.category || 'unknown','enrollment.course.level': course.level || 'unknown','enrollment.course.instructor_id': course.instructorId || 'unknown',});logger.info(logger.fmt`Course found: "${course.title}" (${course.category})`);// Third: Validate user ID is providedif (!userId) {span.setAttributes({'enrollment.validation.user_id': 'missing','enrollment.validation.result': 'failed','enrollment.error': 'user_id_missing',});console.error('❌ User ID is missing');throw new Error('User ID is missing');}// Add final validation success attributesspan.setAttributes({'enrollment.validation.user_id': 'provided','enrollment.validation.result': 'passed','enrollment.process.success': true,});logger.info(logger.fmt`Enrollment validation successful for user ${userId} in course "${course.title}"`);console.log('✅ All validation successful, enrollment approved');res.json({success: true,message: 'Enrollment validation successful',courseId,userId});});} catch (error: any) {Sentry.captureException(error, {tags: {operation: 'enrollment.create.backend',course_id: req.body.courseId || 'undefined',user_id: req.body.userId || 'undefined',},extra: {requestBody: req.body,courseId: req.body.courseId,userId: req.body.userId,hasUserId: !!req.body.userId,hasCourseId: !!req.body.courseId,},});logger.error(logger.fmt`Enrollment error for course ${req.body.courseId || 'undefined'}, user ${req.body.userId || 'undefined'}: ${error.message}`);console.error('💥 Error during enrollment:', error);console.error('📊 Error details:', {message: error.message,stack: error.stack,userId: req.body.userId,courseId: req.body.courseId,});throw new Error('Failed to enroll in course');}}); -
Test Enrollment Tracing
Try enrolling in courses again. Navigate to Explore > Traces in Sentry’s left navigation menu, and search using the
span.description
filter to find your enrollment-related spans using theenrollment.create.server
value. -
Examine the Trace
-
Examine the Logs
Check the Explore > Logs tab for the log entries created by
logger.info
andlogger.error
calls.
Analyzing the Issue
When we look now, we can see that the User ID is not being passed to the backend. This is visible both in the Trace Explorer’s Span views as well as clearly visible in the logs view.
Fixing the Issue
The fix for this is simple - need to update the frontend client to successfully pass the userId to the backend as well.
-
Update Frontend to Include User ID
In the frontend enrollment request, update the
enrollments
object in/apps/frontend/src/services/api.ts
from:return fetchApi<any>('/enrollments', {method: 'POST',body: JSON.stringify({ courseId }),});to the following:
return fetchApi<any>('/enrollments', {method: 'POST',body: JSON.stringify({ courseId, userId }),});
Once this change is made, submit your enrollment again and you’ll see successful enrollment of your courses!
