Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pitcher Bundle Laravel Package

braune-digital/pitcher-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require braune-digital/pitcher-bundle
    

    Add to config/bundles.php (Symfony 4+):

    return [
        // ...
        BrauneDigital\PitcherBundle\BrauneDigitalPitcherBundle::class => ['all' => true],
    ];
    
  2. Configure via config/packages/braune_digital_pitcher.yaml

    braune_digital_pitcher:
        secret: '%env(PITCHER_SECRET)%'  # Replace with your Pitcher secret
        project_id: '%env(PITCHER_PROJECT_ID)%'
        environment: '%kernel.environment%'
        debug: '%kernel.debug%'
    
  3. First Use Case: Logging an Exception Inject the PitcherClient service and use it in an exception handler or controller:

    use BrauneDigital\PitcherBundle\Client\PitcherClientInterface;
    
    public function __construct(private PitcherClientInterface $pitcher)
    {
    }
    
    public function handleException(Exception $e)
    {
        $this->pitcher->sendException($e);
    }
    

Implementation Patterns

Core Workflows

  1. Exception Logging

    • Use PitcherClientInterface in exception handlers (e.g., EventListener for KernelExceptionEvent).
    • Attach context data (e.g., user ID, request data) via the sendException() method’s optional arguments:
      $this->pitcher->sendException($e, [
          'user_id' => $user->id,
          'request_data' => $request->request->all(),
      ]);
      
  2. Configuration Management

    • Override default config via environment variables or config/packages/.
    • Disable in non-production environments by setting debug: true (Pitcher ignores debug environments by default).
  3. Integration with Monolog

    • Extend Monolog handlers to forward critical logs to Pitcher:
      use Monolog\Handler\AbstractProcessingHandler;
      use BrauneDigital\PitcherBundle\Client\PitcherClientInterface;
      
      class PitcherHandler extends AbstractProcessingHandler
      {
          public function __construct(PitcherClientInterface $pitcher)
          {
              parent::__construct($pitcher, Monolog\Logger::ERROR);
          }
      
          protected function write(array $record): void
          {
              $this->pitcher->sendException(new \RuntimeException($record['message']));
          }
      }
      
    • Register in services.yaml:
      services:
          Monolog\Handler\PitcherHandler:
              arguments: ['@braune_digital_pitcher.client']
              tags: ['monolog.handler']
      
  4. Custom Metadata

    • Pass structured metadata (e.g., ['trace_id' => $request->headers->get('X-Trace-ID')]) to enrich Pitcher’s exception context.

Gotchas and Tips

Pitfalls

  1. Secret Management

    • Never hardcode secrets in config files. Use env() or Symfony’s %env() syntax.
    • Validation: The bundle silently fails if the secret or project_id is missing. Validate in config/validator.yaml:
      services:
          BrauneDigital\PitcherBundle\Validator\Constraints\ValidPitcherConfig:
              tags: [validator.constraint_validator]
      
  2. Environment Filtering

    • Pitcher ignores exceptions from debug: true environments. Explicitly set debug: false in production config.
  3. Rate Limiting

    • Pitcher’s API may throttle requests. Implement a retry mechanism in a custom service wrapper:
      use Symfony\Contracts\HttpClient\HttpClientInterface;
      
      class RetryPitcherClient implements PitcherClientInterface
      {
          public function sendException(Exception $e, array $context = []): void
          {
              $client = HttpClientInterface::create();
              $response = $client->post('https://api.pitcher-app.com/exceptions', [
                  'json' => [
                      'secret' => $this->secret,
                      'exception' => $e->getMessage(),
                      'context' => $context,
                  ],
              ]);
      
              if ($response->getStatusCode() === 429) {
                  sleep(1); // Retry after 1 second
                  $this->sendException($e, $context);
              }
          }
      }
      
  4. Deprecated Bundle

    • The package is archived (last release: 2019). Fork or wrap it in a custom service for long-term use.

Debugging Tips

  1. Enable HTTP Debugging Add VERBOSITY: 2 to your .env to log Pitcher API requests:

    SYMFONY_VERBOSITY=2
    
  2. Mock Pitcher in Tests Use a mock PitcherClientInterface in PHPUnit:

    $mockPitcher = $this->createMock(PitcherClientInterface::class);
    $mockPitcher->expects($this->once())
                ->method('sendException')
                ->with($this->isInstanceOf(Exception::class));
    
    $this->container->set(PitcherClientInterface::class, $mockPitcher);
    
  3. Check Response Codes Wrap sendException() calls to log HTTP errors:

    try {
        $this->pitcher->sendException($e);
    } catch (\RuntimeException $e) {
        $this->logger->error('Pitcher API failed', ['exception' => $e->getMessage()]);
    }
    

Extension Points

  1. Custom Exception Formatter Override the default exception serialization by extending BrauneDigital\PitcherBundle\Formatter\ExceptionFormatter:

    class CustomExceptionFormatter extends ExceptionFormatter
    {
        public function format(Exception $e): array
        {
            $data = parent::format($e);
            $data['custom_field'] = $this->getCustomData($e);
            return $data;
        }
    }
    

    Register in services.yaml:

    services:
        BrauneDigital\PitcherBundle\Formatter\ExceptionFormatter:
            class: App\CustomExceptionFormatter
    
  2. Async Processing Use Symfony’s Messenger component to offload Pitcher calls to a queue:

    use Symfony\Component\Messenger\MessageBusInterface;
    
    class PitcherMessage
    {
        public function __construct(private Exception $exception, private array $context) {}
    }
    
    // Handler
    class PitcherHandler
    {
        public function __invoke(PitcherMessage $message)
        {
            $this->pitcher->sendException($message->exception, $message->context);
        }
    }
    
  3. Webhook Integration Trigger Pitcher from frontend errors via a Symfony controller:

    #[Route('/api/errors', methods: ['POST'])]
    public function reportError(Request $request, PitcherClientInterface $pitcher): JsonResponse
    {
        $data = json_decode($request->getContent(), true);
        $pitcher->sendException(new \RuntimeException($data['message']), $data['context']);
        return new JsonResponse(['status' => 'received']);
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours