diff --git a/docs/docs/changelog.md b/docs/docs/changelog.md index 0aa902a..8a728b3 100644 --- a/docs/docs/changelog.md +++ b/docs/docs/changelog.md @@ -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 diff --git a/docs/docs/home.md b/docs/docs/home.md index 3ea45b8..a8cf6b2 100644 --- a/docs/docs/home.md +++ b/docs/docs/home.md @@ -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. diff --git a/docs/docs/orms/prisma.md b/docs/docs/orms/prisma.md index 780e26b..32832d2 100644 --- a/docs/docs/orms/prisma.md +++ b/docs/docs/orms/prisma.md @@ -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+ @@ -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. @@ -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"; @@ -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: diff --git a/docs/docs/orms/rails.md b/docs/docs/orms/rails.md index 2a9a9f0..2fc6930 100644 --- a/docs/docs/orms/rails.md +++ b/docs/docs/orms/rails.md @@ -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' @@ -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+ @@ -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 diff --git a/docs/docs/orms/sqlalchemy.md b/docs/docs/orms/sqlalchemy.md new file mode 100644 index 0000000..03c7744 --- /dev/null +++ b/docs/docs/orms/sqlalchemy.md @@ -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 + +BemiHQ/bemi-sqlalchemy +
+
+ +[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 diff --git a/docs/docs/orms/typeorm.md b/docs/docs/orms/typeorm.md index 1e6254d..0347d13 100644 --- a/docs/docs/orms/typeorm.md +++ b/docs/docs/orms/typeorm.md @@ -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 diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 500509f..041ddd1 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -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", + }, ], }, { diff --git a/docs/sidebars.ts b/docs/sidebars.ts index 489db2c..237eb59 100644 --- a/docs/sidebars.ts +++ b/docs/sidebars.ts @@ -31,6 +31,7 @@ const sidebars: SidebarsConfig = { 'orms/prisma', 'orms/typeorm', 'orms/rails', + 'orms/sqlalchemy', ], }, 'alternatives',