Skip to content

Commit

Permalink
Describe integration with SQLAlchemy in Python
Browse files Browse the repository at this point in the history
  • Loading branch information
exAspArk committed Jun 14, 2024
1 parent 470c2ca commit 5c32407
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 7 deletions.
2 changes: 2 additions & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ keywords: ['Bemi Changelog', 'Bemi New Features', 'Postgres Audit Trails', 'Chan
* Platform
* Enable tracking changes from non-`public` PostgreSQL schemas
* Allow setting ignore-change column rules across all tables (e.g., `*.updatedAt`)
* [Bemi SQLAlchemy](https://github.com/BemiHQ/bemi-sqlalchemy)
* Create a new Python package to allow passing application context with data changes

## 2024-05

Expand Down
4 changes: 4 additions & 0 deletions docs/docs/home.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ This allows automatically enhancing low-level database changes with application-

* **[Ruby on Rails](/orms/rails)**

#### Python

* **[SQLAlchemy](/orms/sqlalchemy)**

## Architecture overview

Bemi is designed to be lightweight and secure. It takes a practical approach to achieving the benefits of [event sourcing](https://martinfowler.com/eaaDev/EventSourcing.html) without requiring rearchitecting existing code, switching to highly specialized databases, or using unnecessary git-like abstractions on top of databases. We want your system to work the way it already does with your existing database to allow keeping things as simple as possible.
Expand Down
10 changes: 6 additions & 4 deletions docs/docs/orms/prisma.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ keywords: [Bemi, Prisma, PostgreSQL, database auditing, data tracking, context-a

This package is a recommended Prisma integration, enabling you to pass application-specific context when performing database changes. This can include context such as the 'where' (API endpoint, worker, etc.), 'who' (user, cron job, etc.), and 'how' behind a change, thereby enriching the information captured by Bemi.

See this [example repo](https://github.com/BemiHQ/bemi-prisma-example) as an Todo app example with Prisma that automatically tracks and contextualizes all changes.

## Prerequisites

- PostgreSQL 14+
Expand Down Expand Up @@ -62,7 +64,9 @@ import { PrismaClient } from '@prisma/client';
const prisma = withPgAdapter(new PrismaClient());
```

Now you can specify custom application context that will be automatically passed with all data changes by following the code examples below. Application context:
Now you can specify custom application context that will be automatically passed with all data changes by following the code examples below.

Application context:

* Is bound to the current asynchronous runtime execution context, for example, an HTTP request.
* Is used only with `INSERT`, `UPDATE`, `DELETE` SQL queries performed via Prisma. Otherwise, it is a no-op.
Expand All @@ -72,7 +76,7 @@ Application context will automatically include the original SQL query that perfo

### Express.js

Add the `setContext` [Express.js](https://expressjs.com/) middleware to pass application context with all underlying data changes within made an HTTP request:
Add the `setContext` [Express.js](https://expressjs.com/) middleware to pass application context with all underlying data changes made within an HTTP request:

```ts title="src/index.ts"
import { setContext } from "@bemi-db/prisma";
Expand Down Expand Up @@ -166,8 +170,6 @@ const MyWorker = () => {
}
```

See this [example repo](https://github.com/BemiHQ/bemi-prisma-example) as an Todo app example with Prisma that automatically tracks all changes.

### SSL

If your database uses a self-signed SSL certificate and you want to enforce using it, you can modify your [Connection URL](https://www.prisma.io/docs/orm/overview/databases/postgresql#connection-url) to include the following arguments:
Expand Down
6 changes: 4 additions & 2 deletions docs/docs/orms/rails.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Bemi vs. PaperTrail, Audited, Logidze - Advanced Rails Audit Trails
sidebar_label: Rails
sidebar_label: Ruby on Rails
hide_title: true
description: Discover why Bemi is the preferred choice over PaperTrail, Audited, and Logidze for tracking database changes in Ruby on Rails. Learn how Bemi integrates with ActiveRecord and PostgreSQL to offer reliable, scalable audit trails with minimal performance impact.
image: 'img/rails-gems-comparison.png'
Expand All @@ -17,6 +17,8 @@ keywords: [Bemi, PaperTrail, Audited, Logidze, Rails audit trails, ActiveRecord

This Ruby gem is a recommended Ruby on Rails integration, enabling you to pass application-specific context when performing database changes. This can include context such as the 'where' (API endpoint, worker, etc.), 'who' (user, cron job, etc.), and 'how' behind a change, thereby enriching the information captured by Bemi.

See this [example repo](https://github.com/BemiHQ/bemi-rails-example) as a Ruby on Rails Todo app that automatically tracks and contextualizes all changes.

## Prerequisites

- PostgreSQL 14+
Expand Down Expand Up @@ -68,7 +70,7 @@ Application context:
* Is used only with `INSERT`, `UPDATE`, `DELETE` SQL queries performed via Active Record. Otherwise, it is a no-op.
* Is passed directly into PG [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html) with data changes without affecting the structure of the database and SQL queries.

See this [example repo](https://github.com/BemiHQ/bemi-rails-example) as a Ruby on Rails Todo app that automatically tracks all changes.
Application context will automatically include the original SQL query that performed data changes, which is generally useful for troubleshooting purposes.

## Database connection

Expand Down
129 changes: 129 additions & 0 deletions docs/docs/orms/sqlalchemy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: Bemi SQLAlchemy Integration - Automate Context-Aware Audit Trails with PostgreSQL
sidebar_label: SQLAlchemy
hide_title: true
description: Discover how Bemi integrates with SQLAlchemy and PostgreSQL to automatically track database changes, providing robust audit trails for your applications. Learn how to install and use the Bemi SQLAlchemy Python package for enhanced data tracking.
image: 'img/bemi-sqlalchemy.png'
keywords: [Bemi, SQLAlchemy, PostgreSQL, database auditing, data tracking, context-aware audit, application context, audit log, audit trail, data versioning]
---

# SQLAlchemy

<a class="github-button" href="https://github.com/BemiHQ/bemi-sqlalchemy" data-size="large" data-show-count="true" aria-label="Star BemiHQ/bemi-sqlalchemy on GitHub">BemiHQ/bemi-sqlalchemy</a>
<br />
<br />

[Bemi](https://bemi.io) plugs into [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy) and PostgreSQL to track database changes automatically. It unlocks robust context-aware audit trails and time travel querying inside your application.

This Python package is a recommended SQLAlchemy integration, enabling you to pass application-specific context when performing database changes. This can include context such as the 'where' (API endpoint, worker, etc.), 'who' (user, cron job, etc.), and 'how' behind a change, thereby enriching the information captured by Bemi.

See this [example repo](https://github.com/BemiHQ/bemi-sqlalchemy-example) as a SQLAlchemy and FastAPI Todo app that automatically tracks and contextualized all changes.

## Prerequisites

- PostgreSQL 14+
- SQLAlchemy

## Installation

1. Install the Python package

```sh
pip install bemi-sqlalchemy
```

2. Generate an [Alembic](https://github.com/sqlalchemy/alembic) migration file to add lightweight [PostgreSQL triggers](https://www.postgresql.org/docs/current/plpgsql-trigger.html) for passing application context with all data changes into PostgreSQL replication log

```sh
alembic revision -m "Init Bemi"
```

And add the following code:

```py title="alembic/versions/a925526dcc3b_init_bemi.py"
...

def upgrade() -> None:
Bemi.migration_upgrade()

def downgrade() -> None:
Bemi.migration_downgrade()
```

3. Run the Alembic migration

```sh
alembic upgrade head
```

## Usage

Now you can easily specify custom application context that will be automatically passed with all data changes:

```py
from bemi import Bemi
from sqlalchemy import create_engine
engine = create_engine(DATABASE_URL)

Bemi.set_context({ "process": "MyWorker" })

with engine.connect() as connection:
connection.execute("INSERT INTO ...")
connection.execute("UPDATE ...")
```

Application context:

* Is bound to the current database session execution context.
* Is used only with `INSERT`, `UPDATE`, `DELETE` SQL queries performed via SQLAlchemy. Otherwise, it is a no-op.
* Is passed directly into PG [Write-Ahead Log](https://www.postgresql.org/docs/current/wal-intro.html) with data changes without affecting the structure of the database and SQL queries.

Application context will automatically include the original SQL query that performed data changes, which is generally useful for troubleshooting purposes.

### FastAPI

Add a middleware to your [FastAPI](https://github.com/tiangolo/fastapi) app to automatically pass application context with all tracked database changes made within an HTTP request:

```py
from bemi import BemiFastAPIMiddleware
from fastapi import FastAPI

app = FastAPI()

app.add_middleware(
BemiFastAPIMiddleware,
set_context=lambda request : {
"user_id": current_user(request),
"endpoint": request.url.path,
"method": request.method,
}
)
```

## Database connection

Connect your PostgreSQL source database on [bemi.io](https://bemi.io) to start ingesting and storing all data changes stitched together with application-specific context. The database connection details can be securely configured through the [dashboard UI](https://dashboard.bemi.io/log-in?ref=prisma) in a few seconds.

![dashboard](/img/dashboard.png)

Once your destination PostgreSQL database has been fully provisioned, you'll see a "Connected" status. You can now test the connection after making database changes in your connected source database:

```
psql postgres://[USERNAME]:[PASSWORD]@[HOSTNAME]:5432/[DATABASE] -c 'SELECT "primary_key", "table", "operation", "before", "after", "context", "committed_at" FROM changes;'
primary_key | table | operation | before | after | context | committed_at
-------------+-------+-----------+----------------------------------------------------+-----------------------------------------------------+-------------------------------------------------------------------------------------------+------------------------
26 | todo | CREATE | {} | {"id": 26, "task": "Sleep", "is_completed": false} | {"user_id": 187234, "endpoint": "/todo", "method": "POST", "SQL": "INSERT INTO ..."} | 2023-12-11 17:09:09+00
27 | todo | CREATE | {} | {"id": 27, "task": "Eat", "is_completed": false} | {"user_id": 187234, "endpoint": "/todo", "method": "POST", "SQL": "INSERT INTO ..."} | 2023-12-11 17:09:11+00
28 | todo | CREATE | {} | {"id": 28, "task": "Repeat", "is_completed": false} | {"user_id": 187234, "endpoint": "/todo", "method": "POST", "SQL": "INSERT INTO ..."} | 2023-12-11 17:09:13+00
26 | todo | UPDATE | {"id": 26, "task": "Sleep", "is_completed": false} | {"id": 26, "task": "Sleep", "is_completed": true} | {"user_id": 187234, "endpoint": "/todo/complete", "method": "PUT", "SQL": "UPDATE ..."} | 2023-12-11 17:09:15+00
27 | todo | DELETE | {"id": 27, "task": "Eat", "is_completed": false} | {} | {"user_id": 187234, "endpoint": "/todo/27", "method": "DELETE", "SQL": "DELETE FROM ..."} | 2023-12-11 17:09:18+00
```

See [Destination Database](/postgresql/destination-database) for more details.

## License

Distributed under the terms of the [LGPL-3.0](https://github.com/BemiHQ/bemi-prisma/blob/main/LICENSE).
If you need to modify and distribute the code, please release it to contribute back to the open-source community.
hide_title: true
2 changes: 1 addition & 1 deletion docs/docs/orms/typeorm.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ keywords: [Bemi, TypeORM integration, PostgreSQL change tracking, database audit

This package is a recommended TypeORM integration, enabling you to pass application-specific context when performing database changes. This can include context such as the 'where' (API endpoint, worker, etc.), 'who' (user, cron job, etc.), and 'how' behind a change, thereby enriching the information captured by Bemi.

See this [example repo](https://github.com/BemiHQ/bemi-typeorm-example) as an Todo app example with TypeORM that automatically tracks all changes.
See this [example repo](https://github.com/BemiHQ/bemi-typeorm-example) as an Todo app example with TypeORM that automatically tracks and contextualizes all changes.

## Prerequisites

Expand Down
4 changes: 4 additions & 0 deletions docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ const config: Config = {
label: "Ruby on Rails",
href: "https://github.com/BemiHQ/bemi-rails",
},
{
label: "SQLAlchemy",
href: "https://github.com/BemiHQ/bemi-sqlalchemy",
},
],
},
{
Expand Down
1 change: 1 addition & 0 deletions docs/sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const sidebars: SidebarsConfig = {
'orms/prisma',
'orms/typeorm',
'orms/rails',
'orms/sqlalchemy',
],
},
'alternatives',
Expand Down

0 comments on commit 5c32407

Please sign in to comment.