{"id":13669206,"url":"https://github.com/theorchard/monolog-cascade","last_synced_at":"2025-04-27T01:32:52.713Z","repository":{"id":28875681,"uuid":"32400011","full_name":"theorchard/monolog-cascade","owner":"theorchard","description":"Configure multiple loggers and handlers in the blink of an eye","archived":false,"fork":false,"pushed_at":"2024-07-10T19:15:43.000Z","size":139,"stargazers_count":145,"open_issues_count":17,"forks_count":62,"subscribers_count":64,"default_branch":"master","last_synced_at":"2024-11-11T05:39:38.549Z","etag":null,"topics":["formatters","handlers","logger","logging","monolog","monolog-cascade","php","processor"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theorchard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-03-17T14:57:15.000Z","updated_at":"2024-08-15T04:31:04.000Z","dependencies_parsed_at":"2024-06-18T11:26:46.545Z","dependency_job_id":"904d4198-2b07-4630-9ef8-414e5f3825e6","html_url":"https://github.com/theorchard/monolog-cascade","commit_stats":{"total_commits":81,"total_committers":24,"mean_commits":3.375,"dds":0.6666666666666667,"last_synced_commit":"9ea42aa6b7ea18322ded0d9cfbcea5761fd0a57d"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theorchard%2Fmonolog-cascade","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theorchard%2Fmonolog-cascade/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theorchard%2Fmonolog-cascade/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theorchard%2Fmonolog-cascade/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theorchard","download_url":"https://codeload.github.com/theorchard/monolog-cascade/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251077102,"owners_count":21532607,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["formatters","handlers","logger","logging","monolog","monolog-cascade","php","processor"],"created_at":"2024-08-02T08:01:06.109Z","updated_at":"2025-04-27T01:32:48.306Z","avatar_url":"https://github.com/theorchard.png","language":"PHP","funding_links":[],"categories":["PHP"],"sub_categories":[],"readme":"Monolog Cascade [![Build Status](https://travis-ci.org/theorchard/monolog-cascade.svg?branch=master)](https://travis-ci.org/theorchard/monolog-cascade) [![Coverage Status](https://coveralls.io/repos/theorchard/monolog-cascade/badge.svg?branch=master)](https://coveralls.io/r/theorchard/monolog-cascade?branch=master)\n===============\n\nWhat is Monolog Cascade?\n------------------------\n\nMonolog Cascade is a [Monolog](https://github.com/Seldaek/monolog) extension that allows you to set up and configure multiple loggers and handlers from a single config file.\n\nIt's been inspired by the [`logging.config`](https://docs.python.org/3.4/library/logging.config.html?highlight=fileconfig#module-logging.config) Python module.\n\n\n------------\n\n\nInstallation\n------------\n\nAdd `monolog-cascade` as a requirement in your `composer.json` file or run\n```sh\n$ composer require theorchard/monolog-cascade\n```\n\nNote: Monolog Cascade requires PHP 5.3.9 or higher.\n\nUsage\n-----\n\n```php\n\u003c?php\nuse Cascade\\Cascade;\n\n// configure your loggers\nCascade::fileConfig('path/to/some/config.yaml');\n\n// or use php array\n$config = require 'config.php';\nCascade::fileConfig($config);\n\n```\n\nThen just use your logger as shown below\n```php\nCascade::getLogger('myLogger')-\u003einfo('Well, that works!');\nCascade::getLogger('myLogger')-\u003eerror('Maybe not...');\n```\n\nConfiguring your loggers\n------------------------\nMonolog Cascade supports the following config formats:\n - Yaml\n - JSON\n - PHP File returning Array\n - PHP Array\n\n### Configuration structure\nHere is a sample Yaml config file:\n```yaml\n\nformatters:\n    dashed:\n        class: Monolog\\Formatter\\LineFormatter\n        format: \"%datetime%-%channel%.%level_name% - %message%\\n\"\nhandlers:\n    console:\n        class: Monolog\\Handler\\StreamHandler\n        level: DEBUG\n        formatter: dashed\n        processors: [memory_processor]\n        stream: php://stdout\n    info_file_handler:\n        class: Monolog\\Handler\\StreamHandler\n        level: INFO\n        formatter: dashed\n        stream: ./example_info.log\nprocessors:\n    web_processor:\n        class: Monolog\\Processor\\WebProcessor\n    memory_processor:\n        class: Monolog\\Processor\\MemoryUsageProcessor\nloggers:\n    myLogger:\n        handlers: [console, info_file_handler]\n        processors: [web_processor]\n```\n\nHere is a sample PHP config file:\n```php\n\u003c?php\n\nreturn array(\n    'version' =\u003e 1,\n\n    'formatters' =\u003e array(\n        'spaced' =\u003e array(\n            'format' =\u003e \"%datetime% %channel%.%level_name%  %message%\\n\",\n            'include_stacktraces' =\u003e true\n        ),\n        'dashed' =\u003e array(\n            'format' =\u003e \"%datetime%-%channel%.%level_name% - %message%\\n\"\n        ),\n    ),\n    'handlers' =\u003e array(\n        'console' =\u003e array(\n            'class' =\u003e 'Monolog\\Handler\\StreamHandler',\n            'level' =\u003e 'DEBUG',\n            'formatter' =\u003e 'spaced',\n            'stream' =\u003e 'php://stdout'\n        ),\n\n        'info_file_handler' =\u003e array(\n            'class' =\u003e 'Monolog\\Handler\\StreamHandler',\n            'level' =\u003e 'INFO',\n            'formatter' =\u003e 'dashed',\n            'stream' =\u003e './demo_info.log'\n        ),\n\n        'error_file_handler' =\u003e array(\n            'class' =\u003e 'Monolog\\Handler\\StreamHandler',\n            'level' =\u003e 'ERROR',\n            'stream' =\u003e './demo_error.log',\n            'formatter' =\u003e 'spaced'\n        )\n    ),\n    'processors' =\u003e array(\n        'tag_processor' =\u003e array(\n            'class' =\u003e 'Monolog\\Processor\\TagProcessor'\n        )\n    ),\n    'loggers' =\u003e array(\n        'my_logger' =\u003e array(\n            'handlers' =\u003e array('console', 'info_file_handler')\n        )\n    )\n);\n```\n\nMore information on how the Cascade config parser loads and reads the parameters:\n\nOnly the `loggers` key is required. If `formatters` and/or `handlers` are ommitted, Monolog's default will be used. `processors` is optional and if ommitted, no processors will be used. (See the \"Optional Keys\" section further below).\n\nOther keys are optional and would be interpreted as described below:\n\n- **_formatters_** - the derived associative array (from the Yaml or JSON) in which each key is the formatter identifier holds keys/values to configure your formatters.\nThe only _reserved_ key is `class` and it should contain the classname of the formatter you would like to use. Other parameters will be interpreted as constructor parameters for that class and passed in when the formatter object is instanced by the Cascade config loader.\u003cbr /\u003e\nIf some parameters are not present in the constructor, they will be treated as extra parameters and Cascade will try to interpret them should they match any custom handler functions that are able to use them. (see [Extra Parameters](#user-content-extra-parameters-other-than-constructors) section below)\u003cbr /\u003e\n\n    If `class` is not provided Cascade will default to `Monolog\\Formatter\\LineFormatter`\n\n- **_handlers_** - the derived associative array (from the Yaml or JSON) in which each key is the handler identifier holds keys/values to configure your handlers.\u003cbr /\u003eThe following keys are _reserved_:\n    - `class` (optional): classname of the handler you would like to use\n    - `formatter` (optional): formatter identifier that you have defined\n    - `processors` (optional): array of processor identifiers that you have defined\n    - `handlers` (optional): array of handler identifiers that you have defined\n    - `handler` (optional): single handler identifier that you have defined\n\n    Other parameters will be interpreted as constructor parameters for that Handler class and passed in when the handler object is instantiated by the Cascade config loader.\u003cbr /\u003e\n    If some parameters are not present in the constructor, they will be interpreted as extra parameters and Cascade will try to interpret them should they match any custom handler functions that are able to use them. (see [Extra Parameters](#user-content-extra-parameters-other-than-constructors) section below)\n\n    If class is not provided Cascade will default to `Monolog\\Handler\\StreamHandler`\n\n- **_processors_** - the derived associative array (from the Yaml or JSON) in which each key is the processor identifier holds keys/values to configure your processors.\u003cbr /\u003eThe following key is _reserved_:\n    - `class` (required): classname of the processor you would like to use\n\n- **_loggers_** - the derived array (from the Yaml or JSON) in which each key is the logger identifier may contain only a `handlers` key and/or a `processors` key. You can decide what handler(s) and/or processor(s) you would like your logger to use.\n\n**Note**: If you would like to use objects as parameters for your handlers, you can pass a class name (using the `class` option) with the corresponding arguments just like you would configure your handler. Cascade recursively instantiates and loads those objects as it parses the config file. See [this sample config file](https://github.com/theorchard/monolog-cascade/blob/master/examples/dependency_config.yml).\n\n#### Parameter case\nYou can use either _underscored_ or _camelCased_ style in your config files, it does not matter. However, it is important that they match the names of the arguments from the constructor method.\n\n```php\npublic function __construct($level = Logger::ERROR, $bubble = true, $appName = null)\n```\n\nUsing a Yaml file:\n```yaml\n    level: ERROR,\n    bubble: true,\n    app_name: \"some app that I wrote\"\n```\n\nCascade will _camelCase_ all the names of your parameters internally prior to be passed to the constructors.\n\n#### Optional keys\n`formatters`, `handlers` and `processors` keys are optional. If ommitted Cascade will default to Monolog's default formatter and handler: `Monolog\\Formatter\\LineFormatter` and `Monolog\\Handler\\StreamHandler` to `stderr`. If `processors` is ommitted, your logger(s) won't use any.\n\n#### Default parameters\nIf a constructor method provides default value(s) in their declaration, Cascade will look it up and identify those parameters as optional with their default values. It can therefore be ommitted in your config file.\n\n#### Order of sections and params\nOrder of the sections within the config file has no impact as long as they are formatted properly.\n\u003cbr /\u003eOrder of parameters does not matter either.\n\n#### Extra parameters (other than constructor's)\nYou may want to have your Formatters and/or Handlers consume values other than via the constructor. Some methods may be called to do additional set up when configuring your loggers. Cascade interprets those extra params 3 different ways and will try do so in that order:\n\n1. _Instance method_\n    \u003cbr /\u003eYour Formatter or Handler has a defined method that takes a param as input. In that case you can write it as follow in your config file:\n\n    ```yaml\n    formatters:\n      spaced:\n          class: Monolog\\Formatter\\LineFormatter\n          format: \"%datetime% %channel%.%level_name%  %message%\\n\"\n          include_stacktraces: true\n    ```\n    In this example, the `LineFormatter` class has an `includeStacktraces` method that takes a boolean. This method will be called upon instantiation.\u003cbr /\u003e\n\n2. _Public member_\n    \u003cbr /\u003eYour Formatter or Handler has a public member that can be set.\n\n    ```yaml\n    formatters:\n        spaced:\n            class: Monolog\\Formatter\\SomeFormatter\n            some_public_member: \"some value\"\n    ```\n    In this example, the public member will be set to the passed in value upon instantiation.\u003cbr /\u003e\n\n3. _Custom handler function_\n    \u003cbr /\u003eSee `FormatterLoader::initExtraOptionsHandlers` and `HandlerLoader::initExtraOptionsHandlers`. Those methods hold closures that can call instance methods if needed. The closure takes the instance and the parameter value as input.\n\n    ```php\n    self::$extraOptionHandlers = array(\n        'Monolog\\Formatter\\LineFormatter' =\u003e array(\n            'includeStacktraces' =\u003e function ($instance, $include) {\n                $instance-\u003eincludeStacktraces($include);\n            }\n        )\n    );\n    ```\n    You can add handlers at runtime if needed. (i.e. if you write your logger handler for instance)\n\nRunning Tests\n-------------\n\nJust run Phpunit:\n```sh\n$ phpunit tests/\n```\n\nContributing\n------------\n\nThis extension is open source. Feel free to contribute and send a pull request!\n\nMake sure your code follows the [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) standards, is documented and has unit tests.\n\n\nWhat's next?\n------------\n - add support for `.ini` config files\n - add support for namespaced Loggers with message propagation (through handler inheritance) so children loggers log messages using parent's handlers\n - add more custom function handlers to cover all the possible options of the current Monolog Formatters and Handlers\n - ~~add support for Processors (DONE)~~\n - ~~add support for DB/Store and other handlers requiring injection into the constructor ([issue #30](https://github.com/theorchard/monolog-cascade/issues/30)) (DONE)~~\n - other suggestions?\n\n\nSymfony Users\n-------------\nYou may want to use [MonologBundle](https://github.com/symfony/MonologBundle) as it integrates directly with your favorite framework.\n\n\nUnder The Hood\n--------------\nHere is a [Medium post](https://medium.com/orchard-technology/enhancing-monolog-699efff1051d#.dw6qu1c2p) if you want to know more about the implementation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheorchard%2Fmonolog-cascade","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheorchard%2Fmonolog-cascade","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheorchard%2Fmonolog-cascade/lists"}