lyzr-audit-logger-dev 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,333 @@
1
+ Metadata-Version: 2.4
2
+ Name: lyzr-audit-logger-dev
3
+ Version: 0.1.0
4
+ Summary: Audit logging library for microservices
5
+ Author-email: Lyzr <support@lyzr.ai>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/lyzr/audit-logger
8
+ Project-URL: Documentation, https://github.com/lyzr/audit-logger#readme
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Python: >=3.10
17
+ Description-Content-Type: text/markdown
18
+ Requires-Dist: motor>=3.0.0
19
+ Requires-Dist: pydantic>=2.0.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
22
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
23
+
24
+ # Audit Logger
25
+
26
+ A Python package for audit logging across microservices. Provides async, non-blocking audit log capture with MongoDB storage.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install audit-logger
32
+ ```
33
+
34
+ Or install from source:
35
+
36
+ ```bash
37
+ # Using HTTPS
38
+ pip install git+https://github.com/NeuralgoLyzr/audit-logger.git
39
+
40
+ # Using SSH
41
+ pip install git+ssh://git@github.com/NeuralgoLyzr/audit-logger.git
42
+ ```
43
+
44
+ For local development:
45
+
46
+ ```bash
47
+ cd audit_logger
48
+ pip install -e .
49
+ ```
50
+
51
+ ## Quick Start
52
+
53
+ ### 1. Initialize at Application Startup
54
+
55
+ ```python
56
+ from audit_logger import init_audit_logger
57
+
58
+ # Option 1: Use environment variable AUDIT_MONGO_URL (defaults to mongodb://localhost:27017)
59
+ audit_manager, audit_logger = init_audit_logger()
60
+
61
+ # Option 2: Explicit configuration
62
+ audit_manager, audit_logger = init_audit_logger(
63
+ mongo_url="mongodb://audit-db:27017",
64
+ db_name="my_service_audit",
65
+ collection_name="audit_logs"
66
+ )
67
+
68
+ # Create indexes (call once on startup)
69
+ await audit_manager.ensure_indexes()
70
+ ```
71
+
72
+ ### 2. Set Context in Middleware
73
+
74
+ ```python
75
+ from audit_logger import set_audit_context, clear_audit_context
76
+
77
+ @app.middleware("http")
78
+ async def audit_middleware(request: Request, call_next):
79
+ # Set context from auth info
80
+ set_audit_context(
81
+ org_id=request.state.auth_user.org_id,
82
+ user_id=request.state.auth_user.user_id,
83
+ api_key=request.headers.get("x-api-key"),
84
+ ip_address=request.client.host,
85
+ )
86
+ try:
87
+ return await call_next(request)
88
+ finally:
89
+ clear_audit_context()
90
+ ```
91
+
92
+ ### 3. Log Audit Events
93
+
94
+ ```python
95
+ from audit_logger import audit_logger, AuditResource
96
+
97
+ # Log a create action (non-blocking, returns immediately)
98
+ audit_logger.log_create(
99
+ resource_type=AuditResource.AGENT,
100
+ resource_id="agent_123",
101
+ resource_name="My Agent",
102
+ metadata={"tools_count": 5}
103
+ )
104
+
105
+ # Log an update action
106
+ from audit_logger import AuditChange
107
+
108
+ audit_logger.log_update(
109
+ resource_type=AuditResource.AGENT,
110
+ resource_id="agent_123",
111
+ changes=[
112
+ AuditChange(field="name", old_value="Old Name", new_value="New Name"),
113
+ AuditChange(field="description", old_value=None, new_value="New description"),
114
+ ]
115
+ )
116
+
117
+ # Log a delete action
118
+ audit_logger.log_delete(
119
+ resource_type=AuditResource.AGENT,
120
+ resource_id="agent_123",
121
+ resource_name="My Agent"
122
+ )
123
+ ```
124
+
125
+ ### 4. Shutdown Gracefully
126
+
127
+ ```python
128
+ from audit_logger import shutdown_audit_logger
129
+
130
+ @app.on_event("shutdown")
131
+ async def shutdown():
132
+ await shutdown_audit_logger()
133
+ ```
134
+
135
+ ## Advanced Usage
136
+
137
+ ### Direct Manager Access
138
+
139
+ For more control, use the `AuditLogManager` directly:
140
+
141
+ ```python
142
+ from audit_logger import get_audit_log_manager, AuditResource, AuditResult
143
+
144
+ manager = get_audit_log_manager()
145
+
146
+ # Log with full control
147
+ manager.log_create(
148
+ org_id="org_123",
149
+ resource_type=AuditResource.TOOL,
150
+ resource_id="tool_456",
151
+ user_id="user_789",
152
+ api_key="sk-xxx",
153
+ ip_address="192.168.1.1",
154
+ resource_name="My Tool",
155
+ metadata={"type": "openapi"},
156
+ result=AuditResult.SUCCESS,
157
+ )
158
+
159
+ # Log inference events
160
+ manager.log_inference(
161
+ org_id="org_123",
162
+ agent_id="agent_456",
163
+ session_id="session_789",
164
+ user_id="user_123",
165
+ result=AuditResult.SUCCESS,
166
+ metadata={"model": "gpt-4", "tokens": 1500}
167
+ )
168
+
169
+ # Log guardrail violations
170
+ from audit_logger import GuardrailViolation, AuditSeverity
171
+
172
+ manager.log_guardrail_violation(
173
+ org_id="org_123",
174
+ session_id="session_789",
175
+ violations=[
176
+ GuardrailViolation(
177
+ violation_type="pii",
178
+ severity=AuditSeverity.MEDIUM,
179
+ details={"entities": ["email", "phone"]}
180
+ )
181
+ ]
182
+ )
183
+ ```
184
+
185
+ ### Query Audit Logs
186
+
187
+ ```python
188
+ from audit_logger import get_audit_log_manager, AuditLogQuery, AuditResource
189
+
190
+ manager = get_audit_log_manager()
191
+
192
+ # Query with filters
193
+ logs = await manager.query(AuditLogQuery(
194
+ org_id="org_123",
195
+ resource_type=AuditResource.AGENT,
196
+ limit=50,
197
+ ))
198
+
199
+ # Get history for a specific resource
200
+ history = await manager.get_by_resource(
201
+ org_id="org_123",
202
+ resource_type=AuditResource.AGENT,
203
+ resource_id="agent_456",
204
+ )
205
+
206
+ # Get session activity
207
+ session_logs = await manager.get_by_session(session_id="session_789")
208
+
209
+ # Count matching logs
210
+ count = await manager.count(AuditLogQuery(org_id="org_123"))
211
+ ```
212
+
213
+ ### Using the Decorator
214
+
215
+ ```python
216
+ from audit_logger import audit_action, AuditAction, AuditResource
217
+
218
+ @audit_action(
219
+ action=AuditAction.DELETE,
220
+ resource_type=AuditResource.AGENT,
221
+ resource_id_param="agent_id",
222
+ )
223
+ async def delete_agent(agent_id: str, _audit_manager=None):
224
+ # Delete logic here
225
+ pass
226
+ ```
227
+
228
+ ### Context Manager
229
+
230
+ ```python
231
+ from audit_logger import audit_context
232
+
233
+ async with audit_context(org_id="org_123", user_id="user_456") as request_id:
234
+ # All audit logs in this block will have the context set
235
+ audit_logger.log_create(AuditResource.AGENT, "agent_789")
236
+ ```
237
+
238
+ ## Configuration
239
+
240
+ ### Environment Variables
241
+
242
+ | Variable | Default | Description |
243
+ |----------|---------|-------------|
244
+ | `AUDIT_MONGO_URL` | `mongodb://localhost:27017` | MongoDB connection URL |
245
+
246
+ ### Programmatic Configuration
247
+
248
+ ```python
249
+ from audit_logger import init_audit_logger
250
+
251
+ # Full configuration
252
+ manager, logger = init_audit_logger(
253
+ mongo_url="mongodb://audit-db:27017",
254
+ db_name="lyzr_audit_logs",
255
+ collection_name="audit_logs",
256
+ )
257
+ ```
258
+
259
+ ### Using Existing Collection
260
+
261
+ If you already have a MongoDB collection configured:
262
+
263
+ ```python
264
+ from motor.motor_asyncio import AsyncIOMotorClient
265
+ from audit_logger import init_audit_logger
266
+
267
+ client = AsyncIOMotorClient("mongodb://localhost:27017")
268
+ collection = client["my_db"]["audit_logs"]
269
+
270
+ manager, logger = init_audit_logger(collection=collection)
271
+ ```
272
+
273
+ ## Available Enums
274
+
275
+ ### AuditAction
276
+ - `CREATE`, `READ`, `UPDATE`, `DELETE`
277
+ - `EXECUTE`, `LOGIN`, `LOGOUT`
278
+ - `ACCESS_DENIED`, `EXPORT`, `IMPORT`
279
+
280
+ ### AuditResource
281
+ - `AGENT`, `TOOL`, `PROVIDER`, `WORKFLOW`
282
+ - `SESSION`, `MESSAGE`, `CONTEXT`, `MEMORY`
283
+ - `CREDENTIAL`, `USER`, `ORGANIZATION`, `API_KEY`
284
+ - `INFERENCE`, `GUARDRAIL`, `ARTIFACT`
285
+
286
+ ### AuditResult
287
+ - `SUCCESS`, `FAILURE`, `BLOCKED`, `PARTIAL`
288
+
289
+ ### AuditSeverity
290
+ - `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`
291
+
292
+ ## MongoDB Schema
293
+
294
+ ```javascript
295
+ {
296
+ "_id": ObjectId,
297
+ "timestamp": ISODate,
298
+ "actor": {
299
+ "org_id": "org_123",
300
+ "user_id": "user_456",
301
+ "api_key_hash": "a1b2c3d4...xyz",
302
+ "ip_address": "192.168.1.1"
303
+ },
304
+ "action": "create",
305
+ "target": {
306
+ "resource_type": "agent",
307
+ "resource_id": "agent_789",
308
+ "resource_name": "Support Bot"
309
+ },
310
+ "result": "success",
311
+ "error_message": null,
312
+ "session_id": "session_abc",
313
+ "request_id": "req_def",
314
+ "changes": [...],
315
+ "guardrail_violations": [...],
316
+ "metadata": {...},
317
+ "severity": "low"
318
+ }
319
+ ```
320
+
321
+ ## Non-Blocking Writes
322
+
323
+ All logging methods are **non-blocking** by default. They use `asyncio.create_task()` to write to MongoDB in the background without blocking your request handlers.
324
+
325
+ For synchronous writes (when you need confirmation):
326
+
327
+ ```python
328
+ log_id = await manager.log_sync(entry)
329
+ ```
330
+
331
+ ## License
332
+
333
+ MIT
@@ -0,0 +1,310 @@
1
+ # Audit Logger
2
+
3
+ A Python package for audit logging across microservices. Provides async, non-blocking audit log capture with MongoDB storage.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install audit-logger
9
+ ```
10
+
11
+ Or install from source:
12
+
13
+ ```bash
14
+ # Using HTTPS
15
+ pip install git+https://github.com/NeuralgoLyzr/audit-logger.git
16
+
17
+ # Using SSH
18
+ pip install git+ssh://git@github.com/NeuralgoLyzr/audit-logger.git
19
+ ```
20
+
21
+ For local development:
22
+
23
+ ```bash
24
+ cd audit_logger
25
+ pip install -e .
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ ### 1. Initialize at Application Startup
31
+
32
+ ```python
33
+ from audit_logger import init_audit_logger
34
+
35
+ # Option 1: Use environment variable AUDIT_MONGO_URL (defaults to mongodb://localhost:27017)
36
+ audit_manager, audit_logger = init_audit_logger()
37
+
38
+ # Option 2: Explicit configuration
39
+ audit_manager, audit_logger = init_audit_logger(
40
+ mongo_url="mongodb://audit-db:27017",
41
+ db_name="my_service_audit",
42
+ collection_name="audit_logs"
43
+ )
44
+
45
+ # Create indexes (call once on startup)
46
+ await audit_manager.ensure_indexes()
47
+ ```
48
+
49
+ ### 2. Set Context in Middleware
50
+
51
+ ```python
52
+ from audit_logger import set_audit_context, clear_audit_context
53
+
54
+ @app.middleware("http")
55
+ async def audit_middleware(request: Request, call_next):
56
+ # Set context from auth info
57
+ set_audit_context(
58
+ org_id=request.state.auth_user.org_id,
59
+ user_id=request.state.auth_user.user_id,
60
+ api_key=request.headers.get("x-api-key"),
61
+ ip_address=request.client.host,
62
+ )
63
+ try:
64
+ return await call_next(request)
65
+ finally:
66
+ clear_audit_context()
67
+ ```
68
+
69
+ ### 3. Log Audit Events
70
+
71
+ ```python
72
+ from audit_logger import audit_logger, AuditResource
73
+
74
+ # Log a create action (non-blocking, returns immediately)
75
+ audit_logger.log_create(
76
+ resource_type=AuditResource.AGENT,
77
+ resource_id="agent_123",
78
+ resource_name="My Agent",
79
+ metadata={"tools_count": 5}
80
+ )
81
+
82
+ # Log an update action
83
+ from audit_logger import AuditChange
84
+
85
+ audit_logger.log_update(
86
+ resource_type=AuditResource.AGENT,
87
+ resource_id="agent_123",
88
+ changes=[
89
+ AuditChange(field="name", old_value="Old Name", new_value="New Name"),
90
+ AuditChange(field="description", old_value=None, new_value="New description"),
91
+ ]
92
+ )
93
+
94
+ # Log a delete action
95
+ audit_logger.log_delete(
96
+ resource_type=AuditResource.AGENT,
97
+ resource_id="agent_123",
98
+ resource_name="My Agent"
99
+ )
100
+ ```
101
+
102
+ ### 4. Shutdown Gracefully
103
+
104
+ ```python
105
+ from audit_logger import shutdown_audit_logger
106
+
107
+ @app.on_event("shutdown")
108
+ async def shutdown():
109
+ await shutdown_audit_logger()
110
+ ```
111
+
112
+ ## Advanced Usage
113
+
114
+ ### Direct Manager Access
115
+
116
+ For more control, use the `AuditLogManager` directly:
117
+
118
+ ```python
119
+ from audit_logger import get_audit_log_manager, AuditResource, AuditResult
120
+
121
+ manager = get_audit_log_manager()
122
+
123
+ # Log with full control
124
+ manager.log_create(
125
+ org_id="org_123",
126
+ resource_type=AuditResource.TOOL,
127
+ resource_id="tool_456",
128
+ user_id="user_789",
129
+ api_key="sk-xxx",
130
+ ip_address="192.168.1.1",
131
+ resource_name="My Tool",
132
+ metadata={"type": "openapi"},
133
+ result=AuditResult.SUCCESS,
134
+ )
135
+
136
+ # Log inference events
137
+ manager.log_inference(
138
+ org_id="org_123",
139
+ agent_id="agent_456",
140
+ session_id="session_789",
141
+ user_id="user_123",
142
+ result=AuditResult.SUCCESS,
143
+ metadata={"model": "gpt-4", "tokens": 1500}
144
+ )
145
+
146
+ # Log guardrail violations
147
+ from audit_logger import GuardrailViolation, AuditSeverity
148
+
149
+ manager.log_guardrail_violation(
150
+ org_id="org_123",
151
+ session_id="session_789",
152
+ violations=[
153
+ GuardrailViolation(
154
+ violation_type="pii",
155
+ severity=AuditSeverity.MEDIUM,
156
+ details={"entities": ["email", "phone"]}
157
+ )
158
+ ]
159
+ )
160
+ ```
161
+
162
+ ### Query Audit Logs
163
+
164
+ ```python
165
+ from audit_logger import get_audit_log_manager, AuditLogQuery, AuditResource
166
+
167
+ manager = get_audit_log_manager()
168
+
169
+ # Query with filters
170
+ logs = await manager.query(AuditLogQuery(
171
+ org_id="org_123",
172
+ resource_type=AuditResource.AGENT,
173
+ limit=50,
174
+ ))
175
+
176
+ # Get history for a specific resource
177
+ history = await manager.get_by_resource(
178
+ org_id="org_123",
179
+ resource_type=AuditResource.AGENT,
180
+ resource_id="agent_456",
181
+ )
182
+
183
+ # Get session activity
184
+ session_logs = await manager.get_by_session(session_id="session_789")
185
+
186
+ # Count matching logs
187
+ count = await manager.count(AuditLogQuery(org_id="org_123"))
188
+ ```
189
+
190
+ ### Using the Decorator
191
+
192
+ ```python
193
+ from audit_logger import audit_action, AuditAction, AuditResource
194
+
195
+ @audit_action(
196
+ action=AuditAction.DELETE,
197
+ resource_type=AuditResource.AGENT,
198
+ resource_id_param="agent_id",
199
+ )
200
+ async def delete_agent(agent_id: str, _audit_manager=None):
201
+ # Delete logic here
202
+ pass
203
+ ```
204
+
205
+ ### Context Manager
206
+
207
+ ```python
208
+ from audit_logger import audit_context
209
+
210
+ async with audit_context(org_id="org_123", user_id="user_456") as request_id:
211
+ # All audit logs in this block will have the context set
212
+ audit_logger.log_create(AuditResource.AGENT, "agent_789")
213
+ ```
214
+
215
+ ## Configuration
216
+
217
+ ### Environment Variables
218
+
219
+ | Variable | Default | Description |
220
+ |----------|---------|-------------|
221
+ | `AUDIT_MONGO_URL` | `mongodb://localhost:27017` | MongoDB connection URL |
222
+
223
+ ### Programmatic Configuration
224
+
225
+ ```python
226
+ from audit_logger import init_audit_logger
227
+
228
+ # Full configuration
229
+ manager, logger = init_audit_logger(
230
+ mongo_url="mongodb://audit-db:27017",
231
+ db_name="lyzr_audit_logs",
232
+ collection_name="audit_logs",
233
+ )
234
+ ```
235
+
236
+ ### Using Existing Collection
237
+
238
+ If you already have a MongoDB collection configured:
239
+
240
+ ```python
241
+ from motor.motor_asyncio import AsyncIOMotorClient
242
+ from audit_logger import init_audit_logger
243
+
244
+ client = AsyncIOMotorClient("mongodb://localhost:27017")
245
+ collection = client["my_db"]["audit_logs"]
246
+
247
+ manager, logger = init_audit_logger(collection=collection)
248
+ ```
249
+
250
+ ## Available Enums
251
+
252
+ ### AuditAction
253
+ - `CREATE`, `READ`, `UPDATE`, `DELETE`
254
+ - `EXECUTE`, `LOGIN`, `LOGOUT`
255
+ - `ACCESS_DENIED`, `EXPORT`, `IMPORT`
256
+
257
+ ### AuditResource
258
+ - `AGENT`, `TOOL`, `PROVIDER`, `WORKFLOW`
259
+ - `SESSION`, `MESSAGE`, `CONTEXT`, `MEMORY`
260
+ - `CREDENTIAL`, `USER`, `ORGANIZATION`, `API_KEY`
261
+ - `INFERENCE`, `GUARDRAIL`, `ARTIFACT`
262
+
263
+ ### AuditResult
264
+ - `SUCCESS`, `FAILURE`, `BLOCKED`, `PARTIAL`
265
+
266
+ ### AuditSeverity
267
+ - `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`
268
+
269
+ ## MongoDB Schema
270
+
271
+ ```javascript
272
+ {
273
+ "_id": ObjectId,
274
+ "timestamp": ISODate,
275
+ "actor": {
276
+ "org_id": "org_123",
277
+ "user_id": "user_456",
278
+ "api_key_hash": "a1b2c3d4...xyz",
279
+ "ip_address": "192.168.1.1"
280
+ },
281
+ "action": "create",
282
+ "target": {
283
+ "resource_type": "agent",
284
+ "resource_id": "agent_789",
285
+ "resource_name": "Support Bot"
286
+ },
287
+ "result": "success",
288
+ "error_message": null,
289
+ "session_id": "session_abc",
290
+ "request_id": "req_def",
291
+ "changes": [...],
292
+ "guardrail_violations": [...],
293
+ "metadata": {...},
294
+ "severity": "low"
295
+ }
296
+ ```
297
+
298
+ ## Non-Blocking Writes
299
+
300
+ All logging methods are **non-blocking** by default. They use `asyncio.create_task()` to write to MongoDB in the background without blocking your request handlers.
301
+
302
+ For synchronous writes (when you need confirmation):
303
+
304
+ ```python
305
+ log_id = await manager.log_sync(entry)
306
+ ```
307
+
308
+ ## License
309
+
310
+ MIT
@@ -0,0 +1,43 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "lyzr-audit-logger-dev"
7
+ version = "0.1.0"
8
+ description = "Audit logging library for microservices"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "Lyzr", email = "support@lyzr.ai"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ ]
24
+ dependencies = [
25
+ "motor>=3.0.0",
26
+ "pydantic>=2.0.0",
27
+ ]
28
+
29
+ [project.optional-dependencies]
30
+ dev = [
31
+ "pytest>=7.0.0",
32
+ "pytest-asyncio>=0.21.0",
33
+ ]
34
+
35
+ [project.urls]
36
+ Homepage = "https://github.com/lyzr/audit-logger"
37
+ Documentation = "https://github.com/lyzr/audit-logger#readme"
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
41
+
42
+ [tool.setuptools.package-dir]
43
+ "" = "src"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+