NewRelicHandler.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <?php
  2. /*
  3. * This file is part of the Monolog package.
  4. *
  5. * (c) Jordi Boggiano <j.boggiano@seld.be>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Monolog\Handler;
  11. use Monolog\Logger;
  12. /**
  13. * Class to record a log on a NewRelic application.
  14. * Enabling New Relic High Security mode may prevent capture of useful information.
  15. *
  16. * @see https://docs.newrelic.com/docs/agents/php-agent
  17. * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
  18. */
  19. class NewRelicHandler extends AbstractProcessingHandler
  20. {
  21. /**
  22. * Name of the New Relic application that will receive logs from this handler.
  23. *
  24. * @var string
  25. */
  26. protected $appName;
  27. /**
  28. * Name of the current transaction
  29. *
  30. * @var string
  31. */
  32. protected $transactionName;
  33. /**
  34. * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
  35. * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
  36. *
  37. * @var boolean
  38. */
  39. protected $explodeArrays;
  40. /**
  41. * {@inheritDoc}
  42. *
  43. * @param string $appName
  44. * @param boolean $explodeArrays
  45. * @param string $transactionName
  46. */
  47. public function __construct(
  48. $level = Logger::ERROR,
  49. $bubble = true,
  50. $appName = null,
  51. $explodeArrays = false,
  52. $transactionName = null
  53. ) {
  54. parent::__construct($level, $bubble);
  55. $this->appName = $appName;
  56. $this->explodeArrays = $explodeArrays;
  57. $this->transactionName = $transactionName;
  58. }
  59. /**
  60. * {@inheritDoc}
  61. */
  62. protected function write(array $record)
  63. {
  64. if (!$this->isNewRelicEnabled()) {
  65. throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
  66. }
  67. if ($appName = $this->getAppName($record['context'])) {
  68. $this->setNewRelicAppName($appName);
  69. }
  70. if ($transactionName = $this->getTransactionName($record['context'])) {
  71. $this->setNewRelicTransactionName($transactionName);
  72. unset($record['context']['transaction_name']);
  73. }
  74. if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Exception) {
  75. newrelic_notice_error($record['message'], $record['context']['exception']);
  76. unset($record['context']['exception']);
  77. } else {
  78. newrelic_notice_error($record['message']);
  79. }
  80. foreach ($record['context'] as $key => $parameter) {
  81. if (is_array($parameter) && $this->explodeArrays) {
  82. foreach ($parameter as $paramKey => $paramValue) {
  83. newrelic_add_custom_parameter('context_' . $key . '_' . $paramKey, $paramValue);
  84. }
  85. } else {
  86. newrelic_add_custom_parameter('context_' . $key, $parameter);
  87. }
  88. }
  89. foreach ($record['extra'] as $key => $parameter) {
  90. if (is_array($parameter) && $this->explodeArrays) {
  91. foreach ($parameter as $paramKey => $paramValue) {
  92. newrelic_add_custom_parameter('extra_' . $key . '_' . $paramKey, $paramValue);
  93. }
  94. } else {
  95. newrelic_add_custom_parameter('extra_' . $key, $parameter);
  96. }
  97. }
  98. }
  99. /**
  100. * Checks whether the NewRelic extension is enabled in the system.
  101. *
  102. * @return bool
  103. */
  104. protected function isNewRelicEnabled()
  105. {
  106. return extension_loaded('newrelic');
  107. }
  108. /**
  109. * Returns the appname where this log should be sent. Each log can override the default appname, set in this
  110. * handler's constructor, by providing the appname in it's context.
  111. *
  112. * @param array $context
  113. * @return null|string
  114. */
  115. protected function getAppName(array $context)
  116. {
  117. if (isset($context['appname'])) {
  118. return $context['appname'];
  119. }
  120. return $this->appName;
  121. }
  122. /**
  123. * Returns the name of the current transaction. Each log can override the default transaction name, set in this
  124. * handler's constructor, by providing the transaction_name in it's context
  125. *
  126. * @param array $context
  127. *
  128. * @return null|string
  129. */
  130. protected function getTransactionName(array $context)
  131. {
  132. if (isset($context['transaction_name'])) {
  133. return $context['transaction_name'];
  134. }
  135. return $this->transactionName;
  136. }
  137. /**
  138. * Sets the NewRelic application that should receive this log.
  139. *
  140. * @param string $appName
  141. */
  142. protected function setNewRelicAppName($appName)
  143. {
  144. newrelic_set_appname($appName);
  145. }
  146. /**
  147. * Overwrites the name of the current transaction
  148. *
  149. * @param $transactionName
  150. */
  151. protected function setNewRelicTransactionName($transactionName)
  152. {
  153. newrelic_name_transaction($transactionName);
  154. }
  155. }