Skip to content

Conversation

philliphartin
Copy link
Contributor

@philliphartin philliphartin commented Jul 10, 2025

Add Source Code Capture for Exception Traces

This PR adds the ability to capture source code lines around exception locations in user-land code, providing developers with immediate context when debugging exceptions without needing to open files.

What's Changed

Configuration

  • Added capture_exception_source_code configuration option (defaults to true)
  • Can be controlled via NIGHTWATCH_CAPTURE_EXCEPTION_SOURCE_CODE environment variable

Core Implementation

  • Updated ExceptionSensor to capture source code context for user files in exception traces
  • Added source code loading and line extraction functionality
  • Only captures code from user-land files (excludes vendor, framework, and internal files)
  • Captures ±5 lines of context around the exception location

API Changes

  • Made Location::isVendorFile() and Location::isInternalFile() public
  • Added Location::getBasePath() method for source code file resolution

Payload Preview

When an exception occurs in user code, the trace now includes a code field with source context:

{
  "trace": [
    {
      "file": "app/Mail/WelcomeEmail.php:28",
      "source": "Illuminate\\Mail\\Mailables\\Envelope->__construct(null, array, array, array, array, array)",
      "code": {
        "23": "    /**",
        "24": "     * Get the message envelope.",
        "25": "     */",
        "26": "    public function envelope(): Envelope",
        "27": "    {",
        "28": "        return new Envelope(",
        "29": "            subject: $this->subject,",
        "30": "        );",
        "31": "    }",
        "32": "",
        "33": "    /**"
      }
    },
    {
      "file": "app/Http/Controllers/UserController.php:45",
      "source": "Illuminate\\Mail\\PendingMail->send(App\\Mail\\WelcomeEmail)",
      "code": {
        "40": "    public function store(Request $request)",
        "41": "    {",
        "42": "        $user = User::create($request->validated());",
        "43": "",
        "44": "        try {",
        "45": "            Mail::to($user->email)->send(new WelcomeEmail($user));",
        "46": "        } catch (Exception $e) {",
        "47": "            report($e);",
        "48": "            return response()->json(['error' => 'Failed to send email'], 500);",
        "49": "        }",
        "50": ""
      }
    }
  ]
}

Benefits

  1. Immediate Context: Once added to our UI, developers can see the exact code that caused the exception without switching to their IDE
  2. Better Error Reports: Support teams get more context when investigating issues
  3. Configurable: Can be disabled in production environments if desired for performance/security

Performance Considerations

  • Only captures source code for user-land files (not vendor/framework code)
  • Files are only loaded once into memory
  • Can be disabled via configuration if needed
  • Minimal overhead as it only activates when exceptions occur

Testing

  • Added comprehensive test coverage for source code capture functionality
  • Tests verify correct context extraction and proper filtering of vendor files
  • Includes tests for configuration toggle

…eptionSensor

- Introduced `getBasePath` method in `Location` class to access the base path.
- Enhanced `ExceptionSensor` to collect and return source code lines around exceptions, including context lines.
- Added a test to verify the correct capture of source code lines during exception handling.
…ames in the trace

- Added configuration option to enable or disable source line capture for exceptions.
- Updated `ExceptionSensor` to conditionally collect source lines based on the new configuration.
- Improved trace serialization to include source lines for the first few frames of the exception stack.
…ality

- Updated tests to assert the correct capture of source lines for exceptions.
- Added a test to verify the disabling of source line capture via configuration.
- Moved the test for capturing source code lines to a new location within the test class.
- Added a new route for testing exception handling in the application.
- Temporarily disabling source line capture to scaffold test
- Simplified the structure of the collected source code lines in `ExceptionSensor`.
- Updated tests to enable source line capture and validate the correct retrieval of source lines for exceptions.
- Wrapped the mail sending logic in a try-catch block to handle exceptions gracefully.
- Added reporting and aborting functionality to manage expected exceptions.
- Updated test cases to reflect changes in source code line references.
- Changed visibility of `isVendorFile` and `isInternalFile` methods in `Location` class from private to public.
- Updated `collectSourceCodeLines` method in `ExceptionSensor` to accept file contents instead of file path, returning a structured object with source lines.
- Improved trace serialization to include source code lines for user files, enhancing exception handling capabilities.
- Adjusted tests to validate the new structure of source code line collection and ensure accurate retrieval of source lines.
@philliphartin philliphartin marked this pull request as draft July 10, 2025 06:11
@philliphartin philliphartin changed the title Add Source code capture for exception traces Add source code capture for exception traces Jul 10, 2025
@faustbrian
Copy link

faustbrian commented Jul 17, 2025

@philliphartin is there any ETA on when this could be expected to be released? That's the last thing before we could cancel our Sentry subscription.

@philliphartin
Copy link
Contributor Author

Hey @faustbrian, we're eager to get this completed ASAP! Ideally next week.

@jessarcher jessarcher force-pushed the feature/code-excerpts branch from b219349 to b6769f5 Compare July 23, 2025 02:07
@faustbrian
Copy link

@philliphartin any progress on this?

@jessarcher jessarcher marked this pull request as ready for review August 11, 2025 04:55
@jessarcher jessarcher merged commit c3dc908 into 1.x Aug 11, 2025
25 checks passed
@jessarcher jessarcher deleted the feature/code-excerpts branch August 11, 2025 06:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants