Skip to content

Commit 9d1a0eb

Browse files
committed
Add monitoring functionality to display code generation steps and progress
1 parent 6a7e286 commit 9d1a0eb

15 files changed

+335
-31
lines changed

CHANGELOG.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file, in reverse
66

77
### Added
88

9-
* Nothing
9+
* Monitoring functionality to display code generation steps and progress.
1010

1111
### Deprecated
1212

composer.json

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
},
2727
"require": {
2828
"php": "^7.3 || ^8.0",
29+
"psr/log": "^1.1",
2930
"symfony/console": "^4.4 || ^5.0 "
3031
},
3132
"require-dev": {

docs/book/02-configuration.md

+38-15
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,54 @@
11
# Configuration
22

3-
The code generator CLI can be started through the `bin/ocmcg` executable. This prints the available CLI commands.
4-
The CLI command `ocmcg:workflow:run` executes the code generation depending on the configuration file. The default
3+
The code generator is shipped with a CLI which executes the code generation depending on the configuration file. The default
54
configuration file name is `open-code-modeling.php.dist` which should be located in the root folder of the application
65
/ repository.
76

87
This file gets the variable `$workflowContext` provided to configure needed slot data for the code generation e. g.
98
paths or global data. You have to return an instance of a class which implements `OpenCodeModeling\CodeGenerator\Config\Config`
109
interface.
1110

12-
The following example add some slot data to the workflow context (`$workflowContext->put()`).
11+
The following code shows a "Hello World!" example. It prepares the `WorkflowContext` object with the first part of the
12+
greeting under slot name `part_one`. The workflow consists of two steps. Step *one* adds the second part of the greeting
13+
to the given input from slot name `part_one`. The returned value is stored under the slot name `greeting`. Step *two*
14+
prints the string of the input slot name `greeting`. It doesn't has an output slot name.
15+
1316
```
17+
use OpenCodeModeling\CodeGenerator;
18+
1419
/** @var CodeGenerator\Workflow\WorkflowContext $workflowContext */
15-
$workflowContext->put('xml_filename', 'data/domain.xml');
16-
17-
$config = new CodeGenerator\Config\ComponentList(
18-
...[
19-
new CodeGenerator\Config\ComponentConfig(
20-
CodeGenerator\Transformator\StringToFile::workflowComponentDescription(
21-
Inspectio\WorkflowConfigFactory::SLOT_GRAPHML_XML,
22-
'xml_filename'
23-
)
20+
$workflowContext->put('part_one', 'Hello'); // init some data so it's available as an input slot name
21+
22+
$config = new CodeGenerator\Config\Workflow(
23+
// step one
24+
new CodeGenerator\Workflow\ComponentDescriptionWithSlot(
25+
function(string $inputHello) {
26+
return $inputHello . ' World!';
27+
},
28+
'greeting', // output slot name
29+
'part_one' // input slot name
30+
),
31+
// step two
32+
new CodeGenerator\Workflow\ComponentDescriptionWithInputSlotOnly(
33+
function(string $greeting) {
34+
echo $greeting;
35+
},
36+
'greeting', // input slot name
2437
),
25-
]
2638
);
2739
28-
$config->addConsoleCommands(new Inspectio\Console\XmlGenerateAllCommand());
29-
3040
return $config;
3141
```
42+
43+
## Register additional Symfony CLI commands
44+
45+
It is possible to add additional CLI commands to the code generator CLI. You can register additional Symfony CLI commands
46+
by adding them to the `$config` object via `$config->addConsoleCommands(new AwesomeCliCommand())`.
47+
48+
## Register a monitor
49+
50+
A monitor can be used to display code generation steps and progress.
51+
52+
You can register a monitor instance of type `\OpenCodeModeling\CodeGenerator\Workflow\Monitoring\Monitoring` to the
53+
`$config` object via `$config->setMonitor(new AwesomeMonitor())`. The Code Generator is shipped with a `Psr\Log\LoggerInterface`
54+
monitor (`\OpenCodeModeling\CodeGenerator\Workflow\Monitoring\LoggerMonitor`).

docs/book/03-cli.md

+29-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
11
# Code Generator CLI
22

3-
TODO CLI call example
3+
The code generator CLI can be started through the `bin/ocmcg` executable. This prints the registered CLI commands from
4+
workflows, and the default available CLI commands. The CLI command `ocmcg:workflow:run` executes the code generation
5+
depending on the configuration file. You can use the CLI option `-c` to specify a specific configuration file.
6+
7+
```
8+
===========================================
9+
Open Code Modeling - PHP Code Generator CLI
10+
===========================================
11+
12+
13+
Usage:
14+
command [options] [arguments]
15+
16+
Options:
17+
-h, --help Display this help message
18+
-q, --quiet Do not output any message
19+
-V, --version Display this application version
20+
--ansi Force ANSI output
21+
--no-ansi Disable ANSI output
22+
-n, --no-interaction Do not ask any interactive question
23+
-c, --config=CONFIG Configuration file
24+
-v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
25+
26+
Available commands:
27+
help Displays help for a command
28+
list Lists commands
29+
ocmcg
30+
ocmcg:workflow:run Executes workflow from configuration file to generate code
31+
```

src/Config/Config.php

+8
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace OpenCodeModeling\CodeGenerator\Config;
1212

13+
use OpenCodeModeling\CodeGenerator\Workflow\Monitoring\Monitoring;
1314
use Symfony\Component\Console\Command\Command;
1415

1516
/**
@@ -23,4 +24,11 @@ interface Config
2324
* @return Command[]
2425
*/
2526
public function consoleCommands(): iterable;
27+
28+
/**
29+
* Monitoring instance for the workflow engine
30+
*
31+
* @return Monitoring|null
32+
*/
33+
public function monitor(): ?Monitoring;
2634
}

src/Config/Workflow.php

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace OpenCodeModeling\CodeGenerator\Config;
1212

1313
use OpenCodeModeling\CodeGenerator\Workflow\Description;
14+
use OpenCodeModeling\CodeGenerator\Workflow\Monitoring\Monitoring;
1415
use Symfony\Component\Console\Command\Command;
1516

1617
/**
@@ -28,6 +29,11 @@ final class Workflow implements WorkflowConfig
2829
**/
2930
private $consoleCommands = [];
3031

32+
/**
33+
* @var Monitoring|null
34+
*/
35+
private $monitor;
36+
3137
public function __construct(Description ...$config)
3238
{
3339
$this->config = $config;
@@ -54,4 +60,14 @@ public function addConsoleCommands(Command ...$consoleCommands): void
5460
$this->consoleCommands[] = $consoleCommand;
5561
}
5662
}
63+
64+
public function monitor(): ?Monitoring
65+
{
66+
return $this->monitor;
67+
}
68+
69+
public function setMonitor(Monitoring $monitor): void
70+
{
71+
$this->monitor = $monitor;
72+
}
5773
}

src/Config/WorkflowList.php

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace OpenCodeModeling\CodeGenerator\Config;
1212

13+
use OpenCodeModeling\CodeGenerator\Workflow\Monitoring\Monitoring;
1314
use Symfony\Component\Console\Command\Command;
1415

1516
/**
@@ -29,6 +30,11 @@ final class WorkflowList implements WorkflowCollection
2930
**/
3031
private $consoleCommands = [];
3132

33+
/**
34+
* @var Monitoring|null
35+
*/
36+
private $monitor;
37+
3238
public function __construct(WorkflowConfig ...$components)
3339
{
3440
$this->components = $components;
@@ -77,4 +83,14 @@ public function addConsoleCommands(Command ...$consoleCommands): void
7783
$this->consoleCommands[] = $consoleCommand;
7884
}
7985
}
86+
87+
public function monitor(): ?Monitoring
88+
{
89+
return $this->monitor;
90+
}
91+
92+
public function setMonitor(Monitoring $monitor): void
93+
{
94+
$this->monitor = $monitor;
95+
}
8096
}

src/Console/WorkflowCommand.php

+12-6
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@
1111
namespace OpenCodeModeling\CodeGenerator\Console;
1212

1313
use OpenCodeModeling\CodeGenerator\Config;
14-
use OpenCodeModeling\CodeGenerator\Config\WorkflowConfig;
1514
use OpenCodeModeling\CodeGenerator\Console;
1615
use OpenCodeModeling\CodeGenerator\Exception\RuntimeException;
16+
use OpenCodeModeling\CodeGenerator\Workflow\Monitoring\Monitoring;
17+
use OpenCodeModeling\CodeGenerator\Workflow\Monitoring\NullMonitor;
1718
use OpenCodeModeling\CodeGenerator\Workflow\WorkflowContext;
1819
use OpenCodeModeling\CodeGenerator\Workflow\WorkflowEngine;
1920
use Symfony\Component\Console\Command\Command;
@@ -39,11 +40,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int
3940

4041
$config = $this->loadConfig($workflowContext);
4142

43+
$monitor = $config->monitor();
44+
4245
if ($config instanceof Config\WorkflowConfig) {
43-
$this->executeWorkflow($config, $workflowContext);
46+
$this->executeWorkflow($config, $workflowContext, $monitor);
4447
} elseif ($config instanceof Config\WorkflowCollection) {
4548
foreach ($config as $workflowConfig) {
46-
$this->executeWorkflow($workflowConfig, $workflowContext);
49+
$this->executeWorkflow($workflowConfig, $workflowContext, $monitor);
4750
}
4851
} else {
4952
throw new RuntimeException(
@@ -62,9 +65,12 @@ private function loadConfig(WorkflowContext $workflowContext): Config\Config
6265
return $this->getHelper(Console\Config::class)->resolver()->resolve($workflowContext);
6366
}
6467

65-
private function executeWorkflow(WorkflowConfig $config, WorkflowContext $workflowContext): void
66-
{
67-
$workflowEngine = new WorkflowEngine();
68+
private function executeWorkflow(
69+
Config\WorkflowConfig $config,
70+
WorkflowContext $workflowContext,
71+
?Monitoring $monitor
72+
): void {
73+
$workflowEngine = new WorkflowEngine($monitor ?: new NullMonitor());
6874
$workflowEngine->run($workflowContext, ...$config->componentDescriptions());
6975
}
7076
}

src/Workflow/Description.php

+7
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,11 @@ interface Description
2222
* @return callable
2323
*/
2424
public function component(): callable;
25+
26+
/**
27+
* A description of the component (purpose, what's generated, transformed, ...)
28+
*
29+
* @return string
30+
*/
31+
public function description(): string;
2532
}

src/Workflow/DescriptionTrait.php

+5
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,9 @@ public function component(): callable
2929
{
3030
return $this->component;
3131
}
32+
33+
public function description(): string
34+
{
35+
return \is_object($this->component) ? \get_class($this->component) : static::class;
36+
}
3237
}
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* @see https://github.com/open-code-modeling/php-code-generator for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-generator/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-generator/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModeling\CodeGenerator\Workflow\Monitoring;
12+
13+
use OpenCodeModeling\CodeGenerator\Workflow\Description;
14+
use OpenCodeModeling\CodeGenerator\Workflow\DescriptionWithInputSlot;
15+
use OpenCodeModeling\CodeGenerator\Workflow\DescriptionWithOutputSlot;
16+
use Psr\Log\LoggerInterface;
17+
18+
final class LoggerMonitor implements Monitoring
19+
{
20+
/**
21+
* @var LoggerInterface
22+
**/
23+
private $logger;
24+
25+
public function __construct(LoggerInterface $logger)
26+
{
27+
$this->logger = $logger;
28+
}
29+
30+
public function start(Description $description): void
31+
{
32+
$this->logger->info('Start: ' . $description->description());
33+
}
34+
35+
public function call(Description $description): void
36+
{
37+
if ($description instanceof DescriptionWithInputSlot) {
38+
$this->logger->info(
39+
\sprintf('|-- Executing with input slots "%s"', \implode('", "', $description->inputSlots())),
40+
);
41+
} else {
42+
$this->logger->info('|-- Executing without input slots');
43+
}
44+
}
45+
46+
public function done(Description $description): void
47+
{
48+
if ($description instanceof DescriptionWithOutputSlot) {
49+
$this->logger->info(\sprintf('|-- Done! Output stored in slot "%s"', $description->outputSlot()));
50+
} else {
51+
$this->logger->info('|-- Done!');
52+
}
53+
}
54+
55+
public function error(Description $description, \Throwable $e): void
56+
{
57+
$this->logger->error(
58+
\sprintf('Error on "%s"! Reason: %s, File: %s, Line: %d',
59+
$description->description(),
60+
$e->getMessage(),
61+
$e->getFile(),
62+
$e->getLine()
63+
),
64+
[
65+
'exception' => $e,
66+
]
67+
);
68+
}
69+
}
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* @see https://github.com/open-code-modeling/php-code-generator for the canonical source repository
5+
* @copyright https://github.com/open-code-modeling/php-code-generator/blob/master/COPYRIGHT.md
6+
* @license https://github.com/open-code-modeling/php-code-generator/blob/master/LICENSE.md MIT License
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace OpenCodeModeling\CodeGenerator\Workflow\Monitoring;
12+
13+
use OpenCodeModeling\CodeGenerator\Workflow\Description;
14+
15+
interface Monitoring
16+
{
17+
public function start(Description $description): void;
18+
19+
public function call(Description $description): void;
20+
21+
public function done(Description $description): void;
22+
23+
public function error(Description $description, \Throwable $e): void;
24+
}

0 commit comments

Comments
 (0)