Installation
composer require ekino/newrelic-bundle
Add to config/bundles.php:
Ekino\NewRelicBundle\EkinoNewRelicBundle::class => ['all' => true],
Configuration
Add to config/packages/ekino_newrelic.yaml:
ekino_newrelic:
license_key: '%env(NEW_RELIC_LICENSE_KEY)%'
application_name: '%env(NEW_RELIC_APP_NAME)%'
First Use Case
php bin/console cache:clear) and check New Relic for the transaction named after the command.Custom Transaction Naming
Override the default naming strategy by implementing Ekino\NewRelicBundle\TransactionNamingStrategy\TransactionNamingStrategyInterface:
// src/Transaction/Naming/CustomNamingStrategy.php
use Ekino\NewRelicBundle\TransactionNamingStrategy\TransactionNamingStrategyInterface;
class CustomNamingStrategy implements TransactionNamingStrategyInterface
{
public function getTransactionName(Request $request): string
{
return 'Custom:' . $request->get('_route');
}
}
Register in config/packages/ekino_newrelic.yaml:
ekino_newrelic:
transaction_naming_strategy: App\Transaction\Naming\CustomNamingStrategy
Ignoring Routes/URLs Exclude specific routes or URLs from tracking:
ekino_newrelic:
ignored_routes: ['app_login', 'app_logout']
ignored_urls: ['^/health', '^/api/v1/webhooks']
Custom Attributes Add custom attributes to transactions (e.g., user ID, plan type):
use Ekino\NewRelicBundle\NewRelic;
class MyController extends AbstractController
{
public function index(Request $request, NewRelic $newRelic)
{
$newRelic->addCustomAttribute('user_id', $request->get('user_id'));
return $this->render('...');
}
}
Error Handling Automatically capture exceptions with custom error messages:
$newRelic->noticeError('Failed to process payment', ['user_id' => 123]);
Background Jobs Name background jobs (e.g., queues) explicitly:
$newRelic->setTransactionName('Background:ProcessOrder');
Symfony Events
Listen to kernel.request to dynamically modify transaction names or attributes:
// src/EventListener/NewRelicListener.php
use Ekino\NewRelicBundle\NewRelic;
use Symfony\Component\HttpKernel\Event\RequestEvent;
class NewRelicListener
{
public function onKernelRequest(RequestEvent $event, NewRelic $newRelic)
{
if ($event->isMainRequest()) {
$newRelic->addCustomAttribute('locale', $event->getRequest()->getLocale());
}
}
}
Register in config/services.yaml:
services:
App\EventListener\NewRelicListener:
tags:
- { name: 'kernel.event_listener', event: 'kernel.request', method: 'onKernelRequest' }
API Requests
For API endpoints, use Ekino\NewRelicBundle\NewRelic to set custom transaction names:
$newRelic->setTransactionName('API:Users:Get');
Console Commands
Extend Ekino\NewRelicBundle\Command\NewRelicAwareCommand for automatic command naming:
use Ekino\NewRelicBundle\Command\NewRelicAwareCommand;
class MyCommand extends NewRelicAwareCommand
{
protected function configure()
{
$this->setName('app:custom-task');
// Transaction name auto-set to 'app:custom-task'
}
}
License Key Validation
NEW_RELIC_DEBUG env var to enable verbose logging:
ekino_newrelic:
debug: '%env(bool:NEW_RELIC_DEBUG)%'
Transaction Name Collisions
controller_name_action) may clash with other transactions. Use ignored_routes or a custom strategy to avoid duplicates.Custom:MyTransaction).Console Command Overhead
ekino_newrelic:
ignore_console_commands: ['app:long-running-task']
Attribute Limits
serialize() for complex data and truncate strings:
$newRelic->addCustomAttribute('user_data', substr(serialize($user), 0, 1000));
Caching and New Relic
cache:page) may show as duplicate transactions. Use ignored_urls to exclude cache routes:
ekino_newrelic:
ignored_urls: ['^/cache']
Symfony 5.4+ Deprecations
Enable Debug Mode
ekino_newrelic:
debug: true
var/log/dev.log.Check Transaction Names
NewRelic::getTransactionName() to verify current transaction names in runtime:
$currentName = $newRelic->getTransactionName();
$this->addFlash('debug', "Current transaction: $currentName");
New Relic UI Tips
symfony.route or symfony.controller in the New Relic dashboard.Common Errors
NEW_RELIC_LICENSE_KEY and check for typos.Custom Transaction Naming Strategies
TransactionNamingStrategyInterface for full control over naming logic. Example:
class RouteBasedNamingStrategy implements TransactionNamingStrategyInterface
{
public function getTransactionName(Request $request): string
{
$route = $request->attributes->get('_route');
return $route ? "Route:$route" : 'Unknown';
}
}
Event Listeners
ekino_newrelic.transaction events:
use Ekino\NewRelicBundle\Event\TransactionEvent;
$dispatcher->addListener('ekino_newrelic.transaction', function (TransactionEvent $event) {
if ($event->getTransactionName() === 'API:Users:Get') {
$event->setTransactionName('API:Users:Fetch');
}
});
Custom Metrics
NewRelic service:
$newRelic->increment('custom.metric.count');
$newRelic->recordMetric('custom.metric.value', 42);
Middleware Integration
use Ekino\NewRelicBundle\NewRelic;
class NewRelicMiddleware implements MiddlewareInterface
{
public function __construct(private NewRelic $newRelic) {}
public function process(Request $request, RequestHandler $handler): Response
{
$this->newRelic->addCustomAttribute('middleware', 'auth');
return $handler->handle($request);
}
}
How can I help you explore Laravel packages today?