diff --git a/constructs/grpc-monitor.mdx b/constructs/grpc-monitor.mdx new file mode 100644 index 00000000..efd654f8 --- /dev/null +++ b/constructs/grpc-monitor.mdx @@ -0,0 +1,412 @@ +--- +title: 'GrpcMonitor Construct' +description: 'Learn how to configure gRPC monitors with the Checkly CLI.' +sidebarTitle: 'gRPC Monitor' +--- + +import GeneralMonitorOptionsTable from '/snippets/general-monitor-options-table.mdx'; + + +Learn more about gRPC Monitors in [the gRPC monitor overview](/detect/uptime-monitoring/grpc-monitors/overview). + + +Use gRPC Monitors to verify that your gRPC services are reachable, responding correctly, and meeting performance expectations. Monitors run in two modes: + +- **BEHAVIOR** — Invokes a unary gRPC method and asserts on the response +- **HEALTH** — Queries the standard `grpc.health.v1.Health/Check` endpoint + + +Before creating gRPC Monitors, ensure you have: + +- An initialized Checkly CLI project +- The hostname and port of the gRPC service you want to monitor +- In BEHAVIOR mode: the fully-qualified method name, and either server reflection enabled on the target or an inline `.proto` file + +For additional setup information, see [CLI overview](/cli/overview). + + + + +```ts HEALTH Mode +import { Frequency, GrpcAssertionBuilder, GrpcMonitor } from "checkly/constructs" + +new GrpcMonitor('grpc-health-1', { + name: 'My Service Health Check', + description: "Checks that **my-service** reports `SERVING` via the gRPC health protocol.", + frequency: Frequency.EVERY_1M, + request: { + url: 'grpc.example.com', + port: 50051, + grpcConfig: { + mode: 'HEALTH', + tls: true, + service: 'my.package.MyService', + }, + assertions: [ + GrpcAssertionBuilder.healthCheckStatus().equals(1), // 1 = SERVING + GrpcAssertionBuilder.responseTime().lessThan(500), + ], + }, +}) +``` + +```ts BEHAVIOR Mode +import { Frequency, GrpcAssertionBuilder, GrpcMonitor } from "checkly/constructs" + +new GrpcMonitor('grpc-behavior-1', { + name: 'User Service GetUser', + description: "Invokes `GetUser` on **user-service** and asserts the response.", + activated: true, + frequency: Frequency.EVERY_5M, + locations: ['us-east-1', 'eu-west-1'], + maxResponseTime: 3000, + degradedResponseTime: 1500, + request: { + url: 'grpc.example.com', + port: 50051, + grpcConfig: { + mode: 'BEHAVIOR', + tls: true, + serviceDefinition: 'REFLECTION', + method: 'users.UserService/GetUser', + message: '{"userId": "health-probe"}', + metadata: [{ key: 'authorization', value: 'Bearer {{GRPC_TOKEN}}' }], + }, + assertions: [ + GrpcAssertionBuilder.statusCode().equals(0), + GrpcAssertionBuilder.responseTime().lessThan(1000), + GrpcAssertionBuilder.responseMessage('$.name').notEmpty(), + ], + }, +}) +``` + + + +## Configuration + +gRPC monitors have their own gRPC-specific settings, plus the standard monitor options shared across all check types. + + + + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `request` | `object` | ✅ | - | gRPC request configuration object | +| `degradedResponseTime` | `number` | ❌ | `4000` | Response time in milliseconds at which the monitor is marked as degraded | +| `maxResponseTime` | `number` | ❌ | `5000` | Response time in milliseconds at which the monitor is marked as failed (max 180,000) | + + + + + + + + + +### `GrpcMonitor` Options + + + +gRPC connection and call configuration. + +**Usage:** + +```ts +new GrpcMonitor('grpc-monitor', { + name: 'My gRPC Service', + request: { + url: 'grpc.example.com', + port: 50051, + grpcConfig: { + mode: 'HEALTH', + tls: true, + }, + assertions: [ + GrpcAssertionBuilder.healthCheckStatus().equals(1), // 1 = SERVING + ], + }, +}) +``` + +**Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `url` | `string` | ✅ | - | Hostname or IP of the gRPC server. No scheme or port. | +| `port` | `number` | ✅ | - | Port the gRPC server listens on (1–65535) | +| `grpcConfig` | `object` | ✅ | - | gRPC-specific call configuration (see below) | +| `ipFamily` | `string` | ❌ | `'IPv4'` | IP family: `'IPv4'` \| `'IPv6'` | +| `skipSSL` | `boolean` | ❌ | `false` | Skip TLS certificate validation when `tls` is enabled | +| `timeout` | `number` | ❌ | `60` | Seconds to wait for the gRPC call to complete (1–180) | +| `assertions` | `GrpcAssertion[]` | ❌ | `[]` | Response assertions using `GrpcAssertionBuilder` | + + + + + +gRPC-specific call configuration nested inside `request`. + +**Parameters:** + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `mode` | `string` | ❌ | `'BEHAVIOR'` | Monitoring mode: `'BEHAVIOR'` \| `'HEALTH'` | +| `tls` | `boolean` | ❌ | `true` | Use TLS for the connection. Set to `false` for plaintext. | +| `metadata` | `Array<{key: string, value: string}>` | ❌ | `[]` | gRPC metadata (request headers) sent with the call | +| `storeResponseBody` | `boolean` | ❌ | `true` | Whether to persist the response body with the check result | +| `method` | `string` | BEHAVIOR | - | Fully-qualified method: `package.Service/Method`. Required in BEHAVIOR mode. | +| `serviceDefinition` | `string` | ❌ | `'REFLECTION'` | How to resolve the method schema: `'REFLECTION'` \| `'PROTO_FILE'`. BEHAVIOR mode only. | +| `protoContent` | `string` | ❌ | - | Inline `.proto` file content. Required when `serviceDefinition` is `'PROTO_FILE'`. | +| `message` | `string` | ❌ | - | JSON-encoded request payload. BEHAVIOR mode only. | +| `service` | `string` | ❌ | - | Service name to health-check. HEALTH mode only. Leave empty to query overall server health. | + + + + +Response time in milliseconds at which the monitor is marked as degraded (warning state). Maximum: 180,000. + +**Usage:** + +```ts highlight={3} +new GrpcMonitor('grpc-thresholds', { + name: 'gRPC Latency Thresholds', + degradedResponseTime: 1500, + maxResponseTime: 3000, + request: { + url: 'grpc.example.com', + port: 50051, + grpcConfig: { mode: 'HEALTH' }, + }, +}) +``` + + + + +Response time in milliseconds at which the monitor is marked as failed. Maximum: 180,000. + +**Usage:** + +```ts highlight={3} +new GrpcMonitor('grpc-thresholds', { + name: 'gRPC Latency Thresholds', + maxResponseTime: 3000, + request: { + url: 'grpc.example.com', + port: 50051, + grpcConfig: { mode: 'HEALTH' }, + }, +}) +``` + + + +### `GrpcMonitor` Assertions + +Use `GrpcAssertionBuilder` to define assertions for the `request` of a `GrpcMonitor`. The following sources are available: + +- `responseTime()`: Assert the total response time (DNS + connect + call) in milliseconds +- `statusCode()`: Assert the numeric gRPC status code (`0` = OK, `14` = UNAVAILABLE, etc.) +- `healthCheckStatus()`: Assert the health status by its **numeric** value (HEALTH mode). The runner evaluates this as a number — not a string. Enum mapping: `UNKNOWN=0`, `SERVING=1`, `NOT_SERVING=2`, `SERVICE_UNKNOWN=3` +- `responseMessage(property?)`: Assert against the JSON response body (BEHAVIOR mode), with an optional JSON path (e.g. `'$.name'`) +- `textBody(property?)`: Assert against the raw response body as text +- `responseMetadata(property?)`: Assert against response metadata (header) values returned by the server, identified by key + +Here are some examples: + +- Assert the call returns gRPC OK (code 0): + +```ts +GrpcAssertionBuilder.statusCode().equals(0) +// Equivalent to: +{ source: 'GRPC_STATUS_CODE', comparison: 'EQUALS', target: '0' } +``` + +- Assert the health check reports SERVING (numeric target required — the runner does not accept string labels): + +```ts +GrpcAssertionBuilder.healthCheckStatus().equals(1) // UNKNOWN=0, SERVING=1, NOT_SERVING=2, SERVICE_UNKNOWN=3 +// Equivalent to: +{ source: 'GRPC_HEALTHCHECK_STATUS', comparison: 'EQUALS', target: '1' } +``` + +- Assert a specific field in the JSON response body: + +```ts +GrpcAssertionBuilder.responseMessage('$.userId').notEmpty() +// Equivalent to: +{ source: 'GRPC_RESPONSE', property: '$.userId', comparison: 'NOT_EMPTY', target: '' } +``` + +- Assert the total response time: + +```ts +GrpcAssertionBuilder.responseTime().lessThan(500) +// Equivalent to: +{ source: 'RESPONSE_TIME', comparison: 'LESS_THAN', target: '500' } +``` + +- Assert a response metadata header value: + +```ts +GrpcAssertionBuilder.responseMetadata('content-type').contains('grpc') +// Equivalent to: +{ source: 'GRPC_METADATA', property: 'content-type', comparison: 'CONTAINS', target: 'grpc' } +``` + +Learn more in our docs on [Assertions](/detect/assertions). + +### General Monitor Options + + +Friendly name for your gRPC Monitor displayed in the Checkly dashboard and used in notifications. + +**Usage:** + +```ts highlight={2} +new GrpcMonitor('my-grpc-monitor', { + name: 'User Service Health', + /* More options ... */ +}) +``` + + + + +How often the gRPC Monitor should run. Use the `Frequency` enum to set the check interval. + +**Usage:** + +```ts highlight={3} +new GrpcMonitor('my-grpc-monitor', { + name: 'User Service Health', + frequency: Frequency.EVERY_1M, + /* More options ... */ +}) +``` + +**Available frequencies**: `EVERY_10S`, `EVERY_20S`, `EVERY_30S`, `EVERY_1M`, `EVERY_2M`, `EVERY_5M`, `EVERY_10M`, `EVERY_15M`, `EVERY_30M`, `EVERY_1H`, `EVERY_2H`, `EVERY_3H`, `EVERY_6H`, `EVERY_12H`, `EVERY_24H` + + + +Array of [public location codes](/concepts/locations/#public-locations) where the gRPC Monitor runs from. Multiple locations provide geographic coverage. + +**Usage:** + +```ts highlight={3} +new GrpcMonitor('global-grpc-monitor', { + name: 'Global gRPC Health', + locations: ['us-east-1', 'eu-west-1', 'ap-southeast-1'], + /* More options ... */ +}) +``` + + + + +Whether the gRPC Monitor is enabled and will run according to its schedule. + +**Usage:** + +```ts highlight={3} +new GrpcMonitor('my-grpc-monitor', { + name: 'User Service Health', + activated: false, + /* More options ... */ +}) +``` + + + +## Examples + + + + +```ts +import { Frequency, GrpcAssertionBuilder, GrpcMonitor } from "checkly/constructs" + +new GrpcMonitor('auth-health', { + name: 'Auth Service Health', + frequency: Frequency.EVERY_1M, + locations: ['us-east-1', 'eu-west-1'], + request: { + url: 'auth.internal.example.com', + port: 50051, + grpcConfig: { + mode: 'HEALTH', + tls: true, + service: 'auth.AuthService', + }, + assertions: [ + GrpcAssertionBuilder.healthCheckStatus().equals(1), // 1 = SERVING + GrpcAssertionBuilder.responseTime().lessThan(500), + ], + }, +}) +``` + + + + +```ts +import { Frequency, GrpcAssertionBuilder, GrpcMonitor } from "checkly/constructs" + +new GrpcMonitor('order-get-order', { + name: 'Order Service GetOrder', + frequency: Frequency.EVERY_5M, + maxResponseTime: 5000, + degradedResponseTime: 2000, + request: { + url: 'orders.example.com', + port: 443, + grpcConfig: { + mode: 'BEHAVIOR', + tls: true, + serviceDefinition: 'PROTO_FILE', + protoContent: `syntax = "proto3"; +package orders; +service OrderService { rpc GetOrder (GetOrderRequest) returns (Order); } +message GetOrderRequest { string order_id = 1; } +message Order { string order_id = 1; string status = 2; }`, + method: 'orders.OrderService/GetOrder', + message: '{"orderId": "probe-001"}', + }, + assertions: [ + GrpcAssertionBuilder.statusCode().equals(0), + GrpcAssertionBuilder.responseMessage('$.status').notEmpty(), + ], + }, +}) +``` + + + + +```ts +import { Frequency, GrpcAssertionBuilder, GrpcMonitor } from "checkly/constructs" + +new GrpcMonitor('secure-grpc', { + name: 'Secure gRPC Service', + frequency: Frequency.EVERY_2M, + request: { + url: 'secure-grpc.example.com', + port: 443, + grpcConfig: { + mode: 'HEALTH', + tls: true, + metadata: [ + { key: 'authorization', value: 'Bearer {{GRPC_API_TOKEN}}' }, + { key: 'x-tenant-id', value: '{{TENANT_ID}}' }, + ], + }, + assertions: [ + GrpcAssertionBuilder.healthCheckStatus().equals(1), // 1 = SERVING + ], + }, +}) +``` + + + diff --git a/detect/uptime-monitoring/grpc-monitors/configuration.mdx b/detect/uptime-monitoring/grpc-monitors/configuration.mdx new file mode 100644 index 00000000..298929fc --- /dev/null +++ b/detect/uptime-monitoring/grpc-monitors/configuration.mdx @@ -0,0 +1,83 @@ +--- +title: 'gRPC Monitor Configuration' +description: 'Configure your gRPC monitor to verify service availability, health, and response correctness.' +sidebarTitle: 'Configuration' +--- + + +To configure a gRPC monitor using code, learn more about the [gRPC Monitor Construct](/constructs/grpc-monitor). + + +### Basic Setup + +Configure your gRPC monitor by specifying the target service and monitoring mode: + +* **Host**: The hostname or IP address of the gRPC server (e.g. `grpc.example.com` or `10.0.0.1`). Do not include a scheme or port. +* **Port**: The port the gRPC server is listening on (e.g. `50051`) +* **IP family**: Choose between IPv4 (default) or IPv6 +* **TLS**: Whether to use TLS encryption for the connection (default: enabled). Disable for plaintext connections. +* **Skip SSL verification**: Skip TLS certificate validation. Useful for servers with self-signed certificates in non-production environments. + +### Monitoring Mode + +Choose between two monitoring modes: + +#### BEHAVIOR Mode (default) + +Invokes a unary gRPC method and asserts on the response. Requires: + +* **Method**: The fully-qualified method name in `package.Service/Method` format (e.g. `mypackage.MyService/GetUser`) +* **Service definition**: How the method schema is resolved: + * **Reflection** (default): The runner discovers the method using gRPC server reflection. Requires reflection to be enabled on the server. + * **Proto file**: Provide the `.proto` file content inline. The runner compiles it locally — no server reflection required. +* **Request message**: Optional JSON-encoded payload sent as the gRPC request body +* **Metadata**: Optional key/value pairs sent as gRPC request headers (e.g. `authorization: Bearer {{MY_TOKEN}}`) + +#### HEALTH Mode + +Calls `grpc.health.v1.Health/Check` using the standard gRPC health-check protocol. Useful for monitoring overall server health without invoking a specific application method. + +* **Service** (optional): The name of the service to check. Leave empty to query overall server health. + +### Assertions + +Use assertions to validate gRPC responses and ensure your service meets availability and performance expectations. + +You can create assertions based on: + +* **Response time**: Assert that the total gRPC call duration (including DNS and connection) is within a threshold +* **gRPC status code**: Assert on the numeric gRPC status code. Common values: `0` (OK), `1` (CANCELLED), `2` (UNKNOWN), `4` (DEADLINE_EXCEEDED), `14` (UNAVAILABLE). See the [gRPC status codes reference](https://grpc.github.io/grpc/core/md_doc_statuscodes.html). +* **Health check status** (HEALTH mode): Assert on the health status string. Valid values: `SERVING`, `NOT_SERVING`, `UNKNOWN`, `SERVICE_UNKNOWN` +* **Response message** (BEHAVIOR mode): Assert against the JSON response body using a JSON path expression. For example: + * `$.status` → assert on a top-level field + * `$.result.id` → assert on a nested field + * Learn more about JSON path assertions: [JSON responses with JSON path](/detect/assertions/#json-responses-with-json-path) +* **Response metadata**: Assert against response metadata (header) values returned by the server, identified by key + +For more details, see our documentation on [Assertions](/detect/assertions). + +### Response Time Limits + +Set performance thresholds for your gRPC service: + +* **Degraded After**: Time threshold (in milliseconds) after which the check is marked as degraded but not failed. Use for early performance warnings without triggering failure alerts. +* **Failed After**: Time threshold after which the check is marked as failed. Use for hard latency limits that should trigger alerts. + +The maximum allowed threshold is 180,000 ms (3 minutes), matching the maximum call timeout. + +### Frequency + +Set how often the monitor runs (every 10 seconds to 24 hours). + +### Scheduling & Locations + +* **Strategy**: Choose between round-robin or parallel execution. Learn more about [scheduling strategies](/concepts/scheduling) +* **Locations**: Select [public](/concepts/locations/#public-locations) or [private](/platform/private-locations/overview) locations to run the monitor from + +### Additional Settings + +* **Name**: Give your monitor a clear name to identify it in dashboards and alerts +* **Description**: Add context about what this monitor does and why it matters. Supports markdown, max 500 characters. When a failure occurs, [Rocky AI](/ai/rocky-ai) uses the description to provide more accurate [root cause and user impact analysis](/resolve/ai-root-cause-analysis/overview) +* **Tags**: Use tags to organize monitors across [dashboards](/communicate/dashboards/overview/) and [maintenance windows](/communicate/maintenance-windows/overview) +* **Retries**: Define how failed runs should be retried. See [retry strategies](/communicate/alerts/retries) +* **Alerting**: Configure your [alert settings](/communicate/alerts/configuration), [alert channels](/communicate/alerts/channels), or set up [webhooks](/integrations/alerts/webhooks) for custom integrations diff --git a/detect/uptime-monitoring/grpc-monitors/overview.mdx b/detect/uptime-monitoring/grpc-monitors/overview.mdx new file mode 100644 index 00000000..f8231427 --- /dev/null +++ b/detect/uptime-monitoring/grpc-monitors/overview.mdx @@ -0,0 +1,90 @@ +--- +title: 'gRPC Monitors Overview' +description: 'Monitor gRPC service availability, health, and response times.' +sidebarTitle: Overview +--- + + +**Monitoring as Code**: Learn more about the [gRPC Monitor Construct](/constructs/grpc-monitor). + + +## What are gRPC Monitors? + +gRPC monitors verify that your gRPC services are reachable, healthy, and responding correctly. They support two monitoring modes: + +* **BEHAVIOR mode** — Invoke any unary gRPC method and assert on the response. Ideal for testing specific service endpoints. The service definition is discovered via server reflection or an inline `.proto` file. +* **HEALTH mode** — Query the standard [gRPC health check protocol](https://github.com/grpc/grpc/blob/master/doc/health-checking.md) (`grpc.health.v1.Health/Check`). Ideal for checking overall server health without needing a specific method to call. + +Typical use cases include: + +* Verifying a microservice's gRPC API responds correctly to a method call +* Monitoring gRPC health check endpoints for backend services +* Checking that a service starts serving requests after a deployment +* Asserting that gRPC status codes and response payloads meet expectations + +## How gRPC Monitors Work + +On each run, Checkly: + +1. Resolves the hostname to an IP address (DNS timing is captured separately) +2. Opens a gRPC connection — optionally with TLS — to the target host and port +3. Attaches any configured metadata (request headers) to the outgoing call +4. Executes the gRPC call: + * **BEHAVIOR mode**: Discovers the method (via reflection or `.proto`), sends the JSON request message, and captures the response + * **HEALTH mode**: Calls `Check` on `grpc.health.v1.Health`, optionally scoped to a specific service name +5. Evaluates your configured assertions against the response (status code, health status, response message, metadata, or response time) + +## gRPC Monitor Results + +Select a specific check run to inspect its results: + +* **Summary**: Shows the target host and port, monitor state, gRPC status code, and total run duration + +* **Error details**: If the run fails, you'll see the error message and gRPC status code to help diagnose what went wrong + +* **Request data**: The method invoked, metadata sent, and request message (BEHAVIOR mode) + +* **Response data**: The gRPC status code and message, health status (HEALTH mode), response message body (BEHAVIOR mode), and response metadata returned by the server + +* **Timing phases**: For each run, Checkly captures: + * DNS: Time to resolve the hostname to an IP address + * Connect: Time to establish the gRPC connection and complete the call + * Total: Full end-to-end duration including DNS + +Learn more in our documentation on [Results](/concepts/results). + +## Troubleshooting + + +**Symptom**: The monitor fails with an error mentioning server reflection. + +**Root cause**: The gRPC server does not have the server reflection service enabled. Many production gRPC servers disable reflection for security reasons. + +**How to fix**: +* Switch `serviceDefinition` to `PROTO_FILE` and provide the `.proto` file content inline in the monitor configuration +* If you control the server, enable gRPC server reflection (e.g. `grpc_reflection_v1alpha` in Go or the equivalent in your framework) + + + +**Symptom**: The monitor fails with a TLS handshake or certificate validation error. + +**How to fix**: +* Ensure the server's TLS certificate is valid and signed by a trusted CA +* If the server uses a self-signed certificate in a non-production environment, enable **Skip SSL verification** in the request configuration (`skipSSL: true` in the CLI construct) +* Verify the hostname matches the certificate's Subject Alternative Names (SANs) + + + +**Symptom**: The health check call succeeds but the returned status is not `SERVING`. + +**Root cause**: The gRPC server's health service is reporting that the requested service (or the server overall) is not ready. + +**How to fix**: +* Check server logs for startup or dependency issues +* If querying a specific service by name, verify the name matches what the server registers with `grpc_health_v1` +* Leave the **Service** field empty to query overall server health instead of a named service + + + +gRPC monitors are supported on private locations. Ensure the Checkly Agent can reach the gRPC server's hostname and port from within your network. No special capabilities beyond network access are required. + diff --git a/detect/uptime-monitoring/overview.mdx b/detect/uptime-monitoring/overview.mdx index d09ba374..41d2a8cb 100644 --- a/detect/uptime-monitoring/overview.mdx +++ b/detect/uptime-monitoring/overview.mdx @@ -41,6 +41,11 @@ Choose the Uptime Monitor that best fits your monitoring needs: + + Monitor gRPC service availability, health, and response correctness. + + + Detect when cron jobs or scheduled tasks fail to run. diff --git a/docs.json b/docs.json index abfd76d5..0404c038 100644 --- a/docs.json +++ b/docs.json @@ -167,6 +167,13 @@ "detect/uptime-monitoring/icmp-monitors/configuration" ] }, + { + "group": "gRPC Monitors", + "pages": [ + "detect/uptime-monitoring/grpc-monitors/overview", + "detect/uptime-monitoring/grpc-monitors/configuration" + ] + }, { "group": "Heartbeat Monitors", "pages": [ @@ -481,6 +488,7 @@ "constructs/dns-monitor", "constructs/tcp-monitor", "constructs/icmp-monitor", + "constructs/grpc-monitor", "constructs/heartbeat-monitor", "constructs/agentic-check", "constructs/api-check",