Using Constructs
Every resource you create using the Checkly CLI is represented by a “construct”: it’s a class you import from checkly/constructs
,
for instance an ApiCheck
or EmailAlertChannel
. A construct is the “as-code” representation of the eventual resource
created / deleted / updated on the Checkly cloud once you run npx checkly deploy
.
Assigning Logical IDs
Assigning a logicalId
is crucial when creating a construct. Remember the following rules when creating and updating constructs:
- Every construct needs to have a
logicalId
. This is the first argument when instantiating a class, i.e.
const check = new ApiCheck('my-logical-id', { name: 'My API check' })
- Every
logicalId
needs to be unique within the scope of aProject
. A Project also has alogicalId
. - A
logicalId
can be any string up to 255 characters in length. - There is no hard limit on the amount of
Project
’s you can have in your Checkly account.
Behind the scenes, we use the logicalId
to create a graph of your resources so we know what to persist, update and remove
from our database. Changing the logicalId
on an existing resource in your code base will tell the Checkly backend that
a resource was removed and a new resource was created.
So, I guess you know now that logical IDs are important!
Creating an API Check
API checks are used to validate your HTTP based API endpoints. Let’s look at the example below as it does a couple of things:
- It defines the basic check properties like
name
,activated
etc. - It defines the HTTP method
GET
theurl
. - It defines an array of assertions to assert the HTTP response status is correct.
// hello-api.check.ts
import { ApiCheck, AssertionBuilder } from 'checkly/constructs'
const path = require('path')
const { readFileSync } = require('fs')
new ApiCheck('hello-api-1', {
name: 'Hello API',
activated: true,
request: {
method: 'GET',
url: 'https://mac-demo-repo.vercel.app/api/hello',
assertions: [
AssertionBuilder.statusCode().equals(200)
],
}
})
Creating and adding an Alert Channel
When a check fails, you want to get alerted. There are two steps to take here:
- Create one or more alert channels. You can put them in a different file to DRY up your code, i.e. in
alert-channels.ts
// alert-channels.ts
import { SmsAlertChannel, EmailAlertChannel } from 'checkly/constructs'
const sendDefaults = {
sendFailure: true,
sendRecovery: true,
sendDegraded: false,
}
const smsChannel = new SmsAlertChannel('sms-channel-1', {
phoneNumber: '0031061234567890',
...sendDefaults
})
const emailChannel = new EmailAlertChannel('email-channel-1', {
address: 'alerts@acme.com',
...sendDefaults
})
module.exports = {
smsChannel,
emailChannel
}
- Now you can import these channels into one or more checks by passing the objects into the
alertChannels
array:
// api.check.ts
import { ApiCheck } from 'checkly/constructs'
import { smsChannel, emailChannel } from './alert-channels'
new ApiCheck('hello-api-1', {
name: 'Hello API',
alertChannels: [smsChannel, emailChannel],
request: {
method: 'GET',
url: 'https://mac-demo-repo.vercel.app/api/hello',
}
})
Using the Constructs API
All resources you can create and manage using the Checkly CLI are derived from “constructs”. These constructs are just
TypeScript classes like ApiCheck
in api-check.ts
and
SlackAlertChannel
in slack-alert-channel.ts
.
You can use standard JS/TS programming to use these constructs to create the monitoring setup of your choice. Loops, variables, if-statements, file imports, extensions etc.
Using ECMAScript modules files (experimental)
If your project uses ECMAScript modules files, you can specify type: "module"
in your package.json
file or use .mjs
file extensions. ECMAScript modules files can be used to create resources or as check’s script dependencies.
Note that
__dirname
and__filename
don’t exist in ECMAScript so you have to adapt your setup/teardown script references using relative paths. Also, as the setup/teardown script dependencies are run under a sandboxed environment, you must use CommonJS (or TypeScript project) for all the second-level dependencies for API and Browser checks.
Example using top-level await
supported in ECMAScript
// __checks__/api.check.mjs
import { ApiCheck, AssertionBuilder } from 'checkly/constructs'
console.log('Fetching endpoints list from the database')
// top-level-await available
const getEndpointFromDB = await Promise.resolve([
{
id: 'fetch-books-check',
name: 'Fetch Book List',
url: 'https://danube-web.shop/api/books',
method: 'GET',
},
{
id: 'fetch-book-check',
name: 'Fetch a Book',
url: 'https://danube-web.shop/api/books/1',
method: 'GET',
}
])
getEndpointFromDB.forEach(endpoint => new ApiCheck(endpoint.id, {
name: endpoint.name,
setupScript: {
// relative reference to the file (__dirname not available in ECMAScript)
entrypoint: './utils/setup.mjs'
},
request: {
url: endpoint.url,
method: endpoint.method,
followRedirects: true,
skipSSL: false,
assertions: [
AssertionBuilder.statusCode().equals(200),
],
}
})
)
// __checks__/utils/setup.mjs
import { getToken } from './auth-client.mjs'
// top-level-await available
request.headers['X-My-Auth-Header'] = await getToken()
// __checks__/utils/auth-client.mjs
// top-level-await is NOT available in second-level script dependencies
export async function getToken () {
console.log('Fetching a token from an imaginary auth API endpoint')
const token = await new Promise(resolve => { return resolve('abc123') })
return token
}
Further Reading
Make sure to check our Constructs Reference page for all the details on all the constructs available in the Checkly CLI
You can contribute to this documentation by editing this page on Github