Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 78 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,45 @@ Installation

`composer require locastic/loggastic`

Quick start
-----------

Mark an entity as loggable with the `Loggable` attribute and put the serialization group on every field you want to track:

```php
<?php

namespace App\Entity;

use Locastic\Loggastic\Annotation\Loggable;
use Symfony\Component\Serializer\Attribute\Groups;

#[Loggable(groups: ['blog_post_log'])]
class BlogPost
{
private int $id;

#[Groups(groups: ['blog_post_log'])]
private string $title;

// ...
}
```

Initialize the storage (Elasticsearch indexes or database tables):

```bash
bin/console locastic:activity-logs:create-loggable-indexes
```

Every create, update and delete on `BlogPost` is now logged automatically. Read the logs back with the `Locastic\Loggastic\DataProvider\ActivityLogProviderInterface` service:

```php
$activityLogs = $activityLogProvider->getActivityLogsByClassAndId(BlogPost::class, $blogPost->getId());
```

Logs are stored in Elasticsearch by default. Set `locastic_loggastic.storage: doctrine` to store them in your relational database instead (see the next section). The rest of this README covers each step in detail.

Choose your storage
-------------------

Expand Down Expand Up @@ -147,16 +186,20 @@ Note: You can also use **annotations, xml and yaml**! Examples coming soon.

Create the Elasticsearch indexes or database tables for your loggable classes:

bin/console locastic:activity-logs:create-loggable-indexes
```bash
bin/console locastic:activity-logs:create-loggable-indexes
```

If you already have some data in the database, make sure to populate current data trackers with the following command:

bin/console locastic:activity-logs:populate-current-data-trackers
```bash
bin/console locastic:activity-logs:populate-current-data-trackers
```

### 4. Displaying activity logs
Here are the examples for displaying activity logs in twig or as Api endpoints:

**a) Displaying logs in Twig**
#### Display activity logs in Twig
`Locastic\Loggastic\DataProvider\ActivityLogProviderInterface` service comes with a few useful methods for getting the activity logs data:
```php
public function getActivityLogsByClass(string $className, array $sort = []): array;
Expand All @@ -165,7 +208,7 @@ Here are the examples for displaying activity logs in twig or as Api endpoints:
```
If you need to read logs directly from a specific Elasticsearch index, use
`Locastic\Loggastic\Bridge\Elasticsearch\Storage\ElasticsearchActivityLogStorage::findByIndexAndObjectId()`.
Use them to fetch data from the Elasticsearch and display it in your views. Example for displaying results in Twig:
Use them to fetch the activity logs from the configured storage and display them in your views. Example for displaying results in Twig:
```twig
Activity logs for Blog Posts:
<br>
Expand All @@ -182,8 +225,8 @@ Updated BlogPost with 1 ID at 02.01.2023 08:30:00 by admin
Deleted BlogPost with 1 ID at 01.01.2023 12:00:00 by admin
```

**b) Displaying logs in the api endpoint using ApiPlatform**
In order to display Loggastic activity logs in an ApiPlatform endpoint, you can use ApiPlatforms ElasticSearch integration: https://api-platform.com/docs/core/elasticsearch/
#### Expose activity logs as an API Platform endpoint (Elasticsearch storage)
In order to display Loggastic activity logs in an ApiPlatform endpoint, you can use ApiPlatforms ElasticSearch integration (this approach only applies to the `elasticsearch` storage): https://api-platform.com/docs/core/elasticsearch/

Example for displaying activity logs in the ApiPlatform endpoint:
```php
Expand Down Expand Up @@ -212,7 +255,7 @@ If you want to return only logs for one entity, use the exact index name. For ex
That's it!
----------
Now you have the basic activity logs setup.
Each time some change happens in the database for loggable entities, the activity log will be saved to the Elasticsearch.
Each time some change happens in the database for loggable entities, the activity log will be saved to the configured storage.

## Customization guide
Now that you have the basic setup, you can add some additional options and customize the library to your needs.
Expand All @@ -239,7 +282,10 @@ services:
The loggers, message handlers, data providers and console commands will use your implementations without any further changes.

## Configuration reference
Default configuration:
All options live under the `locastic_loggastic` key in `config/packages/loggastic.yaml`. The values below are the defaults.

### General options

```yaml
# config/packages/loggastic.yaml
locastic_loggastic:
Expand All @@ -258,16 +304,31 @@ locastic_loggastic:
# 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

# ElasticSearch config (only used when storage is 'elasticsearch')
```

### Elasticsearch connection options

Only used when `storage` is `elasticsearch`:

```yaml
# config/packages/loggastic.yaml
locastic_loggastic:
elastic_host: 'localhost:9200'
elastic_user: null # basic auth username, for secured clusters
elastic_password: null # basic auth password, for secured clusters
elastic_ssl_verification: true # disable only for local development
elastic_date_detection: true #https://www.elastic.co/guide/en/elasticsearch/reference/current/date-detection.html
elastic_dynamic_date_formats: "strict_date_optional_time||epoch_millis||strict_time"
```

### Elasticsearch index mappings

Index mappings for the activity log and current data tracker indexes, only used when `storage` is `elasticsearch` (see https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#mappings):

# ElasticSearch index mapping for ActivityLog. https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#mappings
```yaml
# config/packages/loggastic.yaml
locastic_loggastic:
# ElasticSearch index mapping for ActivityLog
activity_log:
elastic_properties:
id:
Expand Down Expand Up @@ -303,7 +364,6 @@ locastic_loggastic:
type: text
data:
type: text

```

### Saving logs async
Expand Down Expand Up @@ -460,11 +520,13 @@ public function removeProductVariant(ProductVariant $productVariant): static
With `orphanRemoval` enabled the variant is deleted as soon as it leaves the collection, so nulling the owning side is unnecessary, and it makes `logTo()` return null while Loggastic is logging the removal, silently dropping the parent's activity log. Keep the owning side set instead.

### Custom event listeners for saving activity logs
You can use `Locastic\Loggastic\Logger\ActivityLoggerInterface` service to save item changes to the Elasticsearch:
You can use `Locastic\Loggastic\Logger\ActivityLoggerInterface` service to save item changes to the configured storage:
```php
<?php
namespace App\Service;

use Locastic\Loggastic\Logger\ActivityLoggerInterface;

class SomeService
{
public function __construct(private readonly ActivityLoggerInterface $activityLogger)
Expand All @@ -482,12 +544,12 @@ class SomeService
Depending on you application logic, you need to find the most fitting place to trigger logs saving.

In most cases that can be the ***Doctrine event listener*** which is triggered on each database change. Loggastic comes with a built-in Doctrine listener which is used by default.
If you want to turn it off, you can do it by setting the `loggastic.doctrine_listener_enabled` config parameter to `false`:
If you want to turn it off, you can do it by setting the `default_doctrine_subscriber` config option to `false`:
```yaml
# config/packages/loggastic.yaml

loggastic:
doctrine_listener_enabled: false
locastic_loggastic:
default_doctrine_subscriber: false
```

If you are using ***ApiPlatform***, one of the good options would be to use its POST_WRITE event: https://api-platform.com/docs/core/events/#custom-event-listeners
Expand Down
17 changes: 17 additions & 0 deletions context7.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://context7.com/schema/context7.json",
"projectTitle": "Loggastic",
"description": "Symfony bundle for tracking changes to entities and their relations, storing activity logs in Elasticsearch or a relational database (Doctrine DBAL).",
"folders": [],
"excludeFolders": ["tests", ".github"],
"excludeFiles": ["CHANGELOG.md", "SECURITY.md", "CODE_OF_CONDUCT.md", "CONTRIBUTING.md"],
"rules": [
"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, needs a PSR-18 HTTP client, e.g. symfony/http-client + nyholm/psr7), 'doctrine' (uses the default DBAL connection, two shared tables with JSON columns), or 'in_memory' (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 (Elasticsearch indexes or database tables) 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."
]
}
Loading