How to add simple processing in symfony config - php

I am trying to create a simple processing code to Symfony configuration.
Here is the final effect I want to do (config pseudocode):
# config/packages/monolog.yml
monolog:
handlers:
debug_log:
type: '%env(LOGS_ROTATE) > 0 ? "rotating_file" : "stream"%'
max_files: '%env(LOGS_ROTATE) ?? null%'
...
The idea is that if LOGS_ROTATE env is set to a positive number,
type should be rotating_file and max_files should be that number,
otherwise type should be stream and max_files should be skipped
Is it possible to do that?
I was considering using env processors, but those cannot take any parameters,
and using hardcoding config values inside such a processor feels bad.
edit:
I also tried to use symfony expression language, but got an error:
There is no handler class defined for handler "#=%env(logs_rotate) > 0 ? rotating_file : stream".
monolog:
handlers:
debug_log:
type: "#=%env(LOGS_ROTATE) > 0 ? rotating_file : stream"

Related

Workflow in Symfony doesn't work with "multiple_state"

In one of the configuration files of Symfony 5.2.8 with Workflow 5.2.7 I have:
framework:
workflows:
register_participation:
type: 'workflow' # or 'state_machine'
audit_trail:
enabled: true
marking_store:
type: 'multiple_state'
arguments:
- complexState
# [...]
When I execute bin/console I have error:
Unrecognized option "arguments" under framework.workflows.workflows.register_participation.marking_store". Available options are "property", "service", "type".
When I change the configuration to:
framework:
workflows:
register_participation:
type: 'workflow' # or 'state_machine'
audit_trail:
enabled: true
marking_store:
type: 'multiple_state'
property: state
# [...]
I get the error:
The value "multiple_state" is not allowed for path framework.workflows.workflows.register_participation.marking_store.type". Permissible values: "method"
It works when I change to this:
marking_store:
type: 'method'
property: main_state
Anybody have idea what can I do to works with multiple_state? Thanks in advance.
From the symfony workflow documentation:
The marking store type could be “multiple_state” or “single_state”. A
single state marking store does not support a model being on multiple
places at the same time. This means a “workflow” must use a
“multiple_state” marking store and a “state_machine” must use a
“single_state” marking store. Symfony configures the marking store
according to the “type” by default, so it’s preferable to not
configure it.
A single state marking store uses a string to store the data. A
multiple state marking store uses an array to store the data.
So if you configure type "workflow" it should automatically be "multiple_state". You could dump your entity and the state property should be of type array

Remove yaml property and its definition from yaml files in a directory using php or bash

I have many yaml files that have a property definition on multiple lines:
approval_date:
label: inline
type: datetime_plain
weight: 3
region: content
settings:
timezone_override: ''
third_party_settings: { }
I would like to be able to remove the approval_date and its definition from all yaml files. I tried a simple regex search and replace and it work to an extent but the definition varies across different files. Is there a simpler way to remove the property and its definition wherever it using bash script or something similar?
I don't know PHP, but here's a ruby one-liner: read the yaml file into a hash, delete the requested hash key, and emit the new yaml
$ cat file.yaml
some stuff:
- a
- b
- c
approval_date:
label: inline
type: datetime_plain
weight: 3
region: content
settings:
timezone_override: ''
third_party_settings: { }
more stuff: here
$ ruby -e '
require "yaml"
data = YAML.load(File.read(ARGV.shift))
data.delete("approval_date")
puts YAML.dump(data)
' file.yaml
---
some stuff:
- a
- b
- c
more stuff: here
Bash by itself will not handle yaml, and I haven't had success with any of the various libraries that are supposed to add half-hearted support for it.
I have, however, had success treating yaml as JSON using y2j, which allows your yaml to be parsed using the language of jq.
Witness:
$ cat x.yml
keep_me: foo
approval_date:
label: inline
type: datetime_plain
weight: 3
region: content
settings:
timezone_override: ''
third_party_settings: { }
more_to_keep:
label: bar
$ yq 'del(.approval_date)' < x.yml
keep_me: foo
more_to_keep:
label: bar
Note that the yq command is a link to y2j.sh, which is a bash script. The jq command can probably be added to your system using the normal package manager for your operating system.
Of course, doing this in PHP alone may be easier.
$ php -r '$a=yaml_parse_file("x.yml"); unset($a["approval_date"]); print_r($a);'
Array
(
[keep_me] => foo
[more_to_keep] => Array
(
[label] => bar
)
)
Or even:
$ php -r '$a=yaml_parse_file("x.yml"); unset($a["approval_date"]); print yaml_emit($a);'
---
keep_me: foo
more_to_keep:
label: bar
...

Change filename on custom monolog file

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

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

How to disable output for a command in Symfony Console?

I writing a module, actually a custom command in Magento 2. Magento 2 console application is proudly powered by Symfony Console, obviously. And my concernation is how to disable output from $output for specified command?
For example:
$setupUpgradeCommand = $this->getApplication()->find('setup:upgrade');
$setupUpgradeArguments = array(
'command' => 'setup:upgrade',
'--quiet' => true,
);
$setupUpgradeInput = new ArrayInput($setupUpgradeArguments);
$start = microtime(true);
$output->writeln('<info>Start upgrading module schemas...</info>');
$setupUpgradeCommand->run($setupUpgradeInput, $output);
$output->writeln('...............................<info>OK</info>');
// My long logic-code start from here....
Unfortunately, even I set --quiet to true, output of this command setup:upgrade still there.
Any ideas?
As answered in a comment.. although almost exactly the same as the answer by #toooni.
You can insert the NullOutput rather than inserting the actual output object supplied by the command.
use Symfony\Component\Console\Output\NullOutput;
$setupUpgradeCommand->run($setupUpgradeInput, new NullOutput());
You can use BufferedOutput:
use Symfony\Component\Console\Output\BufferedOutput;
...
$setupUpgradeCommand->run($setupUpgradeInput, new BufferedOutput());
The usage is described here:
http://symfony.com/doc/current/cookbook/console/command_in_controller.html
Another option would be to use the logger and have this spewed on your CLI if you ask for it. You can read more about it in this (by now old) news post: http://symfony.com/blog/new-in-symfony-2-4-show-logs-in-console
A full example where you can even format the output taken from the post:
services:
my_formatter:
class: Symfony\Bridge\Monolog\Formatter\ConsoleFormatter
arguments:
- "[%%datetime%%] %%start_tag%%%%message%%%%end_tag%% (%%level_name%%) %%context%% %%extra%%\n"
monolog:
handlers:
console:
type: console
verbosity_levels:
VERBOSITY_NORMAL: NOTICE
channels: my_channel
formatter: my_formatter
You can find the documentation here: http://symfony.com/doc/current/cookbook/logging/monolog.html

Categories