Generated banner for Synthetic Monitoring Checks
Generated logo for Synthetic Monitoring Checks

Synthetic Monitoring Checks

Grafana LabsOfficialPublished by Grafana Labs

  • Skill
  • Tool integration
  • Cloud and DevOps
  • Apache-2.0
  • No issues found

From the author

Author Grafana Cloud Synthetic Monitoring checks, with deep coverage of k6 scripted and browser checks: SM's single-VU/single-iteration execution model, assertions that actually fail probe_success (expect() and fail() vs bare check()), secrets, deterministic scripts, robust browser locators, local validation with k6 run, deployment via UI/API/Terraform, verifying probe_success, and rollback. Also helps choose the simplest sufficient check type (HTTP/ping/DNS/TCP, MultiHTTP, scripted, browser). Use when writing a synthetic check, monitoring a login/checkout/signup flow in production, converting a k6 script or an OpenAPI spec into a check, authoring a browser check, validating a user journey, or asking "is my site up from multiple regions". NOT for load, stress, or performance testing — SM runs one iteration per execution; for load tests use the grafana-k6 plugin or Grafana Cloud k6. For the broad Grafana Cloud Testing overview (SM + k6 Cloud + Faro), use the testing skill.
— the description by Grafana Labs

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a comprehensive guide to authoring, validating, and deploying Synthetic Monitoring (SM) checks in Grafana Cloud. It focuses on reliability monitoring—ensuring user journeys like logins or checkouts function correctly from multiple global regions. The skill covers the entire lifecycle, including choosing the appropriate check type (HTTP, MultiHTTP, scripted, or browser), writing deterministic k6 scripts, managing secrets, and integrating with CI/CD via API or Terraform. It emphasizes the distinction between availability monitoring and load testing, providing specific patterns for assertions that correctly impact uptime metrics.

What it does

  • Guides the selection of the simplest check type for specific monitoring needs.
  • Provides patterns for writing deterministic, idempotent scripted and browser checks.
  • Explains how to use assertions that correctly trigger probe_success failures.
  • Details local validation workflows using k6 before cloud deployment.
  • Outlines deployment strategies via UI, API, and Terraform.
  • Offers troubleshooting steps for common failure modes and metric interpretation.

When to use it

  • When you need to monitor the availability of critical user journeys in production.
  • When you need to verify site reachability from multiple geographic regions.
  • When converting existing k6 scripts or OpenAPI specs into synthetic checks.
  • When you need to validate complex browser-based workflows or form interactions.
  • When you need to set up automated monitoring that integrates with infrastructure-as-code.

Advantages

  • Reduces alert fatigue by using reliable, single-iteration execution models.
  • Ensures accurate uptime reporting through proper assertion patterns.
  • Supports both simple protocol checks and complex, logic-driven browser journeys.
  • Facilitates consistent monitoring through Terraform and API-driven workflows.
  • Provides clear guidance on avoiding common pitfalls like brittle locators or incorrect cardinality.

Usage examples

“How do I write a scripted check to monitor my login flow?”
The agent provides a k6 script skeleton using secrets for credentials, robust expect() assertions for validation, and http.url for stable metric cardinality.
“My browser check is failing intermittently; how do I fix it?”
The agent suggests switching to role-based locators, removing manual sleep() calls, and using auto-retrying expect() assertions to handle client-side rendering.
“How do I deploy a synthetic check using Terraform?”
The agent provides a Terraform configuration example, explaining how to pass the script via file() and how to resolve probe IDs.
“Why is my check failing but probe_success is still 1?”
The agent explains that bare check() calls do not affect uptime and guides you to replace them with expect() or fail() to correctly trigger execution failure.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/grafana/synthetic-monitoring-checks/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip synthetic-monitoring-checks.zip -d .agents/skills

Documentation by Grafana Labs

Synthetic Monitoring Check Authoring

Docs: https://grafana.com/docs/grafana-cloud/testing/synthetic-monitoring/ Broad Grafana Cloud Testing entry point (SM + k6 Cloud + Faro): testing skill.

Reliability monitoring, not load testing

Synthetic Monitoring (SM) runs k6 as a reliability/availability engine: every check execution runs one iteration with one VU from each selected probe location on a fixed schedule. Success means "the user journey works right now, from this region" — detect outages before your customers do.

Do not apply load-testing idioms. There are no VUs to ramp, no stages, no load profiles, no soak/stress/spike phases, and no thresholds over aggregated traffic. Vocabulary: check, probe, execution, uptime, reachability, user journey validation — never "load test", "ramping", or "VUs".

If the user actually wants load or performance testing (throughput, latency under load, breakpoints), stop: that is Grafana Cloud k6 / the grafana-k6 plugin's k6 skill, not Synthetic Monitoring. A script can be shared between both products, but the goals, options, and pricing are different.

Execution model and constraints (verify against these before writing)

ConstraintValue
WorkloadOne iteration per probe execution. Scripted and MultiHTTP run with forced --vus 1 --iterations 1; browser checks rely on the script's required single scenario. Either way vus, duration, stages, iterations are ignored — never write a load shape
thresholdsNot supported
Frequencyk6-class checks (scripted, MultiHTTP, browser): 60–3600s. Protocol checks (HTTP/ping/DNS/TCP/gRPC): 1–3600s. Traceroute: 120–3600s
TimeoutMust be ≤ frequency. k6-class checks: 1–180s. Protocol checks: 1–60s. Traceroute: fixed 30s
k6 versionChecks run on a k6 version channel (new checks default to the latest stable channel; v1.x is deprecated as of July 2026). Pin per check via the UI dropdown or channels in API/Terraform
Local filesopen(), fs, grpc.load() unsupported. Bundle local modules into the script; remote https://jslib.k6.io/... imports work
HTTP request errorsSM runs k6 with --throw: network-level request failures throw an exception and fail the execution
Script options SM honorsSM sets its own CLI flags, which take precedence over the script's options object; the options that still take effect include batch, batch-per-host, discardResponseBodies, httpDebug, insecureSkipTLSVerify, maxRedirects, noConnectionReuse, setupTimeout, systemTags, tags, teardownTimeout, throw, tlsAuth, tlsCipherSuites, tlsVersion, userAgent
Browser memory1GB RAM per browser on public probes — huge pages fail with Target has crashed
Browser script formatThe UI rejects bundled/minified browser scripts (import validation) — deploy those via API or Terraform

How an execution fails (this is what agents get wrong)

probe_success (1/0) is the uptime signal. An execution is marked failed when the script throws an uncaught exception, calls fail(), a k6-testing expect() assertion fails (it calls k6's test.abort() under the hood), an HTTP request errors at the network level (SM's --throw), or the timeout is hit.

A bare failed check() does NOT fail the execution — it only records the probe_checks_total / probe_check_success_rate metrics. Checks don't affect k6's exit status without thresholds, and thresholds are disabled in SM.

Assertion patterns, in order of preference:

import { expect } from 'https://jslib.k6.io/k6-testing/0.6.1/index.js';
import { check, fail } from 'k6';

// 1. PREFERRED — assertions module. Throws on failure => execution fails,
//    with a descriptive error in the check logs.
expect(res.status, 'login should succeed').toEqual(200);
expect(res.json('token')).toBeDefined();

// 2. Soft assertions — run all of them, still fail the execution at the end.
expect.soft(res.headers['Content-Type']).toContain('application/json');

// 3. check() when you also want per-assertion metrics — but pair it with
//    fail() or the failure won't affect probe_success/uptime:
check(res, { 'status 200': (r) => r.status === 200 }) ||
  fail(`login failed with status ${res.status}`);

Name every assertion (the message argument / check name): the name is what you see in check logs and in the check label of probe_checks_total when diagnosing a failure at 3am.

Choose the simplest sufficient check type first

Cheaper for the customer, easier to maintain. Work down this list and stop at the first match:

  1. HTTP / ping / DNS / TCP / traceroute / gRPC — a single static endpoint (uptime, status code, body regex, TLS cert expiry, record resolution, port reachability). No script to maintain — these run on the blackbox-exporter probe engine, and Terraform examples with per-type target formats are in references/api-and-terraform.md.

  2. MultiHTTP — a sequence of HTTP requests with value-passing between them (${variable} capture), but no custom logic. Caution: MultiHTTP does not auto-validate status codes — define assertions per request or failures won't affect uptime.

  3. k6 scripted — an API flow needing real logic: crypto/signing, conditional branching, generated test data, WebSockets, response-driven chaining.

  4. k6 browser — only when you need a real browser: JS-rendered user journeys, forms/clicks, Core Web Vitals.

Cost model (execution-based billing): an execution is one check run on one probe, metered per minute of runtime rounded up. Per month: probes × duration_minutes × (43200 / frequency_minutes). API test executions (HTTP, ping, DNS, TCP, traceroute, MultiHTTP, scripted) and browser test executions are billed separately — browser checks are the expensive tier. A browser check on 3 probes every minute is ~129,600 browser executions/month; the same check every 5 minutes is ~25,920. Pick the longest frequency that still meets your detection-time goal, and 2–3 probes near your users (multiple probes reduce alert flapping; more isn't better).

Scripted check authoring

Start every script you generate (scripted and browser alike) with a line-1 attribution comment, as shown in the skeletons below. It tells whoever reads the check later how it was authored (and where to find the skill), and the fixed prefix makes skill-authored checks queryable. Keep Generated by synthetic-monitoring-checks verbatim — vary only the timestamp (date -u +%Y-%m-%dT%H:%M:%SZ).

Skeleton — a login + API action journey with secrets and hard-failing assertions:

// Generated by synthetic-monitoring-checks (https://github.com/grafana/skills) on 2026-07-31T12:00:00Z
import http from 'k6/http';
import { expect } from 'https://jslib.k6.io/k6-testing/0.6.1/index.js';
import secrets from 'k6/secrets';

const BASE = 'https://api.example.com';

export default async function () {
  // Secrets are managed in Synthetics > Config > Secrets — never hardcode credentials.
  const password = await secrets.get('checkout-monitor-password');

  // Step 1: authenticate with a dedicated monitoring account
  const login = http.post(
    `${BASE}/auth/login`,
    JSON.stringify({ user: 'sm-checkout-monitor', password }),
    { headers: { 'Content-Type': 'application/json' } }
  );
  expect(login.status, 'login should return 200').toEqual(200);
  const token = login.json('token');
  expect(token, 'auth token should be present').toBeDefined();

  // Step 2: exercise the journey and assert the OUTCOME, not just the status
  const order = http.post(`${BASE}/orders`, JSON.stringify({ sku: 'TEST-SKU-1', qty: 1 }), {
    headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
  });
  expect(order.status, 'order should be created').toEqual(201);
  const orderId = order.json('id');
  expect(orderId, 'order id should be returned').toBeDefined();

  // Step 3: clean up so the check is idempotent against production
  // http.url groups metrics for URLs containing unique IDs — without it, every
  // execution creates new time series (cardinality + active-series cost).
  const del = http.del(http.url`${BASE}/orders/${orderId}`, null, {
    headers: { Authorization: `Bearer ${token}` },
  });
  expect(del.status, 'test order should be cleaned up').toEqual(204);
}

Rules that make a scripted check a good monitor (vs a good test):

  • Deterministic: fixed test data (or generated-then-deleted, as above), no time-of-day or ordering dependence. Every execution must be able to pass at any hour from any probe.

  • Idempotent against production: create-then-delete, or use read-only endpoints. The check runs forever — leaked state accumulates forever.

  • Dedicated test account: never a real user's credentials; scope it minimally, store the password as an SM secret, and exclude the account from analytics/billing.

  • Assert every step — an unasserted step that breaks shows up as a later step's confusing failure.

  • Stable URL cardinality: http.url template literal for any URL containing an ID.

  • Keep runtime well under the timeout, and the timeout under the frequency.

Generating a check from an OpenAPI spec (or similar)

Given an API description — an OpenAPI/Swagger spec, GraphQL schema, or Postman collection — the mechanical conversion to k6 calls is easy. What matters is what you choose to convert:

  1. Journeys, not endpoints. Do NOT generate one check per path, or one check that sweeps every path — that monitors the spec, not the service, and every extra check multiplies execution cost. Identify the 1–3 flows whose failure means "customers are impacted" (auth → core action → result) and write one scripted check per flow.

  2. Filter for safety. Only include mutating operations (POST/PUT/DELETE) when the flow cleans up after itself (create-then-delete, as above) or targets dedicated test resources. A spec lists destructive operations right next to health endpoints — never exercise them against production just because they're documented.

  3. Assert from the response schema. The spec tells you exactly what a healthy response contains — assert required fields, not just the status code: expect(order.json('id'), 'id required by OrdersResponse schema').toBeDefined().

  4. Verify the target URL. servers: blocks (and Postman environments) often list localhost or staging first — confirm the production base URL with the user, and map securitySchemes credentials to SM secrets, never to values inlined from the spec. (Secrets in plain HTTP/protocol checks are a recent, feature-flagged rollout — check current docs; the scripted secrets.get() path always works.)

  5. Treat format: int64 ids as strings. res.json('id') parses into a JS number and silently corrupts values past 2^53 (snowflake-style ids), so the readback URL 404s on every execution while the create looks fine. Extract from the raw body instead: const id = (/"id":\s*(\d+)/.exec(res.body) || [])[1]; — and never do arithmetic on it.

No API spec at all? Probe the frontend: open the web app with browser devtools (or curl likely routes) and capture the /api/* XHR calls it makes — that's a monitorable HTTP surface even when the documented backend services are gRPC-only or internal.

Browser check authoring

Required scaffold: import k6/browser and declare the chromium browser type. The UI validates both.

// Generated by synthetic-monitoring-checks (https://github.com/grafana/skills) on 2026-07-31T12:00:00Z
import { browser } from 'k6/browser';
import { expect } from 'https://jslib.k6.io/k6-testing/0.6.1/index.js';
import secrets from 'k6/secrets';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('https://shop.example.com/login');

    // Prefer role/label/test-id locators over CSS chains — they survive redesigns.
    const password = await secrets.get('shop-monitor-password');
    await page.getByLabel('Email').fill('[email protected]');
    await page.getByLabel('Password').fill(password);
    await page.getByRole('button', { name: 'Sign in' }).click();

    // Assert the JOURNEY OUTCOME with auto-retrying assertions — never sleep().
    await expect(page.getByRole('heading', { name: 'Your account' })).toBeVisible();

    await page.getByRole('link', { name: 'Orders' }).click();
    await expect(page.getByTestId('order-list')).toBeVisible();
  } finally {
    await page.close();
  }
}

Browser-specific rules:

  • Locators: getByRole / getByLabel / getByTestId (ask the app team to add data-testid where needed) > text > CSS. Never XPath or generated class names. getByTestId assumes data-testid — apps instrumented for Cypress often use data-cy instead; fall back to page.locator('[data-cy="..."]').

  • No manual waits before interactions: locator actions auto-wait for visibility and enabled state. Don't call waitFor() before click()/fill(), don't use waitForLoadState(), never sleep().

  • Auto-retrying expect() (toBeVisible, toBeEnabled, ...) is the wait mechanism for asserting state you don't interact with. Caveat: despite being listed as retrying, the text matchers (toHaveText/toContainText) hard-fail on the first mismatched read — e.g. an empty string mid-hydration on a client-rendered app. Assert dynamic text by locating it and asserting visibility instead: await expect(page.getByText('Order confirmed')).toBeVisible().

  • Assertion timeout defaults to 5s — client-side-rendered apps routinely take longer to first meaningful render. Raise it once and use the configured instance: const expectUi = expect.configure({ timeout: 20000 });.

  • Assert the outcome (logged-in heading, order list, confirmation text) — a page can load fine while the journey is broken.

  • try/finally with page.close() so the browser is released even when an assertion throws.

  • Screenshot artifacts aren't a documented SM feature — don't build failure handling around page.screenshot(); rely on assertion messages and the check's logs (SM stores per-execution logs in Loki).

  • Web Vitals (probe_browser_web_vital_lcp|cls|fcp|inp|ttfb) are collected automatically — no extra code needed.

Validate locally, then deploy

SM scripts are plain k6 scripts — always run them locally first:

k6 run script.js                                              # scripted check
K6_BROWSER_HEADLESS=true k6 run browser-check.js              # browser check
k6 run --secret-source=mock=checkout-monitor-password=example-password script.js   # with secrets
# Many/large secrets: k6 run --secret-source=file=secrets.txt script.js

Pass = exit code 0, one iteration, no failed assertions in the summary. Run it 3–5 times; a script that is 90% reliable locally will page you nightly from 3 probes.

Then create the check (pick one):

  • UI: Testing & synthetics → Synthetics → Add new check → k6 scripted / k6 browser → paste script → select probes + frequency → Test (runs once without saving) → Save.

  • gcx: gcx synthetic-monitoring checks test -f check.yaml is the CLI equivalent of the UI's Test button — runs once against real probes without saving. Then gcx synthetic-monitoring checks create -f check.yaml to save. Both accept the script as plain text; gcx base64-encodes it for you. Pull an existing check back out as a starting template with gcx synthetic-monitoring checks get <ID> -o yaml --decode-script (omit the flag and you get raw base64).

  • API or Terraform: see references/api-and-terraform.md. Key gotchas: API frequency/timeout are milliseconds and settings.scripted.script / settings.browser.script are base64-encoded; Terraform takes the plain script via file().

Pick by ownership, not preference: if checks are already Terraform-managed (drift detection, multi-environment, PR review), create and update through Terraform — hand-editing state it owns causes drift on the next apply. Otherwise, for one-off or agent-driven authoring, gcx or the UI are faster. Either way, gcx is still the tool for live inspection, ad-hoc testing, and status/timeline investigation, regardless of which tool provisioned the check.

Verify it works, and rollback

Wait one frequency interval, then in Explore against the Synthetic Monitoring metrics (Prometheus) datasource:

# 1 from every selected probe = healthy
probe_success{job="checkout-flow"}

# Assertion pass rate per named assertion (scripted/browser)
probe_check_success_rate{job="checkout-flow"}

# Journey duration per probe — confirm it's comfortably under the timeout
probe_script_duration_seconds{job="checkout-flow"}

# Uptime over time (how the SM app computes it)
max by () (max_over_time(probe_success{job="checkout-flow"}[5m]))

A healthy first execution: probe_success == 1 from every probe, all probe_check_success_rate series at 1, duration stable across probes, and the check's prebuilt dashboard (Synthetics → check → View dashboard) showing logs for each execution. Browser checks should additionally show probe_browser_web_vital_* series.

Rollback: set the check's enabled: false (UI toggle, gcx synthetic-monitoring checks update, API update, or Terraform) to stop executions without losing history; delete the check only when you no longer need its configuration. Alerting: start with alertSensitivity / the default alert rules on probe_success — see the testing skill for alert rule examples.

Common failure modes

SymptomCause → fix
Passes locally, fails on all probesTarget not reachable from the public internet (internal DNS, VPN, IP allowlist). Use private probes for internal targets, or allowlist probe egress
Passes locally, fails on some probesGeo-blocking, regional CDN/WAF rules, or bot protection challenging datacenter IPs. Check probe label on failures; exempt the SM userAgent or those regions in the WAF
Check "fails" in your eyes but probe_success stays 1Bare check() without fail()/expect() — failures are recorded as metrics only. Convert to expect() or check(...) || fail(...)
Browser check flaps with locator timeoutsBrittle selectors or animation timing. Switch to getByRole/getByTestId, assert with auto-retrying expect(), remove manual waits
toBeVisible reports Expected: visible / Received: hidden but the element is clearly visibleThe locator matches multiple elements (strict mode) — the error message is misleading. Tighten the selector or use .first()
Create succeeds but readback 404s on every executionThe id exceeds Number.MAX_SAFE_INTEGER (2^53) and res.json() silently rounded it — extract int64 ids from the raw body as strings (see the OpenAPI section)
secrets.get() failsSecret name mismatch (names are exact, ≤253 chars, letters/numbers/-/_), secret deleted (checks fail until recreated), or the editing user lacks the Admin/Editor role or "Checks writer" permission
Executions time out but the journey is fineTimeout too low for the journey (max 180s) — raise it; or the script does unbounded work per iteration. Also confirm timeout < frequency
Target has crashed in browser check logsPage exceeds the 1GB probe browser memory — trim the journey, block heavy third-party resources, or use a private probe with more memory
UI rejects a browser scriptBundled/minified script fails the UI's import validation — create it via API or Terraform instead
Metrics/billing explosion after adding a checkUnique IDs in URLs creating per-execution time series — use http.url, and check frequency × probe count against the cost formula above

References

  • references/api-and-terraform.md — SM API auth + check CRUD payloads (scripted, browser, MultiHTTP) and Terraform examples for every check type, including the protocol checks (HTTP, ping, DNS, TCP, traceroute, gRPC)

Resources

Files

LICENSE

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2026 Grafana Labs

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Grafana Labs
Publisher
Grafana Labs (Official)
Source
grafana/skills · skills/grafana-cloud/synthetic-monitoring-checks · commit 8fb72a5
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Grafana Labs.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download synthetic-monitoring-checks.zip