Added logging.

This commit is contained in:
Jens True 2023-05-31 14:34:35 +00:00
parent 7a6e71dc6c
commit 4057581b94
10 changed files with 95 additions and 22 deletions

2
.gitignore vendored

@ -1,3 +1,5 @@
/vendor/
/output/
/temp/
config.yml
composer.phar

@ -9,3 +9,6 @@ install:
php composer.phar install --no-dev
install-dev:
php composer.phar install
test:
./vendor/bin/phpunit tests --testdox --coverage-filter src --coverage-html output/coverage

4
backup

@ -21,9 +21,11 @@ if (! $autoload) {
}
require $autoload;
use Symfony\Component\Console\Application;
use Composer\InstalledVersions;
$package = \Composer\InstalledVersions::getRootPackage();
use Symfony\Component\Console\Application;
$application = new Application('backup', $package['version']);

@ -1,12 +1,14 @@
notification:
domain: ntfy.jcktrue.dk
topic: backup
logging:
stream: output.log
rclone:
bwlimit: 6M
backup:
- title: Example
source: test/src
destination: test/dest
source: temp/source
destination: temp/destination
templates:
notify: |
{{ config.title }}

11
output.log Normal file

@ -0,0 +1,11 @@
[2023-05-31T14:30:00.890085+00:00] app.INFO: Initialization complete [] []
[2023-05-31T14:30:00.946882+00:00] rclone.INFO: Execute command ["'rclone' 'size' '--json' 'temp/source'"] []
[2023-05-31T14:30:00.989664+00:00] rclone.INFO: Return code [0] []
[2023-05-31T14:30:00.989960+00:00] rclone.INFO: Execute command ["'rclone' 'size' '--json' 'temp/destination'"] []
[2023-05-31T14:30:01.047504+00:00] rclone.INFO: Return code [0] []
[2023-05-31T14:30:01.047810+00:00] rclone.INFO: Execute command ["'rclone' 'copy' 'temp/source' 'temp/destination' '--bwlimit' '6M'"] []
[2023-05-31T14:30:01.097485+00:00] rclone.INFO: Return code [0] []
[2023-05-31T14:30:01.097797+00:00] rclone.INFO: Execute command ["'rclone' 'size' '--json' 'temp/destination'"] []
[2023-05-31T14:30:01.142119+00:00] rclone.INFO: Return code [0] []
[2023-05-31T14:30:01.174134+00:00] notification.DEBUG: Sending ntfy notification {"topic":"backup","title":"Example","message":"Example\nFrom temp/source to temp/destination\nBackup started: May 31, 2023 14:30\nSource size: 8.00B\nDestination before: 8.00B\nDestination after: 8.00B\nDestination change : 0.00B\nBackup completed: May 31, 2023 14:30\n"} []
[2023-05-31T14:30:01.363282+00:00] notification.DEBUG: Result of ntfy notification ["{\"id\":\"iHfqUGi4dUsC\",\"time\":1685543401,\"expires\":1685586601,\"event\":\"message\",\"topic\":\"backup\",\"title\":\"Example\",\"message\":\"Example\\nFrom temp/source to temp/destination\\nBackup started: May 31, 2023 14:30\\nSource size: 8.00B\\nDestination before: 8.00B\\nDestination after: 8.00B\\nDestination change : 0.00B\\nBackup completed: May 31, 2023 14:30\"}\n"] []

36
src/App.php Normal file

@ -0,0 +1,36 @@
<?php
namespace App;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Exception\ParseException;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
class App {
protected Logger $logger;
protected array $config;
function __construct(string $configFile)
{
$this->config = Yaml::parseFile($configFile);
$logger = new Logger('app');
$logger->pushHandler(new StreamHandler($this->getConfig()['logging']['stream']));
$logger->info("Initialization complete");
$this->logger = $logger;
}
function getConfig() : array
{
return $this->config;
}
function getLogger() : Logger
{
return $this->logger;
}
}

@ -6,8 +6,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Yaml\Yaml;
use Symfony\Component\Yaml\Exception\ParseException;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
@ -30,22 +29,27 @@ class CommandBackup extends Command
$io->title('Start backup process');
$io->info('Opening: '.$input->getArgument('config'));
try {
$config = Yaml::parseFile($input->getArgument('config'));
} catch (ParseException $e) {
$app = new App($input->getArgument('config'));
}
catch (\Throwable $e) {
$io->error('Unable to parse the YAML string: '. $e->getMessage());
return Command::FAILURE;
}
$rclone = new Rclone\Rclone();
$io->info("Rclone version: ". $rclone->getVersion());
$ntfy = new Ntfy\Ntfy($config['notification']['domain']);
$loader = new ArrayLoader($config['templates']);
$rclone = new Rclone\Rclone();
$rclone->setLogger($app->getLogger()->withName('rclone'));
$ntfy = new Ntfy\Ntfy($app->getConfig()['notification']['domain']);
$ntfy->setLogger( $app->getLogger()->withName('notification'));
$loader = new ArrayLoader($app->getConfig()['templates']);
$twig = new Environment($loader);
$twig->addExtension(new Twig\AppExtension());
foreach($io->progressIterate( $config['backup']) as $conf) {
foreach ($io->progressIterate($app->getConfig()['backup']) as $conf) {
try {
$template = array();
$template['config'] = $conf;
@ -63,7 +67,7 @@ class CommandBackup extends Command
} catch (\Throwable $e) {
$message = $e->getMessage();
}
$ntfy->send($config['notification']['topic'], $conf['title'], $message);
$ntfy->send($app->getConfig()['notification']['topic'], $conf['title'], $message);
}
$io->success("Complete");

@ -25,15 +25,15 @@ class CommandShow extends Command
$io = new SymfonyStyle($input, $output);
$io->title('List backup entities');
$io->note('Reading from: '.$input->getArgument('config'));
try {
$config = Yaml::parseFile($input->getArgument('config'));
} catch (ParseException $e) {
$app = new App($input->getArgument('config'));
}
catch (\Throwable $e) {
$io->error('Unable to parse the YAML string: '. $e->getMessage());
return Command::FAILURE;
}
$io->table(['Description', 'Source', 'Destination'], $config['backup']);
$io->table(['Description', 'Source', 'Destination'], $app->getConfig()['backup']);
$io->success("Done");
return Command::SUCCESS;

@ -1,8 +1,11 @@
<?php
namespace App\Ntfy;
use Psr\Log\LoggerAwareTrait;
class Ntfy
{
use LoggerAwareTrait;
protected string $domain;
function __construct(string $domain)
{
@ -11,7 +14,8 @@ class Ntfy
function send(string $topic, string $title, string $message): void
{
file_get_contents(
$this->logger->debug("Sending ntfy notification", ["topic"=>$topic, "title"=>$title, "message"=>$message]);
$result = file_get_contents(
'https://'.$this->domain.'/'.$topic, false, stream_context_create(
['http' => [
'method' => 'POST',
@ -22,6 +26,7 @@ class Ntfy
]
)
);
$this->logger->debug("Result of ntfy notification", [$result]);
}
}

@ -1,13 +1,19 @@
<?php
namespace App\Rclone;
use Psr\Log\LoggerAwareTrait;
use Psr\Log\NullLogger;
use Symfony\Component\Process\Process;
use Symfony\Component\Process\Exception\ProcessFailedException;
use Exception;
class Rclone
{
use LoggerAwareTrait;
protected string $rclonePath;
/**
* Global options
@ -21,6 +27,7 @@ class Rclone
function __construct(string $rclonePath = "rclone")
{
$this->rclonePath = $rclonePath;
$this->setLogger(new NullLogger);
try
{
$version = $this->exec('--version');
@ -28,7 +35,6 @@ class Rclone
catch(ProcessFailedException $e)
{
throw new Exception("Check installation of rclone");
return;
}
$this->version = explode("\n", $version)[0];
@ -77,14 +83,16 @@ class Rclone
$options
)
);
$this->logger->info("Execute command", [$process->getCommandLine()]);
$process->setTimeout(4*3600);
$process->run();
// executes after the command finishes
if (!$process->isSuccessful()) {
$this->logger->error("Failed execution");
throw new ProcessFailedException($process);
}
$this->logger->info("Return code", [$process->getExitCode()]);
return $process->getOutput();
}
}