Skip to content

Commit

Permalink
autoconfiguring
Browse files Browse the repository at this point in the history
delete old logs command
  • Loading branch information
indjeto committed Feb 3, 2024
1 parent d329889 commit e47ac64
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 9 deletions.
101 changes: 101 additions & 0 deletions src/Command/AuditLogDeleteOldLogsCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace DataDog\AuditBundle\Command;

use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ParameterType;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
name: 'audit-logs:delete-old-logs',
description: 'Remove old records from the audit logs',
)]
class AuditLogDeleteOldLogsCommand extends Command
{
public const DEFAULT_RETENTION_PERIOD = 'P3M';

public function __construct(
protected Connection $connection
) {
parent::__construct();
}

#[\Override]
protected function execute(InputInterface $input, OutputInterface $output): int
{
$date = (new \DateTime())->sub(new \DateInterval(self::DEFAULT_RETENTION_PERIOD));
$formattedDate = $date->format('Y-m-d H:i:s');

$output->writeln(sprintf('<info>Delete all records before %s</info>', $formattedDate));

$result = $this->connection->executeQuery(
'SELECT * FROM audit_logs WHERE logged_at < ? ORDER BY logged_at DESC LIMIT 1',
[$formattedDate]
)
->fetchAssociative();

if ($result === false) {
$output->writeln(sprintf('<info>No records to delete</info>'));

return 0;
}

$auditLogStartRecordId = $result['id'];
$auditAssociativeStartRecordId = max($result['source_id'], $result['target_id'], $result['blame_id']);

$count = $this->deleteFromAuditLogs($auditLogStartRecordId);
$output->writeln(sprintf('<info> %s records from audit_logs deleted!</info>', $count));

$count = $this->deleteFromAuditAssociations($auditAssociativeStartRecordId);
$output->writeln(sprintf('<info> %s records from audit_associations deleted!</info>', $count));

return 0;
}

private function deleteFromAuditLogs(int $startRecordId): int
{
$allRecords = 0;
$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS=0');

$sql = 'DELETE LOW_PRIORITY FROM audit_logs WHERE id <= ? ORDER BY id LIMIT 10000';
$stmt = $this->connection->prepare($sql);
$stmt->bindValue(1, $startRecordId, ParameterType::INTEGER);
do {
$startTime = microtime(true);
$deletedRows = $stmt->executeStatement();
$allRecords += $deletedRows;
echo round((microtime(true) - $startTime), 3) . "s ";
sleep(1);
} while ($deletedRows > 0);

$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS=1');

return $allRecords;
}

private function deleteFromAuditAssociations(int $startRecordId): int
{
$allRecords = 0;
$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS=0');

$sql = 'DELETE LOW_PRIORITY FROM mscm.audit_associations WHERE id <= ? ORDER BY id LIMIT 10000';
$stmt = $this->connection->prepare($sql);
$stmt->bindValue(1, $startRecordId, ParameterType::INTEGER);
do {
$startTime = microtime(true);
$deletedRows = $stmt->executeStatement();
$allRecords += $deletedRows;
echo round((microtime(true) - $startTime), 3) . "s ";
sleep(1);
} while ($deletedRows > 0);

$this->connection->executeQuery('SET FOREIGN_KEY_CHECKS=1');

return $allRecords;
}
}
3 changes: 2 additions & 1 deletion src/DependencyInjection/DataDogAuditExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace DataDog\AuditBundle\DependencyInjection;

use DataDog\AuditBundle\EventListener\AuditListener;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
Expand All @@ -17,7 +18,7 @@ public function load(array $configs, ContainerBuilder $container): void
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$auditListener = $container->getDefinition('datadog.event_listener.audit');
$auditListener = $container->getDefinition(AuditListener::class);

if (isset($config['audited_entities']) && !empty($config['audited_entities'])) {
$auditListener->addMethodCall('addAuditedEntities', array($config['audited_entities']));
Expand Down
4 changes: 4 additions & 0 deletions src/EventListener/AuditListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use DataDog\AuditBundle\DBAL\AuditLogger;
use DataDog\AuditBundle\Entity\Association;
use DataDog\AuditBundle\Entity\AuditLog;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\DBAL\Logging\LoggerChain;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\DBAL\Types\Type;
Expand All @@ -13,11 +14,14 @@
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Component\DependencyInjection\Attribute\AsAlias;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
use Symfony\Component\Security\Core\User\UserInterface;

#[AsDoctrineListener(Events::onFlush)]
#[AsAlias(id: 'datadog.event_listener.audit', public: false)]
class AuditListener
{
/**
Expand Down
29 changes: 21 additions & 8 deletions src/Resources/config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,26 @@
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;

return static function (ContainerConfigurator $container) {
// @formatter:off
$services = $container->services();
$services
->set('datadog.event_listener.audit', AuditListener::class)->private()
->arg(0, new Reference(TokenStorageInterface::class))
//->tag('doctrine.event_subscriber')
->tag('doctrine.event_listener', ['event' => 'onFlush',])
// default configuration for services in *this* file
$services = $container->services()
->defaults()
->autowire() // Automatically injects dependencies in your services.
->autoconfigure() // Automatically registers your services as commands, event subscribers, etc.
;
// @formatter:on

// makes classes in src/ available to be used as services
// this creates a service per class whose id is the fully-qualified class name
$services->load('DataDog\\AuditBundle\\', '../../../src/')
->exclude('../../../src/{DependencyInjection,Entity,Resources,DataDogAuditBundle.php}');


// // @formatter:off
// $services = $container->services();
// $services
// ->set('datadog.event_listener.audit', AuditListener::class)->private()
// ->arg(0, new Reference(TokenStorageInterface::class))
// //->tag('doctrine.event_subscriber')
// ->tag('doctrine.event_listener', ['event' => 'onFlush',])
// ;
// // @formatter:on
};

0 comments on commit e47ac64

Please sign in to comment.