=============== LIBRARY RULES =============== From library maintainers: - Requires PHP 8.2+, Symfony 6.4/7.x/8.x, and Doctrine ORM 3.4+. Storage backend: Elasticsearch 8 or 9 (default), any relational database via Doctrine DBAL, or in-memory for tests. - Select the storage backend with the locastic_loggastic.storage config option: 'elasticsearch' (default, requires a PSR-18 HTTP client), 'doctrine' (stores logs in two shared database tables) or 'in_memory' (for test suites). - Mark entities with the #[Loggable(groups: ['...'])] attribute and add the same serialization group to every field and relation you want tracked. - Import Groups from Symfony\Component\Serializer\Attribute, not Symfony\Component\Serializer\Annotation; the Annotation import silently disables logging on Symfony 8. - After configuring loggable entities, initialize the storage with bin/console locastic:activity-logs:create-loggable-indexes, then bin/console locastic:activity-logs:populate-current-data-trackers if data already exists. - Read activity logs through the ActivityLogProviderInterface service instead of querying the storage backend directly. - For a custom storage backend, implement ActivityLogStorageInterface, CurrentDataTrackerStorageInterface and StorageInitializerInterface, and alias the three interfaces to your services. - The dataChanges field of an activity log holds two objects, previousValues and currentValues, each listing only the modified fields. It is not structured as per-field old/new pairs. ### Entity Creation Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/architecture.md Demonstrates the basic creation and persistence of an entity using Doctrine. This is the starting point for logging entity mutations. ```php $blogPost = new BlogPost(); $blogPost->setTitle('Hello'); $em->persist($blogPost); $em->flush(); ``` -------------------------------- ### Example Workflow with Related Commands Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md This example shows the typical sequence of commands for setting up logging, including creating indexes and populating trackers for existing data. ```bash # 1. Create Elasticsearch indexes/database tables bin/console locastic:activity-logs:create-loggable-indexes # 2. If you have existing entities, populate their trackers bin/console locastic:activity-logs:populate-current-data-trackers # 3. Now logging will work correctly; updates will detect changes from the captured state ``` -------------------------------- ### Basic Async Messenger Setup Source: https://github.com/locastic/loggastic/blob/master/_autodocs/configuration.md Configure messages to be processed asynchronously. This setup routes specific message types to the default async handler. ```yaml framework: messenger: routing: 'Locastic\Loggastic\Message\CreateActivityLogMessage': async 'Locastic\Loggastic\Message\UpdateActivityLogMessage': async 'Locastic\Loggastic\Message\DeleteActivityLogMessage': async 'Locastic\Loggastic\Message\PopulateCurrentDataTrackersMessage': async ``` -------------------------------- ### Command Output Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md This shows the expected output during the execution of the populate command, indicating progress and completion. ```text Recreating App\Entity\BlogPost current data tracker storage... Processing batch: 0-100 ............................... Processing batch: 100-200 ............................... Done! ``` -------------------------------- ### Example Output for Index Creation Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md This output shows the successful creation of storage resources for different loggable classes. ```text Preparing activity log storage ... Creating App\Entity\BlogPost activity log storage Creating App\Entity\BlogPost current data tracker storage Creating App\Entity\Product activity log storage Creating App\Entity\Product current data tracker storage Done! ``` -------------------------------- ### Loggastic Configuration Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/README.md Example of Loggastic configuration in YAML format. Specifies the storage backend and paths for loggable classes. ```yaml # config/packages/loggastic.yaml locastic_loggastic: # Storage backend: elasticsearch, doctrine, or in_memory storage: doctrine # Path to loggable classes loggable_paths: - '%kernel.project_dir%/src/Entity' ``` -------------------------------- ### CurrentDataTracker Example Usage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/data-models.md Demonstrates how to retrieve information from a CurrentDataTracker instance, representing the state of a BlogPost. ```php // A tracker stores the latest state of a BlogPost $tracker->getId(); // 'tracker-123' (from storage) $tracker->getObjectId(); // '1' (BlogPost ID) $tracker->getObjectClass(); // 'App\Entity\BlogPost' $tracker->getData(); // ['title' => 'Hello', 'slug' => 'hello', ...] $tracker->getDateTime(); // DateTime when this data was captured ``` -------------------------------- ### Comprehensive Production Activity Log Enricher Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/pre-dispatch-event.md An example of a production-ready event listener that enriches activity log messages with security and request context. It logs entity deletions at a higher severity level. Ensure you have the necessary Symfony security and http-foundation components installed. ```php getActivityLogMessage(); $request = $this->requestStack->getCurrentRequest(); $user = $this->security->getUser(); // Enrich with security context $message->setUser($this->getUserData($user, $request)); // Enrich with request context $message->setRequestUrl($request?->getUri()); // Log deletions at a higher level if ($message instanceof DeleteActivityLogMessageInterface) { $this->logger->warning( 'Entity deletion logged', [ 'class' => $message->getClassName(), 'id' => $message->getObjectId(), 'user' => $user?->getUserIdentifier(), ] ); } } private function getUserData($user, $request): array { if (!$user) { return [ 'anonymous' => true, 'ip' => $request?->getClientIp(), ]; } return [ 'id' => $user->getId(), 'username' => $user->getUserIdentifier(), 'email' => $user->getEmail() ?? null, 'roles' => $user->getRoles(), 'ip' => $request?->getClientIp(), 'user_agent' => $request?->headers->get('User-Agent'), ]; } } ``` -------------------------------- ### API Method Signature Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/README.md Illustrates the standard format for documenting PHP methods, including parameters and their types, optionality, defaults, and descriptions, as well as the return type. ```php public function methodName(Type $param, ?Type $optional = null): ReturnType ``` -------------------------------- ### PopulateCurrentDataTrackersMessage getOffset Method Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Retrieves the starting position for the batch operation. ```php public function getOffset(): int ``` -------------------------------- ### Instantiate and Save CurrentDataTrackerInput Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/data-models.md Example of creating a CurrentDataTrackerInput object, setting its properties including JSON encoded data, and saving it using a storage service. ```php $input = new CurrentDataTrackerInput(); $input->setObjectId('1'); $input->setObjectClass('App\Entity\BlogPost'); $input->setData(json_encode(['title' => 'Hello'])); $storage->save($input, 'App\Entity\BlogPost'); ``` -------------------------------- ### Activity Log Retrieval Example Source: https://github.com/locastic/loggastic/blob/master/_autodocs/architecture.md Shows how to retrieve activity logs for a specific entity class and ID using the ActivityLogProvider. This is used for reading persisted logs. ```php $logs = $activityLogProvider->getActivityLogsByClassAndId($className, $objectId); ``` -------------------------------- ### Activity Log Record Structure Source: https://github.com/locastic/loggastic/blob/master/README.md An example of the data structure for an activity log record, specifically showing changes for 'Edited' actions. ```json { "previousValues": {"title": "My first post"}, "currentValues": {"title": "My updated post"} } ``` -------------------------------- ### Example PHP Class Structure Source: https://github.com/locastic/loggastic/blob/master/_autodocs/README.md Demonstrates the basic structure of a PHP class intended for use within the Loggastic framework. This serves as a template for implementing services that interact with the logging system. ```php findByClass( 'App\Entity\BlogPost', ['loggedAt' => 'desc', 'action' => 'asc'], 20 ); ``` -------------------------------- ### Activity Log Test Case - PHP Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/in-memory-storage.md Extends `KernelTestCase` to provide setup and assertion methods for testing activity logs. It initializes the logger and provider and includes helpers to verify specific actions and data changes. ```php 'test']); $container = self::getContainer(); $this->logger = $container->get(ActivityLoggerInterface::class); $this->provider = $container->get(ActivityLogProviderInterface::class); } protected function assertLoggedAction(string $className, $objectId, string $action): void { $logs = $this->provider->getActivityLogsByClassAndId($className, $objectId); $actions = array_map(fn($log) => $log->getAction(), $logs); $this->assertContains($action, $actions, "Action '$action' not found in logs"); } protected function assertDataChangeLogged(string $className, $objectId, string $field): void { $logs = $this->provider->getActivityLogsByClassAndId($className, $objectId); foreach ($logs as $log) { $changes = $log->getDataChanges(); if ($changes && isset($changes[$field])) { return; // Found } } $this->fail("Field '$field' change not logged"); } } ``` -------------------------------- ### Display Activity Logs in Twig Source: https://github.com/locastic/loggastic/blob/master/README.md Example Twig template code for iterating through and displaying activity logs. Assumes `activityLogs` variable is available. ```twig Activity logs for Blog Posts:
{% for log in activityLogs %} {{ log.action }} {{ log.objectType }} with {{ log.objectId }} ID at {{ log.loggedAt|date('d.m.Y H:i:s') }} by {{ log.user.username }} {% endfor %} ``` -------------------------------- ### Unit Test with In-Memory Storage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/in-memory-storage.md Ideal for unit and integration tests where you don't want external dependencies. This example demonstrates logging blog post creation and updates using the in-memory storage. ```php 'test']); $container = self::getContainer(); $this->logger = $container->get(ActivityLoggerInterface::class); $this->provider = $container->get(ActivityLogProviderInterface::class); } public function testBlogPostCreationIsLogged(): void { $post = new BlogPost(); $post->setTitle('Test Post'); $this->logger->logCreatedItem($post); $logs = $this->provider->getActivityLogsByClassAndId(BlogPost::class, $post->getId()); $this->assertCount(1, $logs); $this->assertSame('Created', $logs[0]->getAction()); } public function testBlogPostUpdateIsLogged(): void { $post = new BlogPost(); $post->setTitle('Original Title'); // Log creation $this->logger->logCreatedItem($post); // Update $post->setTitle('Updated Title'); $this->logger->logUpdatedItem($post); $logs = $this->provider->getActivityLogsByClassAndId(BlogPost::class, $post->getId()); $this->assertCount(2, $logs); $this->assertSame('Created', $logs[0]->getAction()); $this->assertSame('Edited', $logs[1]->getAction()); } } ``` -------------------------------- ### Enriching Activity Log Messages with User Information Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-message-dispatcher.md Implement a listener to enrich activity log messages before dispatch. This example adds user details like username and ID to the message. ```php getActivityLogMessage(); $user = $this->security->getUser(); $message->setUser([ 'username' => $user?->getUserIdentifier(), 'id' => $user?->getId(), ]); } } ``` -------------------------------- ### AMQP Transport Configuration Source: https://github.com/locastic/loggastic/blob/master/README.md Configure AMQP transports for 'activity_logs_default' and 'activity_logs_product' queues. This setup is suitable for high-throughput message processing. ```yaml framework: messenger: transports: activity_logs_default: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' options: exchange: name: activity_logs_default queues: activity_logs_default: ~ activity_logs_product: dsn: '%env(MESSENGER_TRANSPORT_DSN)%' options: queues: activity_logs_product: ~ exchange: name: activity_logs_product routing: 'Locastic\Loggastic\Message\PopulateCurrentDataTrackersMessage': activity_logs_default 'Locastic\Loggastic\Message\CreateActivityLogMessage': activity_logs_default 'Locastic\Loggastic\Message\DeleteActivityLogMessage': activity_logs_default 'Locastic\Loggastic\Message\UpdateActivityLogMessage': activity_logs_default ``` -------------------------------- ### Log Fields from Relations (PHP) Source: https://github.com/locastic/loggastic/blob/master/README.md Example of logging fields from related entities in PHP. Ensure the related entity's fields also have the correct serialization groups. ```php product; } public function setProduct(?Product $product): self { $this->product = $product; return $this; } public function logTo(): ?object { return $this->product; } } ``` -------------------------------- ### Get Activity Logs by Class Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-provider.md Retrieves all activity logs for a given entity class. Use this to fetch logs associated with a specific type of entity. Supports sorting and pagination. ```php use Locastic\Loggastic\DataProvider\ActivityLogProvider; // Assuming $activityLogProvider is an instance of ActivityLogProvider // Get last 20 logs for BlogPost $logs = $activityLogProvider->getActivityLogsByClass( 'App\Entity\BlogPost', ['loggedAt' => 'desc'], 20, 0 ); // Paginate through logs $page = 2; $perPage = 10; $logs = $activityLogProvider->getActivityLogsByClass( 'App\Entity\BlogPost', [], $perPage, ($page - 1) * $perPage ); ``` -------------------------------- ### Manual Logging in Tests Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/in-memory-storage.md Example of manually triggering a log entry within a test method. This ensures logs are only captured via explicit calls when the Doctrine subscriber is disabled. ```php public function testManualLogging(): void { // Only logs via explicit logger calls $this->logger->logCreatedItem($entity); } ``` -------------------------------- ### Custom Activity Log Message Dispatcher Source: https://github.com/locastic/loggastic/blob/master/README.md Decorate the ActivityLogMessageDispatcher to implement custom logic for dispatching messages to specific transports. This example routes 'Product' entity logs to 'activity_logs_product'. ```php getClassName() === Product::class) { $this->decorated->dispatch($activityLogMessage, 'activity_logs_product'); return; } $this->decorated->dispatch($activityLogMessage, $transportName); } } ``` -------------------------------- ### Enriching Activity Log Messages with an Event Listener Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/pre-dispatch-event.md An example of an event listener that intercepts `PreDispatchActivityLogMessageEvent` to enrich the `ActivityLogMessageInterface` with user details (ID, username, roles) and the current request URL. This listener requires `Security` and `RequestStack` services. ```php getActivityLogMessage(); // Set user information $user = $this->security->getUser(); $message->setUser([ 'id' => $user?->getId(), 'username' => $user?->getUserIdentifier(), 'roles' => $user?->getRoles() ?? [], ]); // Set request URL $request = $this->requestStack->getCurrentRequest(); $message->setRequestUrl($request?->getUri()); } } ``` -------------------------------- ### Initialize and Populate Activity Logs (Bash) Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md Use this bash script for automated deployments to create storage indexes and populate trackers from existing data. It simulates non-interactive input for selecting options and batch size. ```bash #!/bin/bash # Create indexes/tables bin/console locastic:activity-logs:create-loggable-indexes # Populate trackers from existing data # Use echo to provide non-interactive input: select "ALL" + batch size echo -e "2\n100" | bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Get Activity Logs by Class and ID Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-provider.md Retrieves activity logs for a specific entity instance. Use this to get the history of a particular record. Supports sorting and pagination. ```php use Locastic\Loggastic\DataProvider\ActivityLogProvider; // Assuming $activityLogProvider is an instance of ActivityLogProvider // Get activity history for a specific blog post $logs = $activityLogProvider->getActivityLogsByClassAndId( 'App\Entity\BlogPost', 1, ['loggedAt' => 'desc'], 50 ); foreach ($logs as $log) { echo $log->getAction(); // 'Created', 'Edited', 'Deleted' echo $log->getLoggedAt()->format('Y-m-d H:i:s'); echo $log->getUser()['username'] ?? 'anonymous'; } ``` -------------------------------- ### Initialize Loggastic Storage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/index.md Run these console commands to create necessary indexes for activity logs and populate data trackers. ```bash bin/console locastic:activity-logs:create-loggable-indexes bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Create Loggable Indexes Source: https://github.com/locastic/loggastic/blob/master/README.md Initialize the necessary Elasticsearch indexes or database tables for loggable entities using the console command. ```bash bin/console locastic:activity-logs:create-loggable-indexes ``` -------------------------------- ### Get Updated Item Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Retrieves the entity that was modified. This method is part of the UpdateActivityLogMessage class. ```php public function getUpdatedItem(): object ``` -------------------------------- ### Initialize Loggastic Storage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/configuration.md Run this command after configuration to initialize the necessary storage structures, such as creating indexes or tables. ```bash # Initialize storage (create indexes or tables) bin/console locastic:activity-logs:create-loggable-indexes ``` -------------------------------- ### Get Message Date Time Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Retrieves the timestamp when the message was created. This method is part of the UpdateActivityLogMessage class. ```php public function getDateTime(): DateTime ``` -------------------------------- ### Initialize and Populate Activity Logs (PHP) Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md Execute Loggastic console commands directly within PHP for creating storage and populating trackers. This method is useful when integrating command logic into existing PHP applications. ```php use Locastic\Loggastic\Command\CreateLoggableIndexesCommand; use Locastic\Loggastic\Command\PopulateCurrentDataTrackersCommand; use Symfony\Component\Console\Input\StringInput; // Create storage $command = $application->find('locastic:activity-logs:create-loggable-indexes'); $command->run(new StringInput(''), $output); // Populate trackers $command = $application->find('locastic:activity-logs:populate-current-data-trackers'); $command->run(new StringInput('ALL 100'), $output); ``` -------------------------------- ### CreateActivityLogMessage getDateTime Method Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Gets the timestamp when the log message was created. This typically defaults to the current time. ```php public function getDateTime(): \DateTime ``` -------------------------------- ### Populate Data Trackers with Custom Batch Size via Input Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Configure the populate command to process a larger number of entities at once for faster completion by piping input to specify the batch size. ```bash # Process 1000 entities at a time for faster completion echo -e "ALL\n1000" | bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Elasticsearch JSON Document Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/data-models.md Documents are stored as-is in Elasticsearch. This example shows the structure of a typical activity log entry. ```json { "id": "log-123", "action": "Edited", "loggedAt": "2024-01-15T10:30:00Z", "objectId": "1", "objectClass": "App\\Entity\\BlogPost", "dataChanges": { "title": {"old": "Hello", "new": "World"} }, "user": {"username": "admin", "id": 1}, "requestUrl": "http://example.com/admin/posts/1/edit" } ``` -------------------------------- ### Get Elasticsearch Item by ID Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/elasticsearch-service.md Retrieves a single document from an Elasticsearch index by its ID. The document is denormalized into the specified class. ```php $log = $elasticsearchService->getItemById( 'log-123', 'blog_post_activity_log', ActivityLog::class ); ``` -------------------------------- ### Run Populate Current Data Trackers Command Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md Execute the command to repopulate data trackers. This is a common step after database migrations or when setting up logging for existing entities. ```bash bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Get Normalized Item Data Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Returns the normalized (serialized) data of the entity as set by the logger. This method is part of the UpdateActivityLogMessage class. ```php public function getNormalizedItem(): array ``` -------------------------------- ### Constructor for ActivityLogProcessor Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-processor.md Initializes the ActivityLogProcessor with necessary dependencies for normalizing objects, managing activity logs, tracking current data, and creating input factories. ```php public function __construct( NormalizerInterface $objectNormalizer, ActivityLogStorageInterface $activityLogStorage, CurrentDataTrackerStorageInterface $currentDataTrackerStorage, ActivityLogInputFactoryInterface $activityLogInputFactory, CurrentDataTrackerInputFactoryInterface $currentDataTrackerInputFactory, LoggableContextFactoryInterface $loggableContextFactory ) ``` -------------------------------- ### Add Loggable Attribute to Entity (PHP) Source: https://github.com/locastic/loggastic/blob/master/README.md Example of adding the Loggable attribute to a PHP entity class. Define the serialization groups for logging. ```php getCollection( 'blog_post_activity_log', ActivityLog::class, [ 'query' => [ 'term' => ['objectId' => '123'] ], 'sort' => [ 'loggedAt' => 'desc' ] ], 20, 0 ); foreach ($logs as $log) { echo $log->getAction(); } ``` -------------------------------- ### Get Elasticsearch Item by Query Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/elasticsearch-service.md Retrieves a single document matching an Elasticsearch query. The document is denormalized into the specified class. An empty query body will match all documents. ```php $log = $elasticsearchService->getItemByQuery( 'blog_post_activity_log', ActivityLog::class, [ 'query' => [ 'term' => ['objectId' => '123'] ] ] ); ``` -------------------------------- ### Get Current Data Tracker by Class and ID Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/current-data-tracker-provider.md Retrieves the tracker containing the last known state of an entity. Use this to access previous values of fields before an update. ```php public function __construct(CurrentDataTrackerStorageInterface $currentDataTrackerStorage) ``` ```php public function getCurrentDataTrackerByClassAndId(string $className, $objectId): ?CurrentDataTrackerInterface ``` ```php $tracker = $currentDataTrackerProvider->getCurrentDataTrackerByClassAndId( 'App\Entity\BlogPost', 1 ); if ($tracker) { $oldData = $tracker->getData(); // Array of all tracked fields echo $oldData['title']; // Previous value of title field } ``` -------------------------------- ### initializeActivityLogStorage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/storage-interfaces.md Creates activity log storage for a loggable class if it doesn't exist. Implementations must be safe to run repeatedly. ```APIDOC ## initializeActivityLogStorage ### Description Creates activity log storage for a loggable class if it doesn't exist. Implementations must be safe to run repeatedly. ### Method Signature `public function initializeActivityLogStorage(string $className): bool` ### Parameters #### Path Parameters - **className** (string) - Required - Fully qualified class name ### Returns - **bool** - true if storage was created, false if it already existed ``` -------------------------------- ### Initialize Current Data Tracker Storage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/storage-interfaces.md Creates storage for current data trackers for a specified class if it's not already present. This operation is designed to be safely repeatable. ```php public function initializeCurrentDataTrackerStorage(string $className): bool ``` -------------------------------- ### Populate Loggastic Trackers Source: https://github.com/locastic/loggastic/blob/master/_autodocs/configuration.md Use this command to populate trackers from existing data, typically after schema changes have been made. ```bash # Populate trackers from existing data (after schema changes) bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Log Created Item with Dispatch Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-message-dispatcher.md Logs a created item by creating a `CreateActivityLogMessage`, dispatching a pre-dispatch event, and then sending the message to the bus via the `ActivityLogMessageDispatcher`. ```php public function logCreatedItem(object $item, ?string $actionName = null): void { $message = new CreateActivityLogMessage($item, $actionName); // Dispatch the event so listeners can enrich the message $this->eventDispatcher->dispatch(PreDispatchActivityLogMessageEvent::create($message)); // Send to message bus $this->activityLogMessageDispatcher->dispatch($message); } ``` -------------------------------- ### YAML Configuration for Loggable Paths Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Specify YAML and XML configuration files within the loggable paths to avoid unsupported mapping type errors. ```yaml locastic_loggastic: loggable_paths: - '%kernel.project_dir%/src/Entity' - '%kernel.project_dir%/config/loggastic' # Place .yml and .xml here ``` -------------------------------- ### Populate Current Data Trackers with Smaller Batch Size Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Use this command to populate data trackers. Specify a smaller batch size (e.g., 50) to prevent memory exhaustion during batch processing. ```bash bin/console locastic:activity-logs:populate-current-data-trackers # Choose batch size: 50 (instead of default 100) ``` -------------------------------- ### UpdateActivityLogMessageInterface Source: https://github.com/locastic/loggastic/blob/master/_autodocs/types.md Interface for updating activity log messages. It includes methods for getting and setting the updated item, its normalized representation, the date/time of the update, and a flag to check if the log was created without changes. ```APIDOC ## UpdateActivityLogMessageInterface Interface for update messages. ### Methods - **getUpdatedItem()**: object - Retrieves the updated item. - **setUpdatedItem(object $updatedItem)**: void - Sets the updated item. - **getNormalizedItem()**: array - Retrieves the normalized representation of the item. - **setNormalizedItem(array $normalizedItem)**: void - Sets the normalized representation of the item. - **isCreateLogWithoutChanges()**: bool - Checks if the log was created without any changes. - **getDateTime()**: \DateTime - Retrieves the date and time of the update. - **setDateTime(\DateTime $dateTime)**: void - Sets the date and time of the update. ``` -------------------------------- ### Create Activity Log Input from Message Source: https://github.com/locastic/loggastic/blob/master/_autodocs/architecture.md Use the `ActivityLogInputFactory` to create input models from incoming messages. This is part of the Factory Pattern implementation for message handling. ```php $activityLogInput = $activityLogInputFactory->createFromActivityLogMessage($message); ``` -------------------------------- ### ActivityLogInputInterface Source: https://github.com/locastic/loggastic/blob/master/_autodocs/types.md Defines the structure for input data used when persisting activity logs. It includes methods for setting and getting various log-related attributes such as action, timestamp, object details, and user information. ```APIDOC ## Interface: ActivityLogInputInterface ### Description Input model used to persist activity logs to storage. ### Methods - `getAction(): ?string` - `setAction(?string $action): void` - `getLoggedAt(): \DateTime` - `setLoggedAt(\DateTime $loggedAt): void` - `getObjectId(): string` - `setObjectId($objectId): void` - `getObjectClass(): ?string` - `setObjectClass(?string $objectClass): void` - `getRequestUrl(): ?string` - `setRequestUrl(?string $requestUrl): void` - `getDataChanges(): ?string` - `setDataChanges(?string $dataChanges = null): void` - `getUser(): ?array` - `setUser(?array $user): void` ### Location `src/Model/Input/ActivityLogInputInterface.php` ``` -------------------------------- ### PreDispatchActivityLogMessageEvent::create Source: https://github.com/locastic/loggastic/blob/master/_autodocs/types.md Creates a new PreDispatchActivityLogMessageEvent instance. ```APIDOC ## create ### Description Creates a new PreDispatchActivityLogMessageEvent instance. ### Method `create(ActivityLogMessageInterface $activityLogMessage): self` ### Parameters #### Path Parameters - **activityLogMessage** (ActivityLogMessageInterface) - Required - The activity log message associated with the event. ``` -------------------------------- ### InMemoryStorageInitializer No-Op Implementation Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/in-memory-storage.md Demonstrates the no-operation implementation of InMemoryStorageInitializer. The initializeActivityLogStorage method always returns true, indicating no actual initialization is needed for in-memory storage. ```php public function initializeActivityLogStorage(string $className): bool { return true; // Always return true (no actual storage to initialize) } ``` -------------------------------- ### PopulateCurrentDataTrackersMessage Constructor Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/message-classes.md Use this constructor to create a message for batch operations to populate current data trackers. Specify the offset, batch size, loggable class, and context. ```php public function __construct(int $offset, int $batchSize, string $loggableClass, array $loggableContext) ``` -------------------------------- ### Populate Current Data Trackers Command Source: https://github.com/locastic/loggastic/blob/master/README.md Command to populate the current data trackers table. Use this if you have existing data and are enabling logging. ```bash bin/console locastic:activity-logs:populate-current-data-trackers ``` -------------------------------- ### Verify Loggable Paths Existence Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Use shell commands to check if the configured paths for loggable files exist and are accessible. ```bash ls -la config/packages/loggastic ls -la src/Entity ``` -------------------------------- ### initializeCurrentDataTrackerStorage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/storage-interfaces.md Creates current data tracker storage for a loggable class if it doesn't exist. Implementations must be safe to run repeatedly. ```APIDOC ## initializeCurrentDataTrackerStorage ### Description Creates current data tracker storage for a loggable class if it doesn't exist. Implementations must be safe to run repeatedly. ### Method Signature `public function initializeCurrentDataTrackerStorage(string $className): bool` ### Parameters #### Path Parameters - **className** (string) - Required - Fully qualified class name ### Returns - **bool** - true if storage was created, false if it already existed ``` -------------------------------- ### recreateCurrentDataTrackerStorage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/storage-interfaces.md Drops existing current data tracker storage and creates it from scratch. ```APIDOC ## recreateCurrentDataTrackerStorage ### Description Drops existing current data tracker storage and creates it from scratch. ### Method Signature `public function recreateCurrentDataTrackerStorage(string $className): void` ### Parameters #### Path Parameters - **className** (string) - Required - Fully qualified class name ### Returns - **void** ``` -------------------------------- ### ActivityLogDoctrineSubscriber Constructor Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-doctrine-subscriber.md Initializes the subscriber with an ActivityLoggerInterface service to dispatch logging messages. ```php public function __construct(ActivityLoggerInterface $activityLogger) ``` -------------------------------- ### Interactive Mode Prompts Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/console-commands.md When run interactively, the command prompts for the loggable class and batch size. This allows for targeted repopulation or processing of large datasets in manageable chunks. ```text Choose loggable class to repopulate current data: [0] App\Entity\BlogPost [1] App\Entity\Product [2] ALL > 2 Enter batch size (number of entities to process per batch) [100]: > 500 ``` -------------------------------- ### Log Created Item Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-logger.md Logs the creation of an entity. Use a custom action name if the default 'CREATED' is not suitable. ```php $activityLogger->logCreatedItem($blogPost); // or with custom action name $activityLogger->logCreatedItem($blogPost, 'BlogPostCreated'); ``` -------------------------------- ### Verify Elasticsearch Host Configuration Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Check the Loggastic configuration file to ensure the correct Elasticsearch host is specified. ```bash # Verify config grep elastic_host config/packages/loggastic.yaml ``` -------------------------------- ### Register Custom Activity Log Storage Source: https://github.com/locastic/loggastic/blob/master/_autodocs/architecture.md Register your custom activity log storage implementation as a service. Ensure it implements the ActivityLogStorageInterface. ```yaml services: Locastic\Loggastic\Storage\ActivityLogStorageInterface: '@App\MyActivityLogStorage' ``` -------------------------------- ### PHP: Correctly Retrieve Activity Logs Source: https://github.com/locastic/loggastic/blob/master/_autodocs/errors.md Ensure the fully qualified class name is used when retrieving activity logs to avoid 'Missing Activity Log' errors. ```php // Correct $logs = $provider->getActivityLogsByClassAndId('App\Entity\BlogPost', 1); // Wrong $logs = $provider->getActivityLogsByClassAndId('BlogPost', 1); ``` -------------------------------- ### Loggastic Storage Interfaces Source: https://github.com/locastic/loggastic/blob/master/README.md These are the core interfaces that must be implemented for custom storage backends. They define the contracts for writing/reading logs, tracking data, and initializing storage. ```php Locastic\Loggastic\Storage\ActivityLogStorageInterface # writes and reads activity logs Locastic\Loggastic\Storage\CurrentDataTrackerStorageInterface # tracks the latest state of each loggable object Locastic\Loggastic\Storage\StorageInitializerInterface # creates the underlying storage (indexes, tables, ...) ``` -------------------------------- ### Configuring Loggable Entities with XML Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/loggable-attribute.md Define loggable classes and their associated serialization groups using an XML configuration file. This provides another alternative to PHP attributes. ```xml ``` -------------------------------- ### Listen to Specific Activity Log Message Types Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/pre-dispatch-event.md Register a listener that specifically handles create messages. The listener checks the message type and returns early if it's not a create message, allowing for custom logic only for create operations. ```php #[AsEventListener(event: PreDispatchActivityLogMessageEvent::class)] final class CreateActivityLogEnricher { public function __invoke(PreDispatchActivityLogMessageEvent $event): void { $message = $event->getActivityLogMessage(); // Only handle create messages if (!$message instanceof CreateActivityLogMessageInterface) { return; } // Custom logic for creates } } ``` -------------------------------- ### Listen to All Activity Log Message Types Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/pre-dispatch-event.md Register a listener to enrich all activity log messages (Create, Update, Delete). This listener is triggered for every pre-dispatch activity log event. ```php #[AsEventListener(event: PreDispatchActivityLogMessageEvent::class)] final class AllActivityLogEnricher { public function __invoke(PreDispatchActivityLogMessageEvent $event): void { // Enrich all messages (Create, Update, Delete) $message = $event->getActivityLogMessage(); $message->setUser(['id' => 1, 'username' => 'admin']); } } ``` -------------------------------- ### ActivityLogInputInterface PHP Source: https://github.com/locastic/loggastic/blob/master/_autodocs/types.md Interface for input models used to persist activity logs. Implement this to provide data for logging. ```php interface ActivityLogInputInterface { public function getAction(): ?string; public function setAction(?string $action): void; public function getLoggedAt(): \DateTime; public function setLoggedAt(\DateTime $loggedAt): void; public function getObjectId(): string; public function setObjectId($objectId): void; public function getObjectClass(): ?string; public function setObjectClass(?string $objectClass): void; public function getRequestUrl(): ?string; public function setRequestUrl(?string $requestUrl): void; public function getDataChanges(): ?string; public function setDataChanges(?string $dataChanges = null): void; public function getUser(): ?array; public function setUser(?array $user): void; } ``` -------------------------------- ### ElasticsearchService Constructor Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/elasticsearch-service.md The constructor for the ElasticsearchService initializes the service with necessary dependencies for Elasticsearch interaction and data serialization. ```APIDOC ## Constructor ```php public function __construct( ElasticsearchClientInterface $elasticsearchClient, NormalizerInterface $normalizer, DenormalizerInterface $denormalizer ) ``` ### Parameters - **$elasticsearchClient** (ElasticsearchClientInterface) - Required - Low-level Elasticsearch client wrapper - **$normalizer** (NormalizerInterface) - Required - Symfony serializer for normalizing objects to arrays - **$denormalizer** (DenormalizerInterface) - Required - Symfony serializer for denormalizing arrays back to objects ``` -------------------------------- ### Retrieve Activity Logs Source: https://github.com/locastic/loggastic/blob/master/README.md Use the `ActivityLogProviderInterface` service to fetch activity logs for a specific class and ID. ```php $activityLogs = $activityLogProvider->getActivityLogsByClassAndId(BlogPost::class, $blogPost->getId()); ``` -------------------------------- ### Process Created Item in ActivityLogProcessor Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/activity-log-processor.md Saves a creation activity log and an initial current data tracker snapshot for a new item. This method is called internally by the CreateActivityLogHandler. ```php public function processCreatedItem(CreateActivityLogMessageInterface $message): void ``` ```php // Called by CreateActivityLogHandler $message = new CreateActivityLogMessage($blogPost); $processor->processCreatedItem($message); // Results in: // - ActivityLog: action='Created', objectId=1, dataChanges=null // - CurrentDataTracker: objectId=1, data={title:'...', content:'...', ...} ``` -------------------------------- ### Configure Doctrine Storage Source: https://github.com/locastic/loggastic/blob/master/README.md Set the storage to 'doctrine' in the configuration file to store activity logs in your relational database instead of Elasticsearch. ```yaml # config/packages/loggastic.yaml locastic_loggastic: storage: doctrine ``` -------------------------------- ### Loggastic Project File Organization Source: https://github.com/locastic/loggastic/blob/master/_autodocs/index.md An overview of the Loggastic project's directory structure, showing the placement of source files, configuration, and tests. ```tree loggastic/ ├── src/ │ ├── Annotation/ │ │ └── Loggable.php │ ├── Bridge/ │ │ ├── Doctrine/ │ │ │ └── Storage/ │ │ └── Elasticsearch/ │ │ └── Storage/ │ ├── Command/ │ ├── DataProcessor/ │ ├── DataProvider/ │ ├── Enum/ │ ├── Event/ │ ├── EventListener/ │ ├── EventSubscriber/ │ ├── Factory/ │ ├── Identifier/ │ ├── Logger/ │ ├── Loggable/ │ ├── Message/ │ ├── MessageDispatcher/ │ ├── MessageHandler/ │ ├── Metadata/ │ ├── Model/ │ │ ├── Input/ │ │ └── Output/ │ ├── Serializer/ │ ├── Storage/ │ │ └── InMemory/ │ ├── Util/ │ └── LocasticLoggasticBundle.php ├── config/ │ └── (YAML configuration files) └── tests/ ``` -------------------------------- ### General Loggastic Configuration Source: https://github.com/locastic/loggastic/blob/master/README.md Defines the storage backend, paths for loggable classes, and enables/disables the Doctrine subscriber and identifier extractor. ```yaml # config/packages/loggastic.yaml locastic_loggastic: # storage backend for activity logs: 'elasticsearch', 'doctrine' or 'in_memory' storage: elasticsearch # directory paths containing loggable classes or xml/yaml files loggable_paths: - '%kernel.project_dir%/Resources/config/loggastic' - '%kernel.project_dir%/src/Entity' # Turn on/off the default Doctrine subscriber default_doctrine_subscriber: true # Turn on/off collection identifier extractor # if set to `true` objects identifiers in collections will be used as array keys # if set to `false` default numeric array keys will be used identifier_extractor: true ``` -------------------------------- ### ActivityLog Model Methods Source: https://github.com/locastic/loggastic/blob/master/_autodocs/api-reference/data-models.md Provides getter and setter methods for all properties of the ActivityLog model. Note that setDataChanges() decodes a JSON string into an array. ```php public function getId(): ?string public function setId(?string $id): void public function getAction(): ?string public function setAction(?string $action): void public function getLoggedAt(): \DateTime public function setLoggedAt(\DateTime $loggedAt): void public function getObjectId(): string public function setObjectId($objectId): void public function getObjectClass(): ?string public function setObjectClass(?string $objectClass): void public function getDataChanges(): ?array public function setDataChanges(?string $dataChanges = null): void public function getRequestUrl(): ?string public function setRequestUrl(?string $requestUrl): void public function getUser(): ?array public function setUser(?array $user): void ```