Skip to content

Add source code capture for exception traces #229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: 1.x
Choose a base branch
from

Conversation

philliphartin
Copy link
Contributor

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 exceptions.capture_source_lines configuration option (defaults to true)
  • Can be controlled via NIGHTWATCH_EXCEPTION_CAPTURE_SOURCE_LINES 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.

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.

2 participants