0
# Migration Monitoring
1
2
Track applied and unapplied Django migrations across database connections to monitor deployment and migration status. Provides visibility into database schema state and migration progress.
3
4
## Capabilities
5
6
### Migration Export Functions
7
8
Functions to track and export Django migration status as Prometheus metrics.
9
10
```python { .api }
11
def ExportMigrations():
12
"""
13
Exports counts of unapplied migrations.
14
15
This is meant to be called during app startup, ideally by
16
django_prometheus.apps.AppConfig.ready().
17
18
Iterates through all database connections and exports migration
19
counts for each database alias.
20
"""
21
22
def ExportMigrationsForDatabase(alias: str, executor):
23
"""
24
Exports migration counts for a specific database.
25
26
Parameters:
27
- alias: str, database connection alias name (e.g., 'default', 'analytics')
28
- executor: Django MigrationExecutor instance for the database connection
29
"""
30
```
31
32
### Django AppConfig Integration
33
34
```python { .api }
35
class DjangoPrometheusConfig(AppConfig):
36
"""Django app configuration that automatically sets up monitoring."""
37
38
def ready(self):
39
"""
40
Initializes Prometheus exports when Django apps are ready.
41
42
Automatically calls ExportMigrations() if migration export is enabled
43
via PROMETHEUS_EXPORT_MIGRATIONS setting.
44
"""
45
```
46
47
## Monitored Metrics
48
49
### Migration Status Metrics
50
- `django_migrations_unapplied_total`: Gauge showing count of unapplied migrations by database connection
51
- `django_migrations_applied_total`: Gauge showing count of applied migrations by database connection
52
53
Both metrics include the `connection` label indicating the database alias.
54
55
## Configuration
56
57
### Settings Configuration
58
59
Enable migration monitoring in Django settings:
60
61
```python
62
# settings.py
63
64
# Enable migration monitoring (disabled by default)
65
PROMETHEUS_EXPORT_MIGRATIONS = True
66
67
# Custom metric namespace (optional)
68
PROMETHEUS_METRIC_NAMESPACE = "myapp"
69
70
# Multiple database configuration
71
DATABASES = {
72
'default': {
73
'ENGINE': 'django.db.backends.postgresql',
74
'NAME': 'main_db',
75
# ... connection settings
76
},
77
'analytics': {
78
'ENGINE': 'django.db.backends.mysql',
79
'NAME': 'analytics_db',
80
# ... connection settings
81
}
82
}
83
```
84
85
### App Configuration
86
87
Migration monitoring is automatically enabled when `django_prometheus` is in `INSTALLED_APPS`:
88
89
```python
90
# settings.py
91
INSTALLED_APPS = [
92
'django_prometheus', # Must be in INSTALLED_APPS
93
# ... other apps
94
]
95
96
# Migration monitoring happens automatically in AppConfig.ready()
97
```
98
99
## Usage Examples
100
101
### Basic Migration Monitoring
102
103
```python
104
# settings.py
105
INSTALLED_APPS = ['django_prometheus', ...]
106
PROMETHEUS_EXPORT_MIGRATIONS = True
107
108
# Migration metrics will be automatically exported when Django starts
109
# Available at /metrics endpoint or configured export port
110
```
111
112
### Multiple Database Monitoring
113
114
```python
115
# settings.py
116
DATABASES = {
117
'default': {
118
'ENGINE': 'django.db.backends.postgresql',
119
'NAME': 'main_app',
120
},
121
'user_data': {
122
'ENGINE': 'django.db.backends.mysql',
123
'NAME': 'user_database',
124
},
125
'cache_db': {
126
'ENGINE': 'django.db.backends.sqlite3',
127
'NAME': '/tmp/cache.db',
128
}
129
}
130
131
PROMETHEUS_EXPORT_MIGRATIONS = True
132
133
# Each database will have separate migration metrics:
134
# django_migrations_applied_total{connection="default"}
135
# django_migrations_applied_total{connection="user_data"}
136
# django_migrations_applied_total{connection="cache_db"}
137
```
138
139
### Manual Migration Export
140
141
```python
142
from django_prometheus.migrations import ExportMigrations, ExportMigrationsForDatabase
143
from django.db import connections
144
from django.db.migrations.executor import MigrationExecutor
145
146
# Manual export for all databases
147
ExportMigrations()
148
149
# Manual export for specific database
150
connection = connections['default']
151
executor = MigrationExecutor(connection)
152
ExportMigrationsForDatabase('default', executor)
153
```
154
155
### Custom App Configuration
156
157
```python
158
from django.apps import AppConfig
159
from django_prometheus.migrations import ExportMigrations
160
161
class MyAppConfig(AppConfig):
162
name = 'myapp'
163
164
def ready(self):
165
# Custom logic before migration export
166
if self.should_export_migrations():
167
ExportMigrations()
168
169
def should_export_migrations(self):
170
"""Custom logic to determine if migrations should be exported."""
171
return os.environ.get('EXPORT_MIGRATIONS', 'false').lower() == 'true'
172
```
173
174
## Metric Interpretation
175
176
### Understanding Migration Counts
177
178
```python
179
# Example metric values:
180
# django_migrations_applied_total{connection="default"} 42
181
# django_migrations_unapplied_total{connection="default"} 3
182
183
# This means:
184
# - 42 migrations have been applied to the 'default' database
185
# - 3 migrations are pending application
186
# - Total migrations defined: 45 (42 + 3)
187
```
188
189
### Deployment Monitoring
190
191
Use migration metrics to monitor deployment status:
192
193
```python
194
# Alerting rules for migration status:
195
# - Alert if unapplied_migrations > 0 after deployment
196
# - Alert if applied_migrations decreases (rollback scenario)
197
# - Monitor migration counts across different environments
198
```
199
200
## Integration with Django Migration System
201
202
### Migration Planning
203
204
The monitoring system uses Django's migration framework internally:
205
206
```python
207
from django.db.migrations.executor import MigrationExecutor
208
from django.db.migrations.loader import MigrationLoader
209
210
# Migration planning (done internally)
211
executor = MigrationExecutor(connection)
212
plan = executor.migration_plan(executor.loader.graph.leaf_nodes())
213
214
# Applied migrations count
215
applied_count = len(executor.loader.applied_migrations)
216
217
# Unapplied migrations count
218
unapplied_count = len(plan)
219
```
220
221
### Migration Graph Analysis
222
223
```python
224
# The system analyzes the complete migration graph
225
loader = MigrationLoader(connection)
226
227
# All defined migrations
228
all_migrations = loader.graph.nodes
229
230
# Applied migrations (from django_migrations table)
231
applied_migrations = loader.applied_migrations
232
233
# Unapplied migrations (calculated difference)
234
unapplied_migrations = set(all_migrations) - applied_migrations
235
```
236
237
## Error Handling
238
239
### Database Connection Issues
240
241
```python
242
# Graceful handling of database connection problems
243
from django.db.backends.dummy.base import DatabaseWrapper
244
245
# If DATABASES = {} (no database configured)
246
if isinstance(connections["default"], DatabaseWrapper):
247
# Skip migration export - no real database configured
248
return
249
250
# Connection-specific error handling
251
for alias in connections.databases:
252
try:
253
executor = MigrationExecutor(connections[alias])
254
ExportMigrationsForDatabase(alias, executor)
255
except Exception as e:
256
# Log error but don't crash application startup
257
logger.warning(f"Could not export migrations for {alias}: {e}")
258
```
259
260
### Migration Loader Errors
261
262
```python
263
# Handle migration loading errors gracefully
264
try:
265
loader = MigrationLoader(connection)
266
applied_migrations = loader.applied_migrations
267
except Exception as e:
268
# Set metrics to -1 to indicate error state
269
applied_migrations.labels(connection=alias).set(-1)
270
unapplied_migrations.labels(connection=alias).set(-1)
271
```
272
273
## Best Practices
274
275
### Deployment Monitoring
276
277
- Monitor migration metrics before and after deployments
278
- Set up alerts for unexpected migration counts
279
- Track migration timing across environments
280
- Use metrics to validate deployment success
281
282
### Database Management
283
284
- Monitor migration status across all database connections
285
- Track migration rollbacks (decreasing applied count)
286
- Alert on schema drift between environments
287
- Integrate with CI/CD pipelines for automated checks
288
289
### Performance Considerations
290
291
- Migration export happens once at Django startup
292
- Minimal performance impact on running application
293
- Database queries only executed during AppConfig.ready()
294
- Suitable for production use with multiple databases