or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ai-monitoring.mdconfiguration.mdcontext-metadata.mdcron-monitoring.mdevent-capture.mdindex.mdintegrations.mdperformance-monitoring.mdprofiling.mdscope-management.mdstructured-logging.md

cron-monitoring.mddocs/

0

# Cron Monitoring

1

2

Scheduled job monitoring with automatic check-ins, failure detection, and alerting for cron jobs and scheduled tasks with support for various scheduling systems.

3

4

## Capabilities

5

6

### Monitor Decorator

7

8

Automatic monitoring for scheduled functions using a decorator that handles check-ins and failure detection.

9

10

```python { .api }

11

def monitor(

12

monitor_slug: str = None,

13

**monitor_config

14

) -> Callable:

15

"""

16

Decorator for automatic cron job monitoring.

17

18

Parameters:

19

- monitor_slug: Unique identifier for the monitor (auto-generated if None)

20

- **monitor_config: Monitor configuration options

21

22

Returns:

23

Callable: Decorator function that wraps the target function

24

"""

25

```

26

27

**Usage Examples:**

28

29

```python

30

import sentry_sdk

31

32

# Simple monitoring with auto-generated slug

33

@sentry_sdk.monitor

34

def daily_cleanup():

35

"""Daily cleanup job - monitored automatically."""

36

cleanup_temp_files()

37

remove_old_logs()

38

vacuum_database()

39

40

# Custom monitor slug and configuration

41

@sentry_sdk.monitor(

42

monitor_slug="hourly-data-sync",

43

schedule_type="crontab",

44

schedule="0 * * * *", # Every hour

45

checkin_margin=5, # 5 minute margin

46

max_runtime=1800, # 30 minute timeout

47

timezone="UTC"

48

)

49

def sync_data():

50

"""Hourly data synchronization job."""

51

fetch_external_data()

52

process_updates()

53

update_cache()

54

55

# Interval-based monitoring

56

@sentry_sdk.monitor(

57

monitor_slug="process-queue",

58

schedule_type="interval",

59

schedule={"value": 5, "unit": "minute"},

60

checkin_margin=2,

61

max_runtime=300

62

)

63

def process_message_queue():

64

"""Process message queue every 5 minutes."""

65

messages = get_pending_messages()

66

for message in messages:

67

process_message(message)

68

```

69

70

### Manual Check-ins

71

72

Manual control over monitor check-ins for complex scheduling scenarios or custom job runners.

73

74

```python { .api }

75

def capture_checkin(

76

monitor_slug: str = None,

77

check_in_id: str = None,

78

status: MonitorStatus = None,

79

duration: float = None,

80

**monitor_config

81

) -> str:

82

"""

83

Send a check-in for a cron monitor.

84

85

Parameters:

86

- monitor_slug: Unique monitor identifier

87

- check_in_id: Check-in ID for updating existing check-in

88

- status: Check-in status (ok, error, in_progress, timeout)

89

- duration: Job duration in seconds

90

- **monitor_config: Monitor configuration for auto-creation

91

92

Returns:

93

str: Check-in ID for future updates

94

"""

95

```

96

97

**Usage Examples:**

98

99

```python

100

import sentry_sdk

101

import time

102

103

def run_batch_job():

104

# Start check-in

105

check_in_id = sentry_sdk.capture_checkin(

106

monitor_slug="batch-processing",

107

status=sentry_sdk.MonitorStatus.IN_PROGRESS,

108

schedule_type="crontab",

109

schedule="0 2 * * *", # Daily at 2 AM

110

max_runtime=3600

111

)

112

113

start_time = time.time()

114

115

try:

116

# Run the actual job

117

process_daily_batch()

118

119

# Success check-in

120

duration = time.time() - start_time

121

sentry_sdk.capture_checkin(

122

monitor_slug="batch-processing",

123

check_in_id=check_in_id,

124

status=sentry_sdk.MonitorStatus.OK,

125

duration=duration

126

)

127

128

except Exception as e:

129

# Failure check-in

130

duration = time.time() - start_time

131

sentry_sdk.capture_checkin(

132

monitor_slug="batch-processing",

133

check_in_id=check_in_id,

134

status=sentry_sdk.MonitorStatus.ERROR,

135

duration=duration

136

)

137

raise

138

139

# Simple success check-in

140

def simple_job():

141

try:

142

perform_task()

143

sentry_sdk.capture_checkin(

144

monitor_slug="simple-task",

145

status=sentry_sdk.MonitorStatus.OK

146

)

147

except Exception:

148

sentry_sdk.capture_checkin(

149

monitor_slug="simple-task",

150

status=sentry_sdk.MonitorStatus.ERROR

151

)

152

raise

153

```

154

155

## Monitor Configuration

156

157

### Schedule Types

158

159

#### Crontab Schedule

160

161

```python

162

@sentry_sdk.monitor(

163

schedule_type="crontab",

164

schedule="0 0 * * *", # Daily at midnight

165

timezone="America/New_York"

166

)

167

def daily_report():

168

generate_daily_report()

169

```

170

171

#### Interval Schedule

172

173

```python

174

@sentry_sdk.monitor(

175

schedule_type="interval",

176

schedule={"value": 30, "unit": "minute"}, # Every 30 minutes

177

checkin_margin=5

178

)

179

def check_system_health():

180

monitor_system_metrics()

181

```

182

183

### Monitor Status Types

184

185

```python { .api }

186

class MonitorStatus:

187

OK = "ok" # Job completed successfully

188

ERROR = "error" # Job failed with an error

189

IN_PROGRESS = "in_progress" # Job is currently running

190

TIMEOUT = "timeout" # Job exceeded max_runtime

191

UNKNOWN = "unknown" # Unknown status

192

```

193

194

### Configuration Options

195

196

- **schedule_type**: "crontab" or "interval"

197

- **schedule**: Cron expression or interval object

198

- **timezone**: Timezone for schedule interpretation

199

- **checkin_margin**: Grace period in minutes for late jobs

200

- **max_runtime**: Maximum expected runtime in seconds

201

- **failure_issue_threshold**: Consecutive failures before alert

202

- **recovery_threshold**: Consecutive successes to clear alert

203

204

## Integration Examples

205

206

### Celery Beat Integration

207

208

```python

209

import sentry_sdk

210

from celery import Celery

211

from celery.schedules import crontab

212

213

app = Celery('tasks')

214

215

@app.task

216

@sentry_sdk.monitor(

217

monitor_slug="celery-cleanup",

218

schedule_type="crontab",

219

schedule="0 3 * * *",

220

timezone="UTC"

221

)

222

def cleanup_task():

223

"""Celery task with Sentry monitoring."""

224

cleanup_old_data()

225

return "Cleanup completed"

226

227

# Celery Beat configuration

228

app.conf.beat_schedule = {

229

'cleanup-task': {

230

'task': 'tasks.cleanup_task',

231

'schedule': crontab(hour=3, minute=0),

232

},

233

}

234

```

235

236

### APScheduler Integration

237

238

```python

239

import sentry_sdk

240

from apscheduler.schedulers.blocking import BlockingScheduler

241

242

scheduler = BlockingScheduler()

243

244

@sentry_sdk.monitor(

245

monitor_slug="apscheduler-job",

246

schedule_type="interval",

247

schedule={"value": 10, "unit": "minute"}

248

)

249

def scheduled_job():

250

"""APScheduler job with monitoring."""

251

process_pending_tasks()

252

253

scheduler.add_job(

254

func=scheduled_job,

255

trigger="interval",

256

minutes=10,

257

id='my_job'

258

)

259

260

scheduler.start()

261

```

262

263

### Crontab Integration

264

265

```bash

266

# System crontab entry

267

0 */6 * * * /usr/bin/python /path/to/monitored_script.py

268

```

269

270

```python

271

#!/usr/bin/env python

272

# monitored_script.py

273

import sentry_sdk

274

275

sentry_sdk.init(dsn="your-dsn-here")

276

277

@sentry_sdk.monitor(

278

monitor_slug="system-cron-job",

279

schedule_type="crontab",

280

schedule="0 */6 * * *", # Every 6 hours

281

max_runtime=1800

282

)

283

def main():

284

"""Script run by system cron."""

285

perform_maintenance_tasks()

286

287

if __name__ == "__main__":

288

main()

289

```

290

291

### Custom Job Runner Integration

292

293

```python

294

import sentry_sdk

295

import time

296

from datetime import datetime

297

298

class JobRunner:

299

def __init__(self):

300

self.jobs = []

301

302

def add_job(self, func, schedule, monitor_slug):

303

self.jobs.append({

304

'func': func,

305

'schedule': schedule,

306

'monitor_slug': monitor_slug,

307

'last_run': None

308

})

309

310

def run_job(self, job):

311

"""Run a single job with monitoring."""

312

monitor_slug = job['monitor_slug']

313

314

# Start check-in

315

check_in_id = sentry_sdk.capture_checkin(

316

monitor_slug=monitor_slug,

317

status=sentry_sdk.MonitorStatus.IN_PROGRESS

318

)

319

320

start_time = time.time()

321

322

try:

323

# Execute the job

324

job['func']()

325

job['last_run'] = datetime.now()

326

327

# Success check-in

328

duration = time.time() - start_time

329

sentry_sdk.capture_checkin(

330

monitor_slug=monitor_slug,

331

check_in_id=check_in_id,

332

status=sentry_sdk.MonitorStatus.OK,

333

duration=duration

334

)

335

336

except Exception as e:

337

# Error check-in

338

duration = time.time() - start_time

339

sentry_sdk.capture_checkin(

340

monitor_slug=monitor_slug,

341

check_in_id=check_in_id,

342

status=sentry_sdk.MonitorStatus.ERROR,

343

duration=duration

344

)

345

# Log error but continue with other jobs

346

print(f"Job {monitor_slug} failed: {e}")

347

348

# Usage

349

runner = JobRunner()

350

runner.add_job(

351

func=lambda: backup_database(),

352

schedule="0 2 * * *",

353

monitor_slug="nightly-backup"

354

)

355

```

356

357

## Error Handling and Recovery

358

359

### Automatic Error Detection

360

361

The monitor decorator automatically detects and reports:

362

- Unhandled exceptions as ERROR status

363

- Function execution time for performance tracking

364

- Missing check-ins for scheduled jobs

365

366

### Recovery Scenarios

367

368

```python

369

import sentry_sdk

370

import time

371

372

@sentry_sdk.monitor(

373

monitor_slug="resilient-job",

374

schedule_type="interval",

375

schedule={"value": 15, "unit": "minute"},

376

failure_issue_threshold=3, # Alert after 3 consecutive failures

377

recovery_threshold=2 # Clear alert after 2 consecutive successes

378

)

379

def resilient_job():

380

"""Job with retry logic and monitoring."""

381

max_retries = 3

382

383

for attempt in range(max_retries):

384

try:

385

perform_critical_operation()

386

return # Success

387

except Exception as e:

388

if attempt == max_retries - 1:

389

# Final attempt failed, let monitor record ERROR

390

raise

391

else:

392

# Retry after delay

393

time.sleep(30 * (attempt + 1))

394

```

395

396

## Best Practices

397

398

### Monitor Naming

399

400

Use descriptive, kebab-case monitor slugs:

401

- `daily-data-backup`

402

- `hourly-cache-refresh`

403

- `weekly-report-generation`

404

405

### Schedule Configuration

406

407

- Set appropriate `checkin_margin` for network delays

408

- Configure `max_runtime` based on historical job duration

409

- Use UTC timezone for consistency across environments

410

411

### Error Handling

412

413

- Always use try/catch blocks for critical jobs

414

- Implement retry logic for transient failures

415

- Send contextual information with check-ins

416

417

### Performance Monitoring

418

419

Monitor job performance trends:

420

- Track duration changes over time

421

- Set alerts for abnormal runtime increases

422

- Monitor resource usage during job execution

423

424

Cron monitoring provides comprehensive visibility into scheduled job health, enabling proactive maintenance and reliable automation workflows.