Programmatically create and manage monitors via code.
Programmatically create and manage monitors via code. This approach is ideal for CI/CD pipelines, managing many monitors, or when you need dynamic monitor configuration.
Manage multiple monitors from a configuration file:
Copied
import*asSentryfrom"@sentry/node";importfsfrom"fs/promises";// Load monitor configurationsconst monitorConfigs =JSON.parse(await fs.readFile("./monitor-configs.json","utf8"),);// Create/update all monitorsasyncfunctionsetupMonitors(){for(const config of monitorConfigs){console.log(`Setting up monitor: ${config.name}`);try{// Test run to create/update the monitorawaitSentry.withMonitor( config.slug,async()=>{console.log(`Monitor ${config.name} is configured`);},{schedule: config.schedule,checkinMargin: config.checkinMargin||5,maxRuntime: config.maxRuntime||30,timezone: config.timezone||"UTC",failureIssueThreshold: config.failureIssueThreshold||1,recoveryThreshold: config.recoveryThreshold||1,},);console.log(`✅ Monitor ${config.name} ready`);}catch(error){console.error(`❌ Failed to setup ${config.name}:`, error);}}}awaitsetupMonitors();
Example monitor-configs.json:
Copied
[{"name":"Daily Data Backup","slug":"daily-data-backup","schedule":{"type":"crontab","value":"0 2 * * *"},"checkinMargin":10,"maxRuntime":60,"timezone":"America/Los_Angeles"},{"name":"Hourly Health Check","slug":"hourly-health-check","schedule":{"type":"interval","value":1,"unit":"hour"},"checkinMargin":5,"maxRuntime":10}]
Environment-Specific Configuration
Configure different monitors for different environments:
Copied
import*asSentryfrom"@sentry/node";const environment = process.env.NODE_ENV||"production";// Environment-specific configurationsconst envConfigs ={production:{checkinMargin:5,maxRuntime:60,failureIssueThreshold:1,// Alert immediately in prod},staging:{checkinMargin:10,maxRuntime:120,failureIssueThreshold:3,// More tolerant in staging},development:{checkinMargin:30,maxRuntime:300,failureIssueThreshold:5,// Very tolerant in dev},};functioncreateEnvironmentAwareMonitor(baseConfig, slug){const envConfig = envConfigs[environment]|| envConfigs.production;return{...baseConfig,...envConfig,// Environment-specific monitor slugslug:`${slug}-${environment}`,};}// Usageconst baseJobConfig ={schedule:{type:"crontab",value:"0 */6 * * *"},timezone:"UTC",};const monitorConfig =createEnvironmentAwareMonitor( baseJobConfig,"data-sync",);Sentry.withMonitor( monitorConfig.slug,async()=>{awaitsyncData();}, monitorConfig,);
CI/CD Pipeline Integration
Set up monitors as part of your deployment process:
Copied
// scripts/setup-monitoring.jsimport*asSentryfrom"@sentry/node";// Initialize Sentry with server-side DSNSentry.init({dsn: process.env.SENTRY_DSN,environment: process.env.DEPLOY_ENV,});const monitors =[{slug:"daily-report-generator",name:"Daily Report Generator",schedule:{type:"crontab",value:"0 9 * * *"},checkinMargin:15,maxRuntime:45,},{slug:"hourly-data-sync",name:"Hourly Data Sync",schedule:{type:"interval",value:1,unit:"hour"},checkinMargin:5,maxRuntime:20,},];asyncfunctiondeployMonitors(){console.log("🚀 Deploying cron monitors...");for(const monitor of monitors){try{// Create/update monitor with a test check-inconst checkInId =Sentry.captureCheckIn({monitorSlug: monitor.slug,status:"ok",},{schedule: monitor.schedule,checkinMargin: monitor.checkinMargin,maxRuntime: monitor.maxRuntime,timezone:"UTC",},);console.log(`✅ Deployed monitor: ${monitor.name}`);}catch(error){console.error(`❌ Failed to deploy ${monitor.name}:`, error); process.exit(1);}}console.log("🎉 All monitors deployed successfully");}// Run if called directlyif(import.meta.url===`file://${process.argv[1]}`){awaitdeployMonitors();}
Validate monitor configurations before deployment:
Copied
import*asSentryfrom"@sentry/node";classMonitorConfigValidator{staticvalidateSchedule(schedule){if(!schedule ||!schedule.type){thrownewError("Schedule type is required");}if(schedule.type==="crontab"){if(!schedule.value||typeof schedule.value!=="string"){thrownewError("Crontab schedule must have a valid value string");}// Basic crontab validation (5 fields)const fields = schedule.value.trim().split(/\s+/);if(fields.length!==5){thrownewError("Crontab schedule must have exactly 5 fields");}}elseif(schedule.type==="interval"){if(!schedule.value||!schedule.unit){thrownewError("Interval schedule must have value and unit");}if(!["minute","hour","day","month","year"].includes(schedule.unit)){thrownewError("Invalid interval unit");}}else{thrownewError('Schedule type must be "crontab" or "interval"');}}staticvalidateConfig(config){// Validate schedulethis.validateSchedule(config.schedule);// Validate optional fieldsif( config.checkinMargin&&(config.checkinMargin<1|| config.checkinMargin>1440)){thrownewError("Checkin margin must be between 1 and 1440 minutes");}if( config.maxRuntime&&(config.maxRuntime<1|| config.maxRuntime>1440)){thrownewError("Max runtime must be between 1 and 1440 minutes");}if(config.failureIssueThreshold&& config.failureIssueThreshold<1){thrownewError("Failure issue threshold must be at least 1");}if(config.recoveryThreshold&& config.recoveryThreshold<1){thrownewError("Recovery threshold must be at least 1");}returntrue;}}// Safe monitor creation with validationasyncfunctioncreateValidatedMonitor(slug, config){try{MonitorConfigValidator.validateConfig(config);// Create monitorSentry.captureCheckIn({monitorSlug: slug,status:"ok"}, config);console.log(`✅ Monitor ${slug} created successfully`);returntrue;}catch(error){console.error(`❌ Failed to create monitor ${slug}:`, error.message);returnfalse;}}// Usageconst monitorConfig ={schedule:{type:"crontab",value:"0 */2 * * *"},checkinMargin:10,maxRuntime:45,timezone:"America/New_York",};awaitcreateValidatedMonitor("validated-job", monitorConfig);
// Store configs in version controlconst monitorConfigs ={production:{checkinMargin:5,failureIssueThreshold:1,},staging:{checkinMargin:15,failureIssueThreshold:3,},};
Help improve this content Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").