Advertisement
Guest User

Untitled

a guest
Apr 25th, 2018
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 43.22 KB | None | 0 0
  1. <?php
  2.  
  3. /*
  4. * This file is part of the Symfony package.
  5. *
  6. * (c) Fabien Potencier <fabien@symfony.com>
  7. *
  8. * For the full copyright and license information, please view the LICENSE
  9. * file that was distributed with this source code.
  10. */
  11.  
  12. namespace Symfony\Bundle\MonologBundle\DependencyInjection;
  13.  
  14. use Symfony\Component\Config\Definition\Builder\TreeBuilder;
  15. use Symfony\Component\Config\Definition\ConfigurationInterface;
  16. use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
  17. use Monolog\Logger;
  18.  
  19. /**
  20. * This class contains the configuration information for the bundle
  21. *
  22. * This information is solely responsible for how the different configuration
  23. * sections are normalized, and merged.
  24. *
  25. * Possible handler types and related configurations (brackets indicate optional params):
  26. *
  27. * - service:
  28. * - id
  29. *
  30. * - stream:
  31. * - path: string
  32. * - [level]: level name or int value, defaults to DEBUG
  33. * - [bubble]: bool, defaults to true
  34. *
  35. * - console:
  36. * - [verbosity_levels]: level => verbosity configuration
  37. * - [level]: level name or int value, defaults to DEBUG
  38. * - [bubble]: bool, defaults to true
  39. *
  40. * - firephp:
  41. * - [level]: level name or int value, defaults to DEBUG
  42. * - [bubble]: bool, defaults to true
  43. *
  44. * - browser_console:
  45. * - [level]: level name or int value, defaults to DEBUG
  46. * - [bubble]: bool, defaults to true
  47. *
  48. * - gelf:
  49. * - publisher: {id: ...} or {hostname: ..., port: ..., chunk_size: ...}
  50. * - [level]: level name or int value, defaults to DEBUG
  51. * - [bubble]: bool, defaults to true
  52. *
  53. * - chromephp:
  54. * - [level]: level name or int value, defaults to DEBUG
  55. * - [bubble]: bool, defaults to true
  56. *
  57. * - rotating_file:
  58. * - path: string
  59. * - [max_files]: files to keep, defaults to zero (infinite)
  60. * - [level]: level name or int value, defaults to DEBUG
  61. * - [bubble]: bool, defaults to true
  62. * - [file_permission]: string|null, defaults to null
  63. * - [filename_format]: string, defaults to '{filename}-{date}'
  64. * - [date_format]: string, defaults to 'Y-m-d'
  65. *
  66. * - mongo:
  67. * - mongo:
  68. * - id: optional if host is given
  69. * - host: database host name, optional if id is given
  70. * - [port]: defaults to 27017
  71. * - [user]: database user name
  72. * - pass: mandatory only if user is present
  73. * - [database]: defaults to monolog
  74. * - [collection]: defaults to logs
  75. * - [level]: level name or int value, defaults to DEBUG
  76. * - [bubble]: bool, defaults to true
  77. *
  78. * - elasticsearch:
  79. * - elasticsearch:
  80. * - id: optional if host is given
  81. * - host: elastic search host name
  82. * - [port]: defaults to 9200
  83. * - [index]: index name, defaults to monolog
  84. * - [document_type]: document_type, defaults to logs
  85. * - [level]: level name or int value, defaults to DEBUG
  86. * - [bubble]: bool, defaults to true
  87. *
  88. * - fingers_crossed:
  89. * - handler: the wrapped handler's name
  90. * - [action_level|activation_strategy]: minimum level or service id to activate the handler, defaults to WARNING
  91. * - [excluded_404s]: if set, the strategy will be changed to one that excludes 404s coming from URLs matching any of those patterns
  92. * - [buffer_size]: defaults to 0 (unlimited)
  93. * - [stop_buffering]: bool to disable buffering once the handler has been activated, defaults to true
  94. * - [passthru_level]: level name or int value for messages to always flush, disabled by default
  95. * - [bubble]: bool, defaults to true
  96. *
  97. * - filter:
  98. * - handler: the wrapped handler's name
  99. * - [accepted_levels]: list of levels to accept
  100. * - [min_level]: minimum level to accept (only used if accepted_levels not specified)
  101. * - [max_level]: maximum level to accept (only used if accepted_levels not specified)
  102. * - [bubble]: bool, defaults to true
  103. *
  104. * - buffer:
  105. * - handler: the wrapped handler's name
  106. * - [buffer_size]: defaults to 0 (unlimited)
  107. * - [level]: level name or int value, defaults to DEBUG
  108. * - [bubble]: bool, defaults to true
  109. * - [flush_on_overflow]: bool, defaults to false
  110. *
  111. * - deduplication:
  112. * - handler: the wrapper handler's name
  113. * - [store]: The file/path where the deduplication log should be kept, defaults to %kernel.cache_dir%/monolog_dedup_*
  114. * - [deduplication_level]: The minimum logging level for log records to be looked at for deduplication purposes, defaults to ERROR
  115. * - [time]: The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through, defaults to 60
  116. * - [bubble]: bool, defaults to true
  117. *
  118. * - group:
  119. * - members: the wrapped handlers by name
  120. * - [bubble]: bool, defaults to true
  121. *
  122. * - whatfailuregroup:
  123. * - members: the wrapped handlers by name
  124. * - [bubble]: bool, defaults to true
  125. *
  126. * - syslog:
  127. * - ident: string
  128. * - [facility]: defaults to 'user', use any of the LOG_* facility constant but without LOG_ prefix, e.g. user for LOG_USER
  129. * - [logopts]: defaults to LOG_PID
  130. * - [level]: level name or int value, defaults to DEBUG
  131. * - [bubble]: bool, defaults to true
  132. *
  133. * - syslogudp:
  134. * - host: syslogd host name
  135. * - [port]: defaults to 514
  136. * - [facility]: defaults to 'user', use any of the LOG_* facility constant but without LOG_ prefix, e.g. user for LOG_USER
  137. * - [logopts]: defaults to LOG_PID
  138. * - [level]: level name or int value, defaults to DEBUG
  139. * - [bubble]: bool, defaults to true
  140. *
  141. * - swift_mailer:
  142. * - from_email: optional if email_prototype is given
  143. * - to_email: optional if email_prototype is given
  144. * - subject: optional if email_prototype is given
  145. * - [email_prototype]: service id of a message, defaults to a default message with the three fields above
  146. * - [content_type]: optional if email_prototype is given, defaults to text/plain
  147. * - [mailer]: mailer service, defaults to mailer
  148. * - [level]: level name or int value, defaults to DEBUG
  149. * - [bubble]: bool, defaults to true
  150. * - [lazy]: use service lazy loading, bool, defaults to true
  151. *
  152. * - native_mailer:
  153. * - from_email: string
  154. * - to_email: string
  155. * - subject: string
  156. * - [level]: level name or int value, defaults to DEBUG
  157. * - [bubble]: bool, defaults to true
  158. *
  159. * - socket:
  160. * - connection_string: string
  161. * - [timeout]: float
  162. * - [connection_timeout]: float
  163. * - [persistent]: bool
  164. * - [level]: level name or int value, defaults to DEBUG
  165. * - [bubble]: bool, defaults to true
  166. *
  167. * - pushover:
  168. * - token: pushover api token
  169. * - user: user id or array of ids
  170. * - [title]: optional title for messages, defaults to the server hostname
  171. * - [level]: level name or int value, defaults to DEBUG
  172. * - [bubble]: bool, defaults to true
  173. *
  174. * - raven:
  175. * - dsn: connection string
  176. * - client_id: Raven client custom service id (optional)
  177. * - [release]: release number of the application that will be attached to logs, defaults to null
  178. * - [level]: level name or int value, defaults to DEBUG
  179. * - [bubble]: bool, defaults to true
  180. * - [auto_stack_logs]: bool, defaults to false
  181. *
  182. * - newrelic:
  183. * - [level]: level name or int value, defaults to DEBUG
  184. * - [bubble]: bool, defaults to true
  185. * - [app_name]: new relic app name, default null
  186. *
  187. * - hipchat:
  188. * - token: hipchat api token
  189. * - room: room id or name
  190. * - [notify]: defaults to false
  191. * - [nickname]: defaults to Monolog
  192. * - [level]: level name or int value, defaults to DEBUG
  193. * - [bubble]: bool, defaults to true
  194. * - [use_ssl]: bool, defaults to true
  195. * - [message_format]: text or html, defaults to text
  196. * - [host]: defaults to "api.hipchat.com"
  197. * - [api_version]: defaults to "v1"
  198. *
  199. * - slack:
  200. * - token: slack api token
  201. * - channel: channel name (with starting #)
  202. * - [bot_name]: defaults to Monolog
  203. * - [icon_emoji]: defaults to null
  204. * - [use_attachment]: bool, defaults to true
  205. * - [use_short_attachment]: bool, defaults to false
  206. * - [include_extra]: bool, defaults to false
  207. * - [level]: level name or int value, defaults to DEBUG
  208. * - [bubble]: bool, defaults to true
  209. *
  210. * - cube:
  211. * - url: http/udp url to the cube server
  212. * - [level]: level name or int value, defaults to DEBUG
  213. * - [bubble]: bool, defaults to true
  214. *
  215. * - amqp:
  216. * - exchange: service id of an AMQPExchange
  217. * - [exchange_name]: string, defaults to log
  218. * - [level]: level name or int value, defaults to DEBUG
  219. * - [bubble]: bool, defaults to true
  220. *
  221. * - error_log:
  222. * - [message_type]: int 0 or 4, defaults to 0
  223. * - [level]: level name or int value, defaults to DEBUG
  224. * - [bubble]: bool, defaults to true
  225. *
  226. * - null:
  227. * - [level]: level name or int value, defaults to DEBUG
  228. * - [bubble]: bool, defaults to true
  229. *
  230. * - test:
  231. * - [level]: level name or int value, defaults to DEBUG
  232. * - [bubble]: bool, defaults to true
  233. *
  234. * - debug:
  235. * - [level]: level name or int value, defaults to DEBUG
  236. * - [bubble]: bool, defaults to true
  237. *
  238. * - loggly:
  239. * - token: loggly api token
  240. * - [level]: level name or int value, defaults to DEBUG
  241. * - [bubble]: bool, defaults to true
  242. * - [tags]: tag names
  243. *
  244. * - logentries:
  245. * - token: logentries api token
  246. * - [use_ssl]: whether or not SSL encryption should be used, defaults to true
  247. * - [level]: level name or int value, defaults to DEBUG
  248. * - [bubble]: bool, defaults to true
  249. * - [timeout]: float
  250. * - [connection_timeout]: float
  251. *
  252. * - flowdock:
  253. * - token: flowdock api token
  254. * - source: human readable identifier of the application
  255. * - from_email: email address of the message sender
  256. * - [level]: level name or int value, defaults to DEBUG
  257. * - [bubble]: bool, defaults to true
  258. *
  259. * - rollbar:
  260. * - id: RollbarNotifier service (mandatory if token is not provided)
  261. * - token: rollbar api token (skip if you provide a RollbarNotifier service id)
  262. * - [config]: config values from https://github.com/rollbar/rollbar-php#configuration-reference
  263. * - [level]: level name or int value, defaults to DEBUG
  264. * - [bubble]: bool, defaults to true
  265. *
  266. * @author Jordi Boggiano <j.boggiano@seld.be>
  267. * @author Christophe Coevoet <stof@notk.org>
  268. */
  269. class Configuration implements ConfigurationInterface
  270. {
  271. /**
  272. * Generates the configuration tree builder.
  273. *
  274. * @return \Symfony\Component\Config\Definition\Builder\TreeBuilder The tree builder
  275. */
  276. public function getConfigTreeBuilder()
  277. {
  278. $treeBuilder = new TreeBuilder();
  279. $rootNode = $treeBuilder->root('monolog');
  280.  
  281. $rootNode
  282. ->fixXmlConfig('channel')
  283. ->fixXmlConfig('handler')
  284. ->children()
  285. ->scalarNode('use_microseconds')->defaultTrue()->end()
  286. ->arrayNode('channels')
  287. ->canBeUnset()
  288. ->prototype('scalar')->end()
  289. ->end()
  290. ->arrayNode('handlers')
  291. ->canBeUnset()
  292. ->useAttributeAsKey('name')
  293. ->prototype('array')
  294. ->fixXmlConfig('member')
  295. ->fixXmlConfig('excluded_404')
  296. ->fixXmlConfig('tag')
  297. ->fixXmlConfig('accepted_level')
  298. ->canBeUnset()
  299. ->children()
  300. ->scalarNode('type')
  301. ->isRequired()
  302. ->treatNullLike('null')
  303. ->beforeNormalization()
  304. ->always()
  305. ->then(function ($v) { return strtolower($v); })
  306. ->end()
  307. ->end()
  308. ->scalarNode('id')->end() // service & rollbar
  309. ->scalarNode('priority')->defaultValue(0)->end()
  310. ->scalarNode('level')->defaultValue('DEBUG')->end()
  311. ->booleanNode('bubble')->defaultTrue()->end()
  312. ->scalarNode('app_name')->defaultNull()->end()
  313. ->booleanNode('include_stacktraces')->defaultFalse()->end()
  314. ->booleanNode('process_psr_3_messages')->defaultTrue()->end()
  315. ->scalarNode('path')->defaultValue('%kernel.logs_dir%/%kernel.environment%.log')->end() // stream and rotating
  316. ->scalarNode('file_permission') // stream and rotating
  317. ->defaultNull()
  318. ->beforeNormalization()
  319. ->ifString()
  320. ->then(function ($v) {
  321. if (substr($v, 0, 1) === '0') {
  322. return octdec($v);
  323. }
  324.  
  325. return (int) $v;
  326. })
  327. ->end()
  328. ->end()
  329. ->scalarNode('filename_format')->defaultValue('{filename}-{date}')->end() //rotating
  330. ->scalarNode('date_format')->defaultValue('Y-m-d')->end() //rotating
  331. ->scalarNode('ident')->defaultFalse()->end() // syslog
  332. ->scalarNode('logopts')->defaultValue(LOG_PID)->end() // syslog
  333. ->scalarNode('facility')->defaultValue('user')->end() // syslog
  334. ->scalarNode('max_files')->defaultValue(0)->end() // rotating
  335. ->scalarNode('action_level')->defaultValue('WARNING')->end() // fingers_crossed
  336. ->scalarNode('activation_strategy')->defaultNull()->end() // fingers_crossed
  337. ->booleanNode('stop_buffering')->defaultTrue()->end()// fingers_crossed
  338. ->scalarNode('passthru_level')->defaultNull()->end() // fingers_crossed
  339. ->arrayNode('excluded_404s') // fingers_crossed
  340. ->canBeUnset()
  341. ->prototype('scalar')->end()
  342. ->end()
  343. ->arrayNode('accepted_levels') // filter
  344. ->canBeUnset()
  345. ->prototype('scalar')->end()
  346. ->end()
  347. ->scalarNode('min_level')->defaultValue('DEBUG')->end() // filter
  348. ->scalarNode('max_level')->defaultValue('EMERGENCY')->end() //filter
  349. ->scalarNode('buffer_size')->defaultValue(0)->end() // fingers_crossed and buffer
  350. ->booleanNode('flush_on_overflow')->defaultFalse()->end() // buffer
  351. ->scalarNode('handler')->end() // fingers_crossed and buffer
  352. ->scalarNode('url')->end() // cube
  353. ->scalarNode('exchange')->end() // amqp
  354. ->scalarNode('exchange_name')->defaultValue('log')->end() // amqp
  355. ->scalarNode('room')->end() // hipchat
  356. ->scalarNode('message_format')->defaultValue('text')->end() // hipchat
  357. ->scalarNode('api_version')->defaultNull()->end() // hipchat
  358. ->scalarNode('channel')->end() // slack
  359. ->scalarNode('bot_name')->defaultValue('Monolog')->end() // slack
  360. ->scalarNode('use_attachment')->defaultTrue()->end() // slack
  361. ->scalarNode('use_short_attachment')->defaultFalse()->end() // slack
  362. ->scalarNode('include_extra')->defaultFalse()->end() // slack
  363. ->scalarNode('icon_emoji')->defaultNull()->end() // slack
  364. ->scalarNode('notify')->defaultFalse()->end() // hipchat
  365. ->scalarNode('nickname')->defaultValue('Monolog')->end() // hipchat
  366. ->scalarNode('token')->end() // pushover & hipchat & loggly & logentries & flowdock & rollbar & slack
  367. ->scalarNode('source')->end() // flowdock
  368. ->booleanNode('use_ssl')->defaultTrue()->end() // logentries & hipchat
  369. ->variableNode('user') // pushover
  370. ->validate()
  371. ->ifTrue(function ($v) {
  372. return !is_string($v) && !is_array($v);
  373. })
  374. ->thenInvalid('User must be a string or an array.')
  375. ->end()
  376. ->end()
  377. ->scalarNode('title')->defaultNull()->end() // pushover
  378. ->scalarNode('host')->defaultNull()->end() // syslogudp & hipchat
  379. ->scalarNode('port')->defaultValue(514)->end() // syslogudp
  380. ->arrayNode('publisher')
  381. ->canBeUnset()
  382. ->beforeNormalization()
  383. ->ifString()
  384. ->then(function ($v) { return array('id'=> $v); })
  385. ->end()
  386. ->children()
  387. ->scalarNode('id')->end()
  388. ->scalarNode('hostname')->end()
  389. ->scalarNode('port')->defaultValue(12201)->end()
  390. ->scalarNode('chunk_size')->defaultValue(1420)->end()
  391. ->end()
  392. ->validate()
  393. ->ifTrue(function ($v) {
  394. return !isset($v['id']) && !isset($v['hostname']);
  395. })
  396. ->thenInvalid('What must be set is either the hostname or the id.')
  397. ->end()
  398. ->end() // gelf
  399. ->arrayNode('mongo')
  400. ->canBeUnset()
  401. ->beforeNormalization()
  402. ->ifString()
  403. ->then(function ($v) { return array('id'=> $v); })
  404. ->end()
  405. ->children()
  406. ->scalarNode('id')->end()
  407. ->scalarNode('host')->end()
  408. ->scalarNode('port')->defaultValue(27017)->end()
  409. ->scalarNode('user')->end()
  410. ->scalarNode('pass')->end()
  411. ->scalarNode('database')->defaultValue('monolog')->end()
  412. ->scalarNode('collection')->defaultValue('logs')->end()
  413. ->end()
  414. ->validate()
  415. ->ifTrue(function ($v) {
  416. return !isset($v['id']) && !isset($v['host']);
  417. })
  418. ->thenInvalid('What must be set is either the host or the id.')
  419. ->end()
  420. ->validate()
  421. ->ifTrue(function ($v) {
  422. return isset($v['user']) && !isset($v['pass']);
  423. })
  424. ->thenInvalid('If you set user, you must provide a password.')
  425. ->end()
  426. ->end() // mongo
  427. ->arrayNode('elasticsearch')
  428. ->canBeUnset()
  429. ->beforeNormalization()
  430. ->ifString()
  431. ->then(function ($v) { return array('id'=> $v); })
  432. ->end()
  433. ->children()
  434. ->scalarNode('id')->end()
  435. ->scalarNode('host')->end()
  436. ->scalarNode('port')->defaultValue(9200)->end()
  437. ->scalarNode('transport')->defaultValue('Http')->end()
  438. ->scalarNode('user')->defaultNull()->end()
  439. ->scalarNode('password')->defaultNull()->end()
  440. ->end()
  441. ->validate()
  442. ->ifTrue(function ($v) {
  443. return !isset($v['id']) && !isset($v['host']);
  444. })
  445. ->thenInvalid('What must be set is either the host or the id.')
  446. ->end()
  447. ->end() // elasticsearch
  448. ->scalarNode('index')->defaultValue('monolog')->end() // elasticsearch
  449. ->scalarNode('document_type')->defaultValue('logs')->end() // elasticsearch
  450. ->scalarNode('ignore_error')->defaultValue(false)->end() // elasticsearch
  451. ->arrayNode('config')
  452. ->canBeUnset()
  453. ->prototype('scalar')->end()
  454. ->end() // rollbar
  455. ->arrayNode('members') // group, whatfailuregroup
  456. ->canBeUnset()
  457. ->performNoDeepMerging()
  458. ->prototype('scalar')->end()
  459. ->end()
  460. ->scalarNode('from_email')->end() // swift_mailer, native_mailer and flowdock
  461. ->arrayNode('to_email') // swift_mailer and native_mailer
  462. ->prototype('scalar')->end()
  463. ->beforeNormalization()
  464. ->ifString()
  465. ->then(function ($v) { return array($v); })
  466. ->end()
  467. ->end()
  468. ->scalarNode('subject')->end() // swift_mailer and native_mailer
  469. ->scalarNode('content_type')->defaultNull()->end() // swift_mailer
  470. ->scalarNode('mailer')->defaultValue('mailer')->end() // swift_mailer
  471. ->arrayNode('email_prototype') // swift_mailer
  472. ->canBeUnset()
  473. ->beforeNormalization()
  474. ->ifString()
  475. ->then(function ($v) { return array('id' => $v); })
  476. ->end()
  477. ->children()
  478. ->scalarNode('id')->isRequired()->end()
  479. ->scalarNode('method')->defaultNull()->end()
  480. ->end()
  481. ->end()
  482. ->booleanNode('lazy')->defaultValue(true)->end() // swift_mailer
  483. ->scalarNode('connection_string')->end() // socket_handler
  484. ->scalarNode('timeout')->end() // socket_handler & logentries
  485. ->scalarNode('time')->defaultValue(60)->end() // deduplication
  486. ->scalarNode('deduplication_level')->defaultValue(Logger::ERROR)->end() // deduplication
  487. ->scalarNode('store')->defaultNull()->end() // deduplication
  488. ->scalarNode('connection_timeout')->end() // socket_handler & logentries
  489. ->booleanNode('persistent')->end() // socket_handler
  490. ->scalarNode('dsn')->end() // raven_handler
  491. ->scalarNode('client_id')->defaultNull()->end() // raven_handler
  492. ->scalarNode('auto_log_stacks')->defaultFalse()->end() // raven_handler
  493. ->scalarNode('release')->defaultNull()->end() // raven_handler
  494. ->scalarNode('message_type')->defaultValue(0)->end() // error_log
  495. ->arrayNode('tags') // loggly
  496. ->beforeNormalization()
  497. ->ifString()
  498. ->then(function ($v) { return explode(',', $v); })
  499. ->end()
  500. ->beforeNormalization()
  501. ->ifArray()
  502. ->then(function ($v) { return array_filter(array_map('trim', $v)); })
  503. ->end()
  504. ->prototype('scalar')->end()
  505. ->end()
  506. ->arrayNode('verbosity_levels') // console
  507. ->beforeNormalization()
  508. ->ifArray()
  509. ->then(function ($v) {
  510. $map = array();
  511. $verbosities = array('VERBOSITY_NORMAL', 'VERBOSITY_VERBOSE', 'VERBOSITY_VERY_VERBOSE', 'VERBOSITY_DEBUG');
  512. // allow numeric indexed array with ascendning verbosity and lowercase names of the constants
  513. foreach ($v as $verbosity => $level) {
  514. if (is_int($verbosity) && isset($verbosities[$verbosity])) {
  515. $map[$verbosities[$verbosity]] = strtoupper($level);
  516. } else {
  517. $map[strtoupper($verbosity)] = strtoupper($level);
  518. }
  519. }
  520.  
  521. return $map;
  522. })
  523. ->end()
  524. ->children()
  525. ->scalarNode('VERBOSITY_NORMAL')->defaultValue('WARNING')->end()
  526. ->scalarNode('VERBOSITY_VERBOSE')->defaultValue('NOTICE')->end()
  527. ->scalarNode('VERBOSITY_VERY_VERBOSE')->defaultValue('INFO')->end()
  528. ->scalarNode('VERBOSITY_DEBUG')->defaultValue('DEBUG')->end()
  529. ->end()
  530. ->validate()
  531. ->always(function ($v) {
  532. $map = array();
  533. foreach ($v as $verbosity => $level) {
  534. $verbosityConstant = 'Symfony\Component\Console\Output\OutputInterface::'.$verbosity;
  535.  
  536. if (!defined($verbosityConstant)) {
  537. throw new InvalidConfigurationException(sprintf(
  538. 'The configured verbosity "%s" is invalid as it is not defined in Symfony\Component\Console\Output\OutputInterface.',
  539. $verbosity
  540. ));
  541. }
  542. if (!is_numeric($level)) {
  543. $levelConstant = 'Monolog\Logger::'.$level;
  544. if (!defined($levelConstant)) {
  545. throw new InvalidConfigurationException(sprintf(
  546. 'The configured minimum log level "%s" for verbosity "%s" is invalid as it is not defined in Monolog\Logger.',
  547. $level, $verbosity
  548. ));
  549. }
  550. $level = constant($levelConstant);
  551. } else {
  552. $level = (int) $level;
  553. }
  554.  
  555. $map[constant($verbosityConstant)] = $level;
  556. }
  557.  
  558. return $map;
  559. })
  560. ->end()
  561. ->end()
  562. ->arrayNode('channels')
  563. ->fixXmlConfig('channel', 'elements')
  564. ->canBeUnset()
  565. ->beforeNormalization()
  566. ->ifString()
  567. ->then(function ($v) { return array('elements' => array($v)); })
  568. ->end()
  569. ->beforeNormalization()
  570. ->ifTrue(function ($v) { return is_array($v) && is_numeric(key($v)); })
  571. ->then(function ($v) { return array('elements' => $v); })
  572. ->end()
  573. ->validate()
  574. ->ifTrue(function ($v) { return empty($v); })
  575. ->thenUnset()
  576. ->end()
  577. ->validate()
  578. ->always(function ($v) {
  579. $isExclusive = null;
  580. if (isset($v['type'])) {
  581. $isExclusive = 'exclusive' === $v['type'];
  582. }
  583.  
  584. $elements = array();
  585. foreach ($v['elements'] as $element) {
  586. if (0 === strpos($element, '!')) {
  587. if (false === $isExclusive) {
  588. throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list.');
  589. }
  590. $elements[] = substr($element, 1);
  591. $isExclusive = true;
  592. } else {
  593. if (true === $isExclusive) {
  594. throw new InvalidConfigurationException('Cannot combine exclusive/inclusive definitions in channels list');
  595. }
  596. $elements[] = $element;
  597. $isExclusive = false;
  598. }
  599. }
  600.  
  601. if (!count($elements)) {
  602. return null;
  603. }
  604.  
  605. return array('type' => $isExclusive ? 'exclusive' : 'inclusive', 'elements' => $elements);
  606. })
  607. ->end()
  608. ->children()
  609. ->scalarNode('type')
  610. ->validate()
  611. ->ifNotInArray(array('inclusive', 'exclusive'))
  612. ->thenInvalid('The type of channels has to be inclusive or exclusive')
  613. ->end()
  614. ->end()
  615. ->arrayNode('elements')
  616. ->prototype('scalar')->end()
  617. ->end()
  618. ->end()
  619. ->end()
  620. ->scalarNode('formatter')->end()
  621. ->booleanNode('nested')->defaultFalse()->end()
  622. ->end()
  623. ->validate()
  624. ->ifTrue(function ($v) { return 'service' === $v['type'] && !empty($v['formatter']); })
  625. ->thenInvalid('Service handlers can not have a formatter configured in the bundle, you must reconfigure the service itself instead')
  626. ->end()
  627. ->validate()
  628. ->ifTrue(function ($v) { return ('fingers_crossed' === $v['type'] || 'buffer' === $v['type'] || 'filter' === $v['type']) && 1 !== count($v['handler']); })
  629. ->thenInvalid('The handler has to be specified to use a FingersCrossedHandler or BufferHandler or FilterHandler')
  630. ->end()
  631. ->validate()
  632. ->ifTrue(function ($v) { return 'fingers_crossed' === $v['type'] && !empty($v['excluded_404s']) && !empty($v['activation_strategy']); })
  633. ->thenInvalid('You can not use excluded_404s together with a custom activation_strategy in a FingersCrossedHandler')
  634. ->end()
  635. ->validate()
  636. ->ifTrue(function ($v) { return 'filter' === $v['type'] && "DEBUG" !== $v['min_level'] && !empty($v['accepted_levels']); })
  637. ->thenInvalid('You can not use min_level together with accepted_levels in a FilterHandler')
  638. ->end()
  639. ->validate()
  640. ->ifTrue(function ($v) { return 'filter' === $v['type'] && "EMERGENCY" !== $v['max_level'] && !empty($v['accepted_levels']); })
  641. ->thenInvalid('You can not use max_level together with accepted_levels in a FilterHandler')
  642. ->end()
  643. ->validate()
  644. ->ifTrue(function ($v) { return 'rollbar' === $v['type'] && !empty($v['id']) && !empty($v['token']); })
  645. ->thenInvalid('You can not use both an id and a token in a RollbarHandler')
  646. ->end()
  647. ->validate()
  648. ->ifTrue(function ($v) { return 'rollbar' === $v['type'] && empty($v['id']) && empty($v['token']); })
  649. ->thenInvalid('The id or the token has to be specified to use a RollbarHandler')
  650. ->end()
  651. ->validate()
  652. ->ifTrue(function ($v) { return 'swift_mailer' === $v['type'] && empty($v['email_prototype']) && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject'])); })
  653. ->thenInvalid('The sender, recipient and subject or an email prototype have to be specified to use a SwiftMailerHandler')
  654. ->end()
  655. ->validate()
  656. ->ifTrue(function ($v) { return 'native_mailer' === $v['type'] && (empty($v['from_email']) || empty($v['to_email']) || empty($v['subject'])); })
  657. ->thenInvalid('The sender, recipient and subject have to be specified to use a NativeMailerHandler')
  658. ->end()
  659. ->validate()
  660. ->ifTrue(function ($v) { return 'service' === $v['type'] && !isset($v['id']); })
  661. ->thenInvalid('The id has to be specified to use a service as handler')
  662. ->end()
  663. ->validate()
  664. ->ifTrue(function ($v) { return 'syslogudp' === $v['type'] && !isset($v['host']); })
  665. ->thenInvalid('The host has to be specified to use a syslogudp as handler')
  666. ->end()
  667. ->validate()
  668. ->ifTrue(function ($v) { return 'gelf' === $v['type'] && !isset($v['publisher']); })
  669. ->thenInvalid('The publisher has to be specified to use a GelfHandler')
  670. ->end()
  671. ->validate()
  672. ->ifTrue(function ($v) { return 'socket' === $v['type'] && !isset($v['connection_string']); })
  673. ->thenInvalid('The connection_string has to be specified to use a SocketHandler')
  674. ->end()
  675. ->validate()
  676. ->ifTrue(function ($v) { return 'pushover' === $v['type'] && (empty($v['token']) || empty($v['user'])); })
  677. ->thenInvalid('The token and user have to be specified to use a PushoverHandler')
  678. ->end()
  679. ->validate()
  680. ->ifTrue(function ($v) { return 'raven' === $v['type'] && !array_key_exists('dsn', $v) && null === $v['client_id']; })
  681. ->thenInvalid('The DSN has to be specified to use a RavenHandler')
  682. ->end()
  683. ->validate()
  684. ->ifTrue(function ($v) { return 'hipchat' === $v['type'] && (empty($v['token']) || empty($v['room'])); })
  685. ->thenInvalid('The token and room have to be specified to use a HipChatHandler')
  686. ->end()
  687. ->validate()
  688. ->ifTrue(function ($v) { return 'hipchat' === $v['type'] && !in_array($v['message_format'], array('text', 'html')); })
  689. ->thenInvalid('The message_format has to be "text" or "html" in a HipChatHandler')
  690. ->end()
  691. ->validate()
  692. ->ifTrue(function ($v) { return 'hipchat' === $v['type'] && null !== $v['api_version'] && !in_array($v['api_version'], array('v1', 'v2'), true); })
  693. ->thenInvalid('The api_version has to be "v1" or "v2" in a HipChatHandler')
  694. ->end()
  695. ->validate()
  696. ->ifTrue(function ($v) { return 'slack' === $v['type'] && (empty($v['token']) || empty($v['channel'])); })
  697. ->thenInvalid('The token and channel have to be specified to use a SlackHandler')
  698. ->end()
  699. ->validate()
  700. ->ifTrue(function ($v) { return 'cube' === $v['type'] && empty($v['url']); })
  701. ->thenInvalid('The url has to be specified to use a CubeHandler')
  702. ->end()
  703. ->validate()
  704. ->ifTrue(function ($v) { return 'mongo' === $v['type'] && !isset($v['mongo']); })
  705. ->thenInvalid('The mongo configuration has to be specified to use a MongoHandler')
  706. ->end()
  707. ->validate()
  708. ->ifTrue(function ($v) { return 'amqp' === $v['type'] && empty($v['exchange']); })
  709. ->thenInvalid('The exchange has to be specified to use a AmqpHandler')
  710. ->end()
  711. ->validate()
  712. ->ifTrue(function ($v) { return 'loggly' === $v['type'] && empty($v['token']); })
  713. ->thenInvalid('The token has to be specified to use a LogglyHandler')
  714. ->end()
  715. ->validate()
  716. ->ifTrue(function ($v) { return 'loggly' === $v['type'] && !empty($v['tags']); })
  717. ->then(function ($v) {
  718. $invalidTags = preg_grep('/^[a-z0-9][a-z0-9\.\-_]*$/i', $v['tags'], PREG_GREP_INVERT);
  719. if (!empty($invalidTags)) {
  720. throw new InvalidConfigurationException(sprintf('The following Loggly tags are invalid: %s.', implode(', ', $invalidTags)));
  721. }
  722.  
  723. return $v;
  724. })
  725. ->end()
  726. ->validate()
  727. ->ifTrue(function ($v) { return 'logentries' === $v['type'] && empty($v['token']); })
  728. ->thenInvalid('The token has to be specified to use a LogEntriesHandler')
  729. ->end()
  730. ->validate()
  731. ->ifTrue(function ($v) { return 'flowdock' === $v['type'] && empty($v['token']); })
  732. ->thenInvalid('The token has to be specified to use a FlowdockHandler')
  733. ->end()
  734. ->validate()
  735. ->ifTrue(function ($v) { return 'flowdock' === $v['type'] && empty($v['from_email']); })
  736. ->thenInvalid('The from_email has to be specified to use a FlowdockHandler')
  737. ->end()
  738. ->validate()
  739. ->ifTrue(function ($v) { return 'flowdock' === $v['type'] && empty($v['source']); })
  740. ->thenInvalid('The source has to be specified to use a FlowdockHandler')
  741. ->end()
  742. ->end()
  743. ->validate()
  744. ->ifTrue(function ($v) { return isset($v['debug']); })
  745. ->thenInvalid('The "debug" name cannot be used as it is reserved for the handler of the profiler')
  746. ->end()
  747. ->example(array(
  748. 'syslog' => array(
  749. 'type' => 'stream',
  750. 'path' => '/var/log/symfony.log',
  751. 'level' => 'ERROR',
  752. 'bubble' => 'false',
  753. 'formatter' => 'my_formatter',
  754. ),
  755. 'main' => array(
  756. 'type' => 'fingers_crossed',
  757. 'action_level' => 'WARNING',
  758. 'buffer_size' => 30,
  759. 'handler' => 'custom',
  760. ),
  761. 'custom' => array(
  762. 'type' => 'service',
  763. 'id' => 'my_handler',
  764. )
  765. ))
  766. ->end()
  767. ->end()
  768. ;
  769.  
  770. return $treeBuilder;
  771. }
  772. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement