Change filename on custom monolog file - php

I use a rotating monolog handler
monolog:
channels: ['import']
handlers:
import_client:
level: debug
type: rotating_file
max_files: 10
path: '%kernel.logs_dir%/import.log'
channels: [import_client]
All works fine except I don't like the filename. I get import-2018-02-22.log.
Does it exist a way to change this format?
I would like the filename to be like import-"date(YmdHis)".log.
Is possible to rewrite the filename format? Did you have any solutions ?

I found the solution, need to add in config handler a new parameter :
date_format: 'YmdHms'

The RotatingFileHandler Logs records to a file and creates one logfile per day. It will also delete files older than $maxFiles. You should use logrotate for high profile setups though, this is just meant as a quick and dirty solution.
As you can see in the original RotatingFileHandler: you could possibly change the rotate dateformat
public function setFilenameFormat($filenameFormat, $dateFormat)
But I don't see any configuration option in the symfony monolog reference.
You could call a service using
services:
app.custom_rotating_service:
# ...
calls:
- method: setFilenameFormat
arguments:
- 'yourFilenameFormat'
- 'Ymd'
It seems to me you would get into soemthing complex for no added value of a date format.
TLDR
It's not possible to have a logfile By Hour/Minute with monolog
Changing Date format or the rotation frequency to months/year of the handler seems (to me) doable but not supported by the symfony monolog configuration. you could create a service and try to call the method automatically on service isntance creation
You should use logrotate if you have a custom need of rotating log

Related

Is it possible to load Swagger annotations from a different class or file?

I have the following simple PHP method like the following
/**
*
* (swagger annotation to be called from a different class)
*
*/
public function getApiCall()
{
//Do something
}
and I need to include long Swagger documentation into the annotation above the method, so
is it possible to write the annotation in a different class ? and call it here with something like
/**
*
*call('App\Http\Controllers\testAnnotation');
*/
The main purpose is to have a clean class without so many lines of documentation and annotations in it.
Loading "annotations from a different class" is not something that makes a lot of sense. Annotations are read in the annotated code, that's their whole purpose.
But if you want to keep configuration and code separated, you do not have to use Swagger-Php to generate your swagger configuration file.
The package is simply a convenience way to generate the swagger.json file from code annotations.
But if you do not want to use annotations in the first place, and keep your classes clean from extraneous configuration (something that I personally applaud), just... do not use Swagger-Php and build your own configuration files outside of your classes.
You could even write it in YAML, if you feel more comfortable than writing JSON by hand. For example::
openapi: 3.0.0
info:
title: 'Search API'
version: 1.0.0
servers:
- url:
description: Current host server
- url: https:your-server.com
description: Prod server
paths:
/foo:
post:
summary: 'Creates a new foo'
description: 'Builds a new Foo and makes it available to Bar'
requestBody:
description: 'Foo '
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Foo'
responses:
'201':
description: Foo created
'202':
description: Foo queued, it will be eventually created.
components:
schemas:
Foo:
type: object
required:
- name
- size
properties:
name:
type: string
size:
type: integer
This, once converted to JSON (there are many libraries to do this, or you could even use a free service like this one), you can feed the resulting JSON to swagger directly.
E.g. the YAML above parses to this JSON file. You can easily test it out by heading to the Swagger demo instance, and past the JSON URL in the "explore" location bar, and you'll get something like this:
In the end, it's not much more work than using annotations (if any more work at all), and you can keep your entity classes clean from configuration concerns.

How can I output the date with ConsoleLogger?

I have a console command and I'm initializing ConsoleLogger in the initialize method:
$this->logger = new ConsoleLogger($output);
But the date is not outputted in the console. Is it possible to prefix the output with the datetime?
I know this is an old topic, but it's the first result when you google for "symfony console log date", that's why I'd like to share what I found when trying to solve this.
According to the Symfony docs, you can specify a custom formatter (found in old Symfony 2.6 docs)
https://symfony.com/doc/2.6//cookbook/logging/monolog_console.html
# app/config/services.yml
services:
my_formatter:
class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
arguments:
# NOTE
# The placeholder to use in the `format` is enclosed in single `%` (ex.: `%datetime%`)
# However, here we escape `%` characters so Symfony will not interpret them as service parameters.
# https://symfony.com/doc/current/configuration.html#configuration-parameters
- "[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n"
But that's not doing the trick already.
Taking a look at the source of ConsoleFormatter, I found this:
const SIMPLE_FORMAT = "%datetime% %start_tag%%level_name%%end_tag% <comment>[%channel%]</> %message%%context%%extra%\n";
const SIMPLE_DATE = 'H:i:s';
So there date is set as H:i:s here.
Luckily this date can be overwritten with the date_format option.
This is how I solved it now:
In my monolog.yaml I added the formatter
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
verbosity_levels:
VERBOSITY_NORMAL: DEBUG
formatter: console_log_formatter
And in services.yml I added the custom formatter with my date_format set
console_log_formatter:
class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
arguments:
- date_format: 'Y-m-d H:i:s'
maybe you need to define the verbosity level
$this->consoleLogger = new ConsoleLogger($output, [LogLevel::INFO => OutputInterface::VERBOSITY_NORMAL]);
Hope this is what you are looking for

Symfony 2 - how to parse %parameter% in my own Yaml file loader?

I have a Yaml loader that loads additional config items for a "profile" (where one application can use different profiles, e.g. for different local editions of the same site).
My loader is very simple:
# YamlProfileLoader.php
use Symfony\Component\Config\Loader\FileLoader;
use Symfony\Component\Yaml\Yaml;
class YamlProfileLoader extends FileLoader
{
public function load($resource, $type = null)
{
$configValues = Yaml::parse($resource);
return $configValues;
}
public function supports($resource, $type = null)
{
return is_string($resource) && 'yml' === pathinfo(
$resource,
PATHINFO_EXTENSION
);
}
}
The loader is used more or less like this (simplified a bit, because there is caching too):
$loaderResolver = new LoaderResolver(array(new YamlProfileLoader($locator)));
$delegatingLoader = new DelegatingLoader($loaderResolver);
foreach ($yamlProfileFiles as $yamlProfileFile) {
$profileName = basename($yamlProfileFile, '.yml');
$profiles[$profileName] = $delegatingLoader->load($yamlProfileFile);
}
So is the Yaml file it's parsing:
# profiles/germany.yml
locale: de_DE
hostname: %profiles.germany.host_name%
At the moment, the resulting array contains literally '%profiles.germany.host_name%' for the 'hostname' array key.
So, how can I parse the % parameters to get the actual parameter values?
I've been trawling through the Symfony 2 code and docs (and this SO question and can't find where this is done within the framework itself. I could probably write my own parameter parser - get the parameters from the kernel, search for the %foo% strings and look-up/replace... but if there's a component ready to be used, I prefer to use this.
To give a bit more background, why I can't just include it into the main config.yml: I want to be able to load app/config/profiles/*.yml, where * is the profile name, and I am using my own Loader to accomplish this. If there's a way to wildcard import config files, then that might also work for me.
Note: currently using 2.4 but just about ready to upgrade to 2.5 if that helps.
I've been trawling through the Symfony 2 code and docs (and this SO question and can't find where this is done within the framework itself.
Symfony's dependency injection component uses a compiler pass to resolve parameter references during the optimisation phase.
The Compiler gets the registered compiler passes from its PassConfig instance. This class configures a few compiler passes by default, which includes the ResolveParameterPlaceHoldersPass.
During container compilation, the ResolveParameterPlaceHoldersPass uses the Container's ParameterBag to resolve strings containing %parameters%. The compiler pass then sets that resolved value back into the container.
So, how can I parse the % parameters to get the actual parameter values?
You'd need access to the container in your ProfileLoader (or wherever you see fit). Using the container, you can recursively iterate over your parsed yaml config and pass values to the container's parameter bag to be resolved via the resolveValue() method.
Seems to me like perhaps a cleaner approach would be for you to implement this in your bundle configuration. That way your config will be validated against a defined structure, which can catch configuration errors early. See the docs on bundle configuration for more information (that link is for v2.7, but hopefully will apply to your version also).
I realise this is an old question, but I have spent quite a while figuring this out for my own projects, so I'm posting the answer here for future reference.
I tried a lot of options to resolve %parameter% to parameters.yml but no luck at all. All I can think of is parsing %parameter% and fetch it from container, no innovation yet.
On the other hand I don't have enough information about your environment to see the big picture but I just come up with another idea. It can be quite handy if you declare your profiles in your parameters.yml file and load it as an array in your controller or service via container.
app/config/parameters.yml
parameters:
profiles:
germany:
locale: de_DE
host_name: http://de.example.com
uk:
locale: en_EN
host_name: http://uk.example.com
turkey:
locale: tr_TR
host_name: http://tr.example.com
You can have all your profiles as an array in your controller.
<?php
namespace Acme\DemoBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class DefaultController extends Controller
{
public function indexAction()
{
$profiles = $this->container->getParameter('profiles');
var_dump($profiles);
return $this->render('AcmeDemoBundle:Default:index.html.twig');
}
}
With this approach
you don't have to code a custom YamlLoader
you don't have to worry about importing parameters into other yml files
you can have your profiles as an array anytime you have the $container in your hand
you don't have to load/cache profile files one by one
you don't have to find a wildcard file loading solution
If I got your question correctly, this approach can help you.

What is the preferred/best way to store parameters in an external config file?

I completed a project in Symfony2 and am now improving/refactoring it. One small task is to put some parameters/credentials in an external config file.
I know that I can import that file by using:
# app/config/config.yml
imports:
- { resource: parameters.php }
or:
// app/config/config.php
$loader->import('parameters.php');
But I want to know the difference/benefits of using yml, xml or php as an external file. Is one of them ' safer' or 'better' then the other perhaps?
In practice there's no difference, this is rather question what you are used to.
In my opinion parameters.yml is just key-value stuff so yml is just perfect for this.
Yml is probably most clear but maybe not most fluent.
Check this question for more general differences between various formats.

Symfony2 - Monolog - Level up or down customized logger

Using Symfon2 and its Monolog framework to for logging, I am having some trouble.
On the one hand, I have a service configured with my own logger. It is working properly and I get to "info" and "err" messages without problems.
services:
my_logger:
class: Monolog\Logger
arguments: [my_info]
calls:
- [pushHandler, [#my_log_handler]]
my_log_handler:
class: Monolog\Handler\StreamHandler
arguments: [%kernel.root_dir%/logs/my_info.log, 100]
Using the following in the controller causes proper messages to be written
$this->get('my_logger')->info('info message');
$this->get('my_logger')->err('error message');
Here comes my question
Once I have placed planty of those ->err and ->info logging messages, how I tell the configuration to just write those written through the err method?
At the beginning may be I need many information, and for that reason I would write many info messages. But in a while, I may prefer to level up the logging messages through setting the action level to warning or error, avoiding the info logs to be written.
Any idea?
You just need to tweak the level at which your handler is listening. In this case it means changing the 100 to something higher like 400 for errors. So that gives you:
my_log_handler:
class: Monolog\Handler\StreamHandler
arguments: [%kernel.root_dir%/logs/my_info.log, 400]

Categories