published on Saturday, Sep 19, 2026 by Pulumi
published on Saturday, Sep 19, 2026 by Pulumi
Use this resource to create and manage New Relic Notebooks.
Notebooks are shareable documents that combine live NRQL queries, visualizations, and Markdown narrative in a single view - the kind of thing you’d reach for when investigating an incident, reviewing weekly service health, or building an onboarding guide for a new team member. This resource manages both the notebook title and its full body content using the same declarative UI format the New Relic platform uses natively.
NOTE: The notebook body must be a valid declarative UI document. See Content Format and Schema for the required envelope structure and supported visualization types.
See Examples at the bottom of this page for ready-to-use notebook templates.
Example Usage
The recommended approach is to supply the notebook body as a raw JSON string. You can use a file() reference for larger notebooks, or an inline heredoc for smaller ones.
import * as pulumi from "@pulumi/pulumi";
import * as newrelic from "@pulumi/newrelic";
const incidentRunbook = new newrelic.Notebook("incident_runbook", {
title: "Production API Incident - Investigation",
content: `{
\\"type\\": \\"declarative\\",
\\"version\\": 1,
\\"content\\": [
{
\\"type\\": \\"container\\",
\\"props\\": { \\"layout\\": \\"stack\\" },
\\"content\\": [
{
\\"type\\": \\"widget\\",
\\"content\\": {
\\"type\\": \\"visualization\\",
\\"id\\": \\"viz.markdown\\",
\\"props\\": {
\\"text\\": \\"# Production API Incident\\
\\
**Status**: Resolved\\
**Impact**: ~15% of API requests failed\\
\\
Use this notebook to walk through what happened and track action items.\\"
}
}
},
{
\\"type\\": \\"widget\\",
\\"props\\": { \\"title\\": \\"Peak error rate\\" },
\\"content\\": {
\\"type\\": \\"visualization\\",
\\"id\\": \\"viz.billboard\\",
\\"props\\": {
\\"nrqlQueries\\": [
{
\\"accountIds\\": [1234567],
\\"query\\": \\"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\\"
}
],
\\"thresholdsWithSeriesOverrides\\": {
\\"thresholds\\": [
{ \\"to\\": 1, \\"severity\\": \\"success\\" },
{ \\"from\\": 1, \\"to\\": 5, \\"severity\\": \\"warning\\" },
{ \\"from\\": 5, \\"severity\\": \\"critical\\" }
]
}
}
}
},
{
\\"type\\": \\"widget\\",
\\"props\\": { \\"title\\": \\"Error rate over time\\" },
\\"content\\": {
\\"type\\": \\"visualization\\",
\\"id\\": \\"viz.line\\",
\\"props\\": {
\\"nrqlQueries\\": [
{
\\"accountIds\\": [1234567],
\\"query\\": \\"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\\"
}
],
\\"legend\\": { \\"enabled\\": true },
\\"yAxisLeft\\": { \\"zero\\": true },
\\"nullValues\\": { \\"nullValue\\": \\"zero\\" }
}
}
}
]
}
]
}
`,
});
import pulumi
import pulumi_newrelic as newrelic
incident_runbook = newrelic.Notebook("incident_runbook",
title="Production API Incident - Investigation",
content="""{
\"type\": \"declarative\",
\"version\": 1,
\"content\": [
{
\"type\": \"container\",
\"props\": { \"layout\": \"stack\" },
\"content\": [
{
\"type\": \"widget\",
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.markdown\",
\"props\": {
\"text\": \"# Production API Incident\
\
**Status**: Resolved\
**Impact**: ~15% of API requests failed\
\
Use this notebook to walk through what happened and track action items.\"
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Peak error rate\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.billboard\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\"
}
],
\"thresholdsWithSeriesOverrides\": {
\"thresholds\": [
{ \"to\": 1, \"severity\": \"success\" },
{ \"from\": 1, \"to\": 5, \"severity\": \"warning\" },
{ \"from\": 5, \"severity\": \"critical\" }
]
}
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Error rate over time\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.line\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\"
}
],
\"legend\": { \"enabled\": true },
\"yAxisLeft\": { \"zero\": true },
\"nullValues\": { \"nullValue\": \"zero\" }
}
}
}
]
}
]
}
""")
package main
import (
"github.com/pulumi/pulumi-newrelic/sdk/v5/go/newrelic"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := newrelic.NewNotebook(ctx, "incident_runbook", &newrelic.NotebookArgs{
Title: pulumi.String("Production API Incident - Investigation"),
Content: pulumi.String(`{
\"type\": \"declarative\",
\"version\": 1,
\"content\": [
{
\"type\": \"container\",
\"props\": { \"layout\": \"stack\" },
\"content\": [
{
\"type\": \"widget\",
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.markdown\",
\"props\": {
\"text\": \"# Production API Incident\
\
**Status**: Resolved\
**Impact**: ~15% of API requests failed\
\
Use this notebook to walk through what happened and track action items.\"
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Peak error rate\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.billboard\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\"
}
],
\"thresholdsWithSeriesOverrides\": {
\"thresholds\": [
{ \"to\": 1, \"severity\": \"success\" },
{ \"from\": 1, \"to\": 5, \"severity\": \"warning\" },
{ \"from\": 5, \"severity\": \"critical\" }
]
}
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Error rate over time\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.line\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\"
}
],
\"legend\": { \"enabled\": true },
\"yAxisLeft\": { \"zero\": true },
\"nullValues\": { \"nullValue\": \"zero\" }
}
}
}
]
}
]
}
`),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using NewRelic = Pulumi.NewRelic;
return await Deployment.RunAsync(() =>
{
var incidentRunbook = new NewRelic.Notebook("incident_runbook", new()
{
Title = "Production API Incident - Investigation",
Content = @"{
\""type\"": \""declarative\"",
\""version\"": 1,
\""content\"": [
{
\""type\"": \""container\"",
\""props\"": { \""layout\"": \""stack\"" },
\""content\"": [
{
\""type\"": \""widget\"",
\""content\"": {
\""type\"": \""visualization\"",
\""id\"": \""viz.markdown\"",
\""props\"": {
\""text\"": \""# Production API Incident\
\
**Status**: Resolved\
**Impact**: ~15% of API requests failed\
\
Use this notebook to walk through what happened and track action items.\""
}
}
},
{
\""type\"": \""widget\"",
\""props\"": { \""title\"": \""Peak error rate\"" },
\""content\"": {
\""type\"": \""visualization\"",
\""id\"": \""viz.billboard\"",
\""props\"": {
\""nrqlQueries\"": [
{
\""accountIds\"": [1234567],
\""query\"": \""SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\""
}
],
\""thresholdsWithSeriesOverrides\"": {
\""thresholds\"": [
{ \""to\"": 1, \""severity\"": \""success\"" },
{ \""from\"": 1, \""to\"": 5, \""severity\"": \""warning\"" },
{ \""from\"": 5, \""severity\"": \""critical\"" }
]
}
}
}
},
{
\""type\"": \""widget\"",
\""props\"": { \""title\"": \""Error rate over time\"" },
\""content\"": {
\""type\"": \""visualization\"",
\""id\"": \""viz.line\"",
\""props\"": {
\""nrqlQueries\"": [
{
\""accountIds\"": [1234567],
\""query\"": \""SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\""
}
],
\""legend\"": { \""enabled\"": true },
\""yAxisLeft\"": { \""zero\"": true },
\""nullValues\"": { \""nullValue\"": \""zero\"" }
}
}
}
]
}
]
}
",
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.newrelic.Notebook;
import com.pulumi.newrelic.NotebookArgs;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var incidentRunbook = new Notebook("incidentRunbook", NotebookArgs.builder()
.title("Production API Incident - Investigation")
.content("""
{
\"type\": \"declarative\",
\"version\": 1,
\"content\": [
{
\"type\": \"container\",
\"props\": { \"layout\": \"stack\" },
\"content\": [
{
\"type\": \"widget\",
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.markdown\",
\"props\": {
\"text\": \"# Production API Incident\
\
**Status**: Resolved\
**Impact**: ~15% of API requests failed\
\
Use this notebook to walk through what happened and track action items.\"
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Peak error rate\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.billboard\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\"
}
],
\"thresholdsWithSeriesOverrides\": {
\"thresholds\": [
{ \"to\": 1, \"severity\": \"success\" },
{ \"from\": 1, \"to\": 5, \"severity\": \"warning\" },
{ \"from\": 5, \"severity\": \"critical\" }
]
}
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Error rate over time\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.line\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\"
}
],
\"legend\": { \"enabled\": true },
\"yAxisLeft\": { \"zero\": true },
\"nullValues\": { \"nullValue\": \"zero\" }
}
}
}
]
}
]
}
""")
.build());
}
}
resources:
incidentRunbook:
type: newrelic:Notebook
name: incident_runbook
properties:
title: Production API Incident - Investigation
content: |
{
\"type\": \"declarative\",
\"version\": 1,
\"content\": [
{
\"type\": \"container\",
\"props\": { \"layout\": \"stack\" },
\"content\": [
{
\"type\": \"widget\",
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.markdown\",
\"props\": {
\"text\": \"# Production API Incident\
\
**Status**: Resolved\
**Impact**: ~15% of API requests failed\
\
Use this notebook to walk through what happened and track action items.\"
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Peak error rate\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.billboard\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\"
}
],
\"thresholdsWithSeriesOverrides\": {
\"thresholds\": [
{ \"to\": 1, \"severity\": \"success\" },
{ \"from\": 1, \"to\": 5, \"severity\": \"warning\" },
{ \"from\": 5, \"severity\": \"critical\" }
]
}
}
}
},
{
\"type\": \"widget\",
\"props\": { \"title\": \"Error rate over time\" },
\"content\": {
\"type\": \"visualization\",
\"id\": \"viz.line\",
\"props\": {
\"nrqlQueries\": [
{
\"accountIds\": [1234567],
\"query\": \"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\"
}
],
\"legend\": { \"enabled\": true },
\"yAxisLeft\": { \"zero\": true },
\"nullValues\": { \"nullValue\": \"zero\" }
}
}
}
]
}
]
}
pulumi {
required_providers {
newrelic = {
source = "pulumi/newrelic"
}
}
}
resource "newrelic_notebook" "incident_runbook" {
title = "Production API Incident - Investigation"
content = "{\n \\\"type\\\": \\\"declarative\\\",\n \\\"version\\\": 1,\n \\\"content\\\": [\n {\n \\\"type\\\": \\\"container\\\",\n \\\"props\\\": { \\\"layout\\\": \\\"stack\\\" },\n \\\"content\\\": [\n {\n \\\"type\\\": \\\"widget\\\",\n \\\"content\\\": {\n \\\"type\\\": \\\"visualization\\\",\n \\\"id\\\": \\\"viz.markdown\\\",\n \\\"props\\\": {\n \\\"text\\\": \\\"# Production API Incident\\\n\\\n**Status**: Resolved\\\n**Impact**: ~15% of API requests failed\\\n\\\nUse this notebook to walk through what happened and track action items.\\\"\n }\n }\n },\n {\n \\\"type\\\": \\\"widget\\\",\n \\\"props\\\": { \\\"title\\\": \\\"Peak error rate\\\" },\n \\\"content\\\": {\n \\\"type\\\": \\\"visualization\\\",\n \\\"id\\\": \\\"viz.billboard\\\",\n \\\"props\\\": {\n \\\"nrqlQueries\\\": [\n {\n \\\"accountIds\\\": [1234567],\n \\\"query\\\": \\\"SELECT percentage(count(*), WHERE httpResponseCode >= 400) AS 'Error Rate %' FROM Transaction WHERE appName = 'api-production' SINCE 1 hour ago\\\"\n }\n ],\n \\\"thresholdsWithSeriesOverrides\\\": {\n \\\"thresholds\\\": [\n { \\\"to\\\": 1, \\\"severity\\\": \\\"success\\\" },\n { \\\"from\\\": 1, \\\"to\\\": 5, \\\"severity\\\": \\\"warning\\\" },\n { \\\"from\\\": 5, \\\"severity\\\": \\\"critical\\\" }\n ]\n }\n }\n }\n },\n {\n \\\"type\\\": \\\"widget\\\",\n \\\"props\\\": { \\\"title\\\": \\\"Error rate over time\\\" },\n \\\"content\\\": {\n \\\"type\\\": \\\"visualization\\\",\n \\\"id\\\": \\\"viz.line\\\",\n \\\"props\\\": {\n \\\"nrqlQueries\\\": [\n {\n \\\"accountIds\\\": [1234567],\n \\\"query\\\": \\\"SELECT percentage(count(*), WHERE httpResponseCode >= 400) FROM Transaction WHERE appName = 'api-production' TIMESERIES 1 minute SINCE 1 hour ago\\\"\n }\n ],\n \\\"legend\\\": { \\\"enabled\\\": true },\n \\\"yAxisLeft\\\": { \\\"zero\\\": true },\n \\\"nullValues\\\": { \\\"nullValue\\\": \\\"zero\\\" }\n }\n }\n }\n ]\n }\n ]\n}\n"
}
Content Format and Schema
A notebook body is a JSON document with a fixed three-level structure. The first two levels are always written the same way. The third level is where all your widgets go.
WARNING: The
//annotations in the snippet below are for illustration only and are not valid JSON. Do not include them in your actual notebook body.
{
// Level 1 - always fixed
// This structure is identical across every notebook. Do not modify these fields.
"type": "declarative",
"version": 1,
"content": [
{
// Level 2 - always fixed
// This structure is identical across every notebook. Do not modify these fields.
"type": "container",
"props": { "layout": "stack" },
"content": [
// Level 3 - your widgets go here. Add as many as you need.
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": { "text": "## Section header\n\nAdd narrative, context, or action items here." }
}
},
{
"type": "widget",
"props": { "title": "Error rate" },
"content": {
"type": "visualization",
"id": "viz.billboard",
"props": { ... }
}
},
{
"type": "widget",
"props": { "title": "Throughput over time" },
"content": {
"type": "visualization",
"id": "viz.line",
"props": { ... }
}
}
]
}
]
}
Understanding the structure
Levels 1 and 2 are always identical. You always write them exactly as shown above - they cannot be customized beyond what is described here.
Level 1 - Document envelope (fixed)
typemust always be"declarative".versionmust always be the integer1.contentis an array containing exactly one container object (Level 2). The New Relic Notebooks UI only renders the first container - place all widgets inside it.
Level 2 - Container (fixed)
typemust always be"container".propsmust always be{ "layout": "stack" }.contentis the array where your widgets live. This is the only attribute in Level 2 that varies - add as many widget objects as you need.
Level 3 is where you do your work. Every object in the Level 2 content array is a widget. Each widget has three attributes:
- Level 3 - Widgets (customizable)
typemust always be"widget".props(widget-level, controls the title label above the chart) - The rules differ by chart type. Note: thispropsis not the same ascontent.propsbelow - it only controls the widget’s display title, not the chart configuration.viz.markdownonly:propsmust be absent entirely from the widget object. Including even an empty"props": {}will fail validation atpulumi previewtime.- All other chart types:
propsmust be present and must include atitlekey. An empty string""is valid as a title. Example:"props": { "title": "Error rate" }.
content- The visualization to render. Three sub-fields are always required:typemust be"visualization".ididentifies the chart type - for example"viz.markdown","viz.line","viz.area". See Supported visualization types for the full list.props(content-level, chart configuration) - Holds the chart-specific configuration such as NRQL queries, axis settings, and thresholds. This is separate from the widget-levelpropsdescribed above - these props define how the chart renders its data, not the display title.
Putting it together - a quick reference:
The following summarizes the steps to create a notebook that follows the required structure and passes validation without errors.
- Start with Level 1:
"type": "declarative","version": 1, and a"content"array with one object. - Inside that object, add Level 2:
"type": "container","props": { "layout": "stack" }, and a"content"array. - Inside the Level 2
"content"array, add as many Level 3 widget objects as you need. Each widget must have:"type": "widget"- always."props": { "title": "..." }(widget-level - display title only, not chart config) - Required for all chart types. Omit entirely forviz.markdownwidgets."content"containing"type": "visualization","id": "<chart-type>"(see Supported Visualization Types for all valid values), and"props": { ... }(content-level - chart configuration such as queries, thresholds, axis options).
Supported Visualization Types
The id field inside a widget’s content object identifies which chart type to render. The following visualization types are supported:
Visualization type reference
id | Display name | Typical NRQL shape |
|---|---|---|
viz.markdown | Markdown | N/A |
viz.line | Line | TIMESERIES |
viz.area | Area | TIMESERIES |
viz.stacked-bar | Bar (stacked) | TIMESERIES or FACET |
viz.bar | Bar (simplified) | FACET |
viz.stacked-horizontal-bar | Horizontal stacked bar | FACET |
viz.pie | Pie | FACET |
viz.table | Table | FACET |
viz.billboard | Billboard | Single aggregation |
viz.gauge | Gauge | Single aggregation |
viz.histogram | Histogram | histogram() function |
viz.heatmap | Heatmap | histogram() with FACET |
viz.scatter | Scatter | Two-value FACET |
viz.apdex | Apdex | Apdex-compatible |
viz.bullet | Bullet | Single aggregation |
viz.funnel | Funnel | funnel() function |
viz.event-feed | Event feed | Any |
viz.json | JSON | Any |
viz.sparkline | Sparkline | TIMESERIES |
viz.sparkline-lite | Sparkline Lite | TIMESERIES |
Widget props reference
Each visualization type below lists its supported props. These go inside the widget’s content.props object.
viz.markdown - Markdown
Renders a text block supporting GitHub-flavoured Markdown. Use it to add context, section headers, runbook steps, or action-item checklists between your charts.
NOTE: The
propskey must be absent entirely from the widget object forviz.markdown. Including"props": {}will fail validation. See Understanding the structure for both a code example and an explanation of why this restriction exists.
text- (Required) The Markdown source string. Supports headings, bold, italic, code, lists, task lists (- [ ]), tables, and links. Use\nfor newlines within the string.
Example:
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": "## Investigation Notes\n\n- [ ] Check alert history\n- [ ] Review recent deploys"
}
}
}
viz.line - Line chart
The workhorse for time-series data. Use it when you want to show how a metric changes over time and need full control over axes, thresholds, and per-series styling.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.alertQueries- (Optional) Alert violation objects to overlay warning/critical bands on the chart. Only available forviz.line. Each object supports:accountIds- (Required) Account IDs the alert query runs against.violationId- (Required) The violation ID to overlay.duration- (Required) Duration in milliseconds.endTime- (Required) End time as an epoch millisecond timestamp.
legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.position- (Optional) Where to place the legend. Valid values are"bottom"(default),"left", or"right".
facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
yAxisLeft- (Optional) Configuration for the left Y axis.min- (Optional) Fixed minimum value for the axis.max- (Optional) Fixed maximum value for the axis.zero- (Optional) Force zero as the axis origin. Defaults totrue.scale- (Optional) Axis scale. Valid values are"linear"(default) and"logarithmic".
yAxisRight- (Optional) Configuration for the right Y axis. Supports the same sub-keys asyAxisLeft, plus:series- (Optional) List of series names to plot against the right axis.name- (Required) The series name to bind to the right axis.
nullValues- (Optional) Controls how null data points are rendered.nullValue- (Optional) Default null handling. Valid values:"default","zero","preserve","remove".seriesOverrides- (Optional) Per-series null value overrides.seriesName- (Required) The series to override.nullValue- (Required) The null handling for that series.
colors- (Optional) Controls chart coloring.colorPalette- (Optional) Color palette. Valid values are"consistent"(default) and"dynamic".seriesOverrides- (Optional) Per-series color overrides.seriesName- (Required) The series to override.color- (Required) RGB hex color, e.g."#FF0000".
units- (Optional) Data units for display formatting.unit- (Optional) Default unit for all series. See Validunits.unitvalues.seriesOverrides- (Optional) Per-series unit overrides.seriesName- (Required) The series to override.unit- (Required) The unit for that series.
thresholds- (Optional) Horizontal threshold bands drawn across the chart. See Nestedthresholdsblocks (line, area, stacked-bar).isLabelVisible- (Optional) Show threshold labels on the chart. Defaults tofalse.thresholds- (Optional) Array of threshold band definitions.name- (Optional) A label for the threshold band.from- (Optional) Lower bound of the threshold range (inclusive).to- (Optional) Upper bound of the threshold range (inclusive).severity- (Required) Color coding. Valid values:"success","warning","severe","critical","unavailable".
chartStyles- (Optional) Visual style overrides for the chart.lineInterpolation- (Optional) Line interpolation mode. Valid values:"linear"(default),"smooth","stepBefore","stepAfter".gradient- (Optional) Gradient fill under the line.enabled- (Optional) Enable gradient fill. Defaults tofalse.
chartTypes- (Optional) Override the chart type per series.seriesOverrides- (Optional) Per-series chart type overrides.seriesName- (Required) The series to override.chartType- (Required) Valid values:"line","area".
tooltip- (Optional) Tooltip display behaviour.mode- (Optional) Valid values:"single"(default),"all","hidden".
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Throughput by Application (requests / min)"
},
"content": {
"type": "visualization",
"id": "viz.line",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT rate(count(*), 1 minute) AS 'rpm' FROM Transaction FACET appName TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"legend": {
"enabled": true,
"position": "bottom"
},
"yAxisLeft": {
"min": 0,
"zero": true
},
"nullValues": {
"nullValue": "zero"
},
"chartStyles": {
"lineInterpolation": "smooth"
},
"tooltip": {
"mode": "all"
},
"colors": {
"colorPalette": "consistent"
},
"platformOptions": {
"ignoreTimeRange": false
},
"refreshRate": {
"frequency": 60000
}
}
}
}
viz.area - Area chart
Great for showing cumulative totals or filled time-series where the area under the line carries meaning.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
Supports the same props as viz.line, with the following differences:
alertQueriesandyAxisRightare not available.nullValuessupports"default","zero","preserve"(not"remove").- Additional prop:
chartStylesstacked- (Optional) Stack multiple series on top of each other.enabled- (Optional) Enable stacked layout. Defaults totrue.
Example:
{
"type": "widget",
"props": {
"title": "Response Time Percentiles (ms)"
},
"content": {
"type": "visualization",
"id": "viz.area",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT percentile(duration * 1000, 50) AS 'P50 ms', percentile(duration * 1000, 95) AS 'P95 ms', percentile(duration * 1000, 99) AS 'P99 ms' FROM Transaction TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"legend": {
"enabled": true,
"position": "bottom"
},
"yAxisLeft": {
"zero": true
},
"nullValues": {
"nullValue": "zero"
},
"chartStyles": {
"stacked": {
"enabled": false
}
},
"colors": {
"seriesOverrides": [
{
"seriesName": "P50 ms",
"color": "#11A600"
},
{
"seriesName": "P95 ms",
"color": "#FFB951"
},
{
"seriesName": "P99 ms",
"color": "#BF0016"
}
]
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.stacked-bar - Bar chart (stacked / timeseries)
Use this when you want to compare part-to-whole relationships over time - for example, traffic broken down by endpoint or host.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
Supports all viz.line props except alertQueries, yAxisRight, and the "remove" null value. Additional prop:
chartStyles- (Optional) Visual style configuration.stacked- (Optional) Stack configuration.enabled- (Optional) Enable stacked layout. Defaults totrue.
Example:
{
"type": "widget",
"props": {
"title": "Request Volume by App (stacked)"
},
"content": {
"type": "visualization",
"id": "viz.stacked-bar",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) FROM Transaction FACET appName TIMESERIES 10 minutes SINCE 3 hours ago"
}
],
"legend": {
"enabled": true
},
"yAxisLeft": {
"zero": true
},
"nullValues": {
"nullValue": "zero"
},
"chartStyles": {
"stacked": {
"enabled": true
}
},
"thresholds": {
"isLabelVisible": true,
"thresholds": [
{
"name": "High traffic",
"from": 5000,
"severity": "warning"
}
]
},
"platformOptions": {
"ignoreTimeRange": false
},
"refreshRate": {
"frequency": 60000
}
}
}
}
viz.bar - Bar chart (simplified)
A simpler bar chart for categorical FACET comparisons - when you want counts or averages across a dimension and a timeseries axis isn’t needed.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
colors- (Optional) Controls chart coloring.colorPalette- (Optional) Color palette. Valid values are"consistent"(default) and"dynamic".seriesOverrides- (Optional) Per-series color overrides.seriesName- (Required) The series to override.color- (Required) RGB hex color, e.g."#FF0000".
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Top Transaction Types by Count"
},
"content": {
"type": "visualization",
"id": "viz.bar",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) FROM Transaction FACET name SINCE 1 hour ago LIMIT 10"
}
],
"facet": {
"showOtherSeries": false
},
"colors": {
"colorPalette": "consistent"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.stacked-horizontal-bar - Horizontal stacked bar
Useful for comparing proportions across categories when your label text is long and reads better horizontally.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Log Volume by Level"
},
"content": {
"type": "visualization",
"id": "viz.stacked-horizontal-bar",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) AS 'Log Lines' FROM Log FACET level SINCE 3 hours ago"
}
],
"legend": {
"enabled": true
},
"facet": {
"showOtherSeries": false
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.pie - Pie chart
Good for showing how a whole is divided among a small number of categories. If you have more than 7-8 slices, a bar chart is usually clearer.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults totrue(differs from other chart types).
legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.
colors- (Optional) Controls chart coloring.colorPalette- (Optional) Color palette. Valid values are"consistent"(default) and"dynamic".seriesOverrides- (Optional) Per-series color overrides.seriesName- (Required) The series to override.color- (Required) RGB hex color, e.g."#FF0000".
chartStyles- (Optional) Visual style configuration.gradient- (Optional) Gradient fill for pie slices.enabled- (Optional) Enable gradient. Defaults tofalse.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Disk Utilisation by Host"
},
"content": {
"type": "visualization",
"id": "viz.pie",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(diskUsedPercent) AS 'Disk Used %' FROM StorageSample FACET hostname SINCE 30 minutes ago"
}
],
"legend": {
"enabled": true
},
"facet": {
"showOtherSeries": false
},
"colors": {
"colorPalette": "consistent"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.table - Table
The right choice when you need to show raw rows, multi-column comparisons, or sortable ranked lists. Pairs well with initialSorting and column-level thresholds.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
initialSorting- (Optional) Default sort applied when the table first renders.name- (Required) Column name to sort by.direction- (Required) Sort direction. Valid values:"asc","desc".
hiddenColumns- (Optional) Columns to suppress from the rendered table.columnName- (Required) The column name to hide, as it appears in the query results.
thresholds- (Optional) Column-level color thresholds. See Nestedthresholdsblocks (table). Each entry supports:columnName- (Required) The column to apply the threshold to.from- (Optional) Lower bound of the range.to- (Optional) Upper bound of the range.severity- (Required) Valid values:"success","warning","severe","critical","unavailable".
dataFormatters- (Optional) Custom per-column data format configuration.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Host Health - CPU, Memory and Disk"
},
"content": {
"type": "visualization",
"id": "viz.table",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(cpuPercent) AS 'Avg CPU %', max(cpuPercent) AS 'Max CPU %', average(memoryUsedPercent) AS 'Avg Mem %', average(diskUsedPercent) AS 'Disk Used %' FROM SystemSample FACET hostname SINCE 30 minutes ago LIMIT 20"
}
],
"initialSorting": {
"name": "Avg CPU %",
"direction": "desc"
},
"thresholds": [
{
"columnName": "Avg CPU %",
"from": 80,
"severity": "critical"
},
{
"columnName": "Avg CPU %",
"from": 60,
"to": 80,
"severity": "warning"
},
{
"columnName": "Avg Mem %",
"from": 90,
"severity": "critical"
},
{
"columnName": "Disk Used %",
"from": 85,
"severity": "critical"
}
],
"facet": {
"showOtherSeries": false
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.billboard - Billboard
Displays a single large metric value with color-coded threshold ranges. Perfect for at-a-glance status tiles at the top of a notebook.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
thresholdsWithSeriesOverrides- (Optional) Threshold configuration for the billboard. See NestedthresholdsWithSeriesOverridesblocks (billboard).thresholds- (Optional) Global threshold ranges applied to all series.from- (Optional) Lower bound of the range.to- (Optional) Upper bound of the range.severity- (Required) Valid values:"success","warning","severe","critical","unavailable".
seriesOverrides- (Optional) Per-series threshold overrides for multi-value billboards.seriesName- (Required) The series to override.from- (Optional) Lower bound.to- (Optional) Upper bound.severity- (Required) Severity level for this series.
billboardSettings- (Optional) Fine-grained layout and linking options.visual- (Optional) Controls the visual presentation of the billboard.alignment- (Optional) Alignment of values on the billboard. Valid values:"auto","stacked","inline".display- (Optional) What to show on the billboard. Valid values:"auto","all","value","label","none".
gridOptions- (Optional) Grid layout for multi-value billboards.columns- (Optional) Number of columns in the grid.label- (Optional) Label display size configuration.value- (Optional) Value display size configuration.
link- (Optional) A clickable link attached to the billboard.url- (Required) The destination URL.title- (Optional) Link text shown on the billboard.newTab- (Optional) Open the link in a new tab. Defaults tofalse.
units- (Optional) Data units for display formatting.unit- (Optional) Default unit for all series. See Validunits.unitvalues.seriesOverrides- (Optional) Per-series unit overrides.seriesName- (Required) The series to override.unit- (Required) The unit for that series.
dataFormatters- (Optional) Custom per-column data format configuration.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Request Volume and Error Rate"
},
"content": {
"type": "visualization",
"id": "viz.billboard",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT rate(count(*), 1 minute) AS 'Requests / min', percentage(count(*), WHERE error IS true) AS 'Error Rate %', count(*) AS 'Total Requests' FROM Transaction SINCE 1 hour ago"
}
],
"thresholdsWithSeriesOverrides": {
"thresholds": [
{
"to": 1,
"severity": "success"
},
{
"from": 1,
"to": 5,
"severity": "warning"
},
{
"from": 5,
"severity": "critical"
}
],
"seriesOverrides": [
{
"seriesName": "Error Rate %",
"from": 1,
"severity": "critical"
}
]
},
"billboardSettings": {
"visual": {
"alignment": "inline",
"display": "all"
}
},
"facet": {
"showOtherSeries": false
},
"platformOptions": {
"ignoreTimeRange": false
},
"refreshRate": {
"frequency": 60000
}
}
}
}
viz.gauge - Gauge
Shows a single value against a min/max scale, making it easy to communicate how close you are to a limit or target.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.colors- (Optional) Controls chart coloring.colorPalette- (Optional) Color palette. Valid values are"consistent"(default) and"dynamic".seriesOverrides- (Optional) Per-series color overrides.seriesName- (Required) The series to override.color- (Required) RGB hex color, e.g."#FF0000".
facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
gaugeSettings- (Optional) Appearance and scale options for the gauge.displayMode- (Optional) Gauge shape. Valid values:"arc"(default),"circular","bar".min- (Optional) Lower bound of the scale.max- (Optional) Upper bound of the scale. Defaults to100.display- (Optional) What to render inside the gauge. Valid values:"auto"(default),"all","value","name","none".showThresholdMarkers- (Optional) Show tick marks at threshold boundaries. Defaults totrue.showThresholdLabels- (Optional) Show labels at threshold boundaries. Defaults tofalse.thresholdsColorMode- (Optional) How threshold colors are applied. Valid values:"solid"(default),"gradient".
thresholds- (Optional) Threshold zones displayed on the gauge scale.thresholds- (Optional) Array of threshold zone entries.from- (Optional) Lower bound of the zone.severity- (Required) Severity level for this zone.
units- (Optional) Data units for display formatting.unit- (Optional) Default unit for all series. See Validunits.unitvalues.seriesOverrides- (Optional) Per-series unit overrides.seriesName- (Required) The series to override.unit- (Required) The unit for that series.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Memory Utilisation (%)"
},
"content": {
"type": "visualization",
"id": "viz.gauge",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(memoryUsedPercent) AS 'Memory %' FROM SystemSample SINCE 30 minutes ago"
}
],
"gaugeSettings": {
"displayMode": "arc",
"min": 0,
"max": 100,
"display": "auto",
"showThresholdMarkers": true,
"showThresholdLabels": false,
"thresholdsColorMode": "solid"
},
"thresholds": {
"thresholds": [
{
"from": 0,
"severity": "success"
},
{
"from": 60,
"severity": "warning"
},
{
"from": 80,
"severity": "critical"
}
]
},
"colors": {
"colorPalette": "consistent"
},
"units": {
"unit": "PERCENTAGE"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.histogram - Histogram
Visualizes the distribution of a numeric attribute across buckets. Your query must use the histogram() NRQL function.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. Query must usehistogram(attr)orhistogram(attr, width: N, buckets: N). See NestednrqlQueriesblocks.legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.position- (Optional) Where to place the legend. Valid values are"bottom"(default),"left", or"right".
colors- (Optional) Controls chart coloring.colorPalette- (Optional) Color palette. Valid values are"consistent"(default) and"dynamic".seriesOverrides- (Optional) Per-series color overrides.seriesName- (Required) The series to override.color- (Required) RGB hex color, e.g."#FF0000".
yAxisLeft- (Optional) Configuration for the left Y axis.min- (Optional) Fixed minimum value for the axis.max- (Optional) Fixed maximum value for the axis.zero- (Optional) Force zero as the axis origin. Defaults totrue.scale- (Optional) Axis scale. Valid values are"linear"(default) and"logarithmic".
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Transaction Duration Distribution"
},
"content": {
"type": "visualization",
"id": "viz.histogram",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT histogram(duration * 1000, 0.5, 20) FROM Transaction SINCE 1 hour ago"
}
],
"legend": {
"enabled": true
},
"yAxisLeft": {
"zero": true
},
"colors": {
"colorPalette": "consistent"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.heatmap - Heatmap
Renders a two-dimensional density map. Requires histogram() combined with a FACET to produce the row-and-bucket structure.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. Query must usehistogram()with aFACETclause. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Duration Distribution by App"
},
"content": {
"type": "visualization",
"id": "viz.heatmap",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT histogram(duration * 1000, 0.5, 20) FROM Transaction FACET appName SINCE 3 hours ago"
}
],
"facet": {
"showOtherSeries": false
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.scatter - Scatter plot
Plots two numeric measures against each other to reveal correlations. Your query should return two numeric values and a FACET for the data points.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. Query should return two numeric values and aFACET. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.position- (Optional) Where to place the legend. Valid values are"bottom"(default),"left", or"right".
nullValues- (Optional) Controls how null data points are rendered.nullValue- (Optional) Default null handling. Valid values:"default","zero","preserve","remove".seriesOverrides- (Optional) Per-series null value overrides.seriesName- (Required) The series to override.nullValue- (Required) The null handling for that series.
yAxisLeft- (Optional) Configuration for the left Y axis.min- (Optional) Fixed minimum value for the axis.max- (Optional) Fixed maximum value for the axis.zero- (Optional) Force zero as the axis origin. Defaults totrue.scale- (Optional) Axis scale. Valid values are"linear"(default) and"logarithmic".
units- (Optional) Data units for display formatting.unit- (Optional) Default unit for all series. See Validunits.unitvalues.seriesOverrides- (Optional) Per-series unit overrides.seriesName- (Required) The series to override.unit- (Required) The unit for that series.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "CPU % vs Memory % by Host"
},
"content": {
"type": "visualization",
"id": "viz.scatter",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(cpuPercent) AS 'Avg CPU %', average(memoryUsedPercent) AS 'Avg Mem %' FROM SystemSample FACET hostname SINCE 1 hour ago TIMESERIES 5 minutes"
}
],
"legend": {
"enabled": true
},
"yAxisLeft": {
"zero": true
},
"facet": {
"showOtherSeries": false
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.apdex - Apdex
Renders an Apdex score widget. Use it when you’re tracking application performance against a satisfaction threshold.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.legend- (Optional) Controls the chart legend.enabled- (Optional) Show or hide the legend. Defaults totrue.position- (Optional) Where to place the legend. Valid values are"bottom"(default),"left", or"right".
tooltip- (Optional) Tooltip display behaviour.mode- (Optional) Valid values:"single"(default),"all","hidden".
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Apdex Score Over Time"
},
"content": {
"type": "visualization",
"id": "viz.apdex",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT apdex(duration, 0.5) AS 'Apdex' FROM Transaction SINCE 3 hours ago TIMESERIES 5 minutes"
}
],
"legend": {
"enabled": true,
"position": "bottom"
},
"tooltip": {
"mode": "single"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.bullet - Bullet chart
Compares an actual value against a target goal. The limit sets the goal line - without it the chart won’t render correctly.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.limit- (Required) The target value shown as the goal line on the chart.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Requests vs Target"
},
"content": {
"type": "visualization",
"id": "viz.bullet",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) AS 'Requests' FROM Transaction SINCE 1 hour ago"
}
],
"limit": 50000,
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.funnel - Funnel chart
Tracks how users or events progress through sequential steps. Requires the funnel() NRQL function.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. Query must use thefunnel()NRQL function. See NestednrqlQueriesblocks.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Transaction Funnel"
},
"content": {
"type": "visualization",
"id": "viz.funnel",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT funnel(session, WHERE name = 'step1' AS 'Step 1', WHERE name = 'step2' AS 'Step 2') FROM PageView SINCE 1 hour ago"
}
],
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.event-feed - Event feed
Streams individual events as a scrollable list. Useful when you want to show raw log entries or transaction events rather than aggregations.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Recent Transactions"
},
"content": {
"type": "visualization",
"id": "viz.event-feed",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT * FROM Transaction SINCE 10 minutes ago LIMIT 20"
}
],
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.json - JSON
Renders the raw JSON payload returned by your query. Handy for debugging complex nested event structures.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Transaction Metrics (JSON)"
},
"content": {
"type": "visualization",
"id": "viz.json",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) AS 'count', average(duration)*1000 AS 'avg_ms', percentile(duration*1000, 95) AS 'p95_ms' FROM Transaction FACET appName SINCE 1 hour ago"
}
],
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.sparkline - Sparkline
A compact inline time-series with no axis labels. Good for dense notebooks where you want trend at a glance without the full chart chrome.
This chart type requires a widget-level props object with a title key. See Understanding the structure.
nrqlQueries- (Required) Array of NRQL query objects. See NestednrqlQueriesblocks.facet- (Optional) Controls FACET grouping behaviour.showOtherSeries- (Optional) Show the “Other” group forFACETqueries. Defaults tofalse.
nullValues- (Optional) Controls how null data points are rendered.nullValue- (Optional) Default null handling. Valid values:"default","zero","preserve","remove".seriesOverrides- (Optional) Per-series null value overrides.seriesName- (Required) The series to override.nullValue- (Required) The null handling for that series.
chartStyles- (Optional) Visual style overrides.lineInterpolation- (Optional) Line interpolation mode. Valid values:"linear"(default),"smooth","stepBefore","stepAfter".
yAxisLeft- (Optional) Configuration for the left Y axis.min- (Optional) Fixed minimum value for the axis.max- (Optional) Fixed maximum value for the axis.zero- (Optional) Force zero as the axis origin. Defaults totrue.
platformOptions- (Optional) Platform-level rendering options.ignoreTimeRange- (Optional) Use the query’s own time range instead of the notebook time picker. Defaults tofalse.
refreshRate- (Optional) Auto-refresh configuration.frequency- (Optional) Refresh interval in milliseconds, or"auto". See ValidrefreshRate.frequencyvalues.
Example:
{
"type": "widget",
"props": {
"title": "Throughput Trend"
},
"content": {
"type": "visualization",
"id": "viz.sparkline",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT rate(count(*), 1 minute) AS 'rpm' FROM Transaction TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"chartStyles": {
"lineInterpolation": "smooth"
},
"nullValues": {
"nullValue": "zero"
},
"yAxisLeft": {
"zero": true
},
"colors": {
"colorPalette": "consistent"
},
"tooltip": {
"mode": "single"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
viz.sparkline-lite - Sparkline Lite
Ultra-compact sparkline with no axis labels. Supports the same props as viz.sparkline except yAxisLeft.
Example:
{
"type": "widget",
"props": {
"title": "Log Volume Trend"
},
"content": {
"type": "visualization",
"id": "viz.sparkline-lite",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT count(*) AS 'Log lines' FROM Log TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"chartStyles": {
"lineInterpolation": "stepAfter"
},
"nullValues": {
"nullValue": "zero"
},
"colors": {
"colorPalette": "consistent"
},
"platformOptions": {
"ignoreTimeRange": false
}
}
}
}
Nested Blocks Reference
The following sections describe the structure of blocks that appear repeatedly across multiple visualization types.
Nested nrqlQueries blocks
All query-based visualizations accept a nrqlQueries array. Each entry in the array supports:
accountIds- (Required) An array of one or more New Relic account IDs to run the query against.query- (Required) A valid NRQL query string.offset- (Optional) Number of milliseconds to offset the query time window.
Nested thresholds blocks (line, area, stacked-bar)
Used with the thresholds.thresholds array inside viz.line, viz.area, and viz.stacked-bar to draw horizontal threshold bands across the chart.
name- (Optional) A label shown on the threshold band.from- (Optional) Lower bound of the threshold range (inclusive).to- (Optional) Upper bound of the threshold range (inclusive).severity- (Required) Color coding applied to data in this range. Valid values:"success","warning","severe","critical","unavailable".
Nested thresholds blocks (table)
Used with the thresholds array inside viz.table to apply color coding per column.
columnName- (Required) The column to apply the threshold to, as it appears in the query results.from- (Optional) Lower bound of the range.to- (Optional) Upper bound of the range.severity- (Required) Color coding for values in this range. Valid values:"success","warning","severe","critical","unavailable".
Nested thresholdsWithSeriesOverrides blocks (billboard)
Used with viz.billboard to control color coding for the displayed metric values.
thresholds- (Optional) Global threshold ranges applied to all series.from- (Optional) Lower bound of the range.to- (Optional) Upper bound of the range.severity- (Required) Valid values:"success","warning","severe","critical","unavailable".
seriesOverrides- (Optional) Per-series threshold overrides for multi-value billboards.seriesName- (Required) The series name to override.from- (Optional) Lower bound.to- (Optional) Upper bound.severity- (Required) Severity level for this series.
Valid Values Reference
Valid units.unit values
APDEX, BITS, BITS_PER_MS, BITS_PER_SECOND, BYTES, BYTES_PER_MS, BYTES_PER_SECOND, CELSIUS, COUNT, DOLLAR, HERTZ, MS, PAGES_PER_SECOND, PERCENTAGE, REQUESTS_PER_SECOND, REQUESTS_PER_MINUTE, SECONDS, TIMESTAMP
Valid refreshRate.frequency values
| Value | Interval |
|---|---|
"auto" | Platform default |
0 | No refresh |
5000 | 5 seconds |
30000 | 30 seconds |
60000 | 1 minute |
300000 | 5 minutes |
1800000 | 30 minutes |
3600000 | 1 hour |
10800000 | 3 hours |
43200000 | 12 hours |
86400000 | 24 hours |
Examples
Ready-to-use notebook templates. Expand any example to see the full configuration.
Load notebook from a JSON file (recommended for larger notebooks)
Per-service runbook notebooks
Use forEach to generate a runbook notebook for each service in your estate. The jsonencode({...}) expression lets you embed Terraform expressions like each.value and var.account_id directly inside the notebook body.
import * as pulumi from "@pulumi/pulumi";
import * as newrelic from "@pulumi/newrelic";
const config = new pulumi.Config();
const services = config.getObject<Array<string>>("services") || [
"checkout",
"inventory",
"payments",
];
const runbooks: newrelic.Notebook[] = [];
for (const range of services.map((v, k) => ({key: k, value: v}))) {
runbooks.push(new newrelic.Notebook(`runbooks-${range.key}`, {
title: `${range.value} - Runbook`,
content: JSON.stringify({
type: "declarative",
version: 1,
content: [{
type: "container",
props: {
layout: "stack",
},
content: [
{
type: "widget",
content: {
type: "visualization",
id: "viz.markdown",
props: {
text: `# ${range.value}
Add investigation steps and runbook content here.`,
},
},
},
{
type: "widget",
props: {
title: "Error rate",
},
content: {
type: "visualization",
id: "viz.billboard",
props: {
nrqlQueries: [{
accountIds: [accountId],
query: `SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '${range.value}' SINCE 1 hour ago`,
}],
},
},
},
],
}],
}),
}));
}
import pulumi
from typing import Any
import json
import pulumi_newrelic as newrelic
config = pulumi.Config()
services = config.get_object("services")
if services is None:
services = [
"checkout",
"inventory",
"payments",
]
runbooks: list[newrelic.Notebook] = []
for runbooks_range in [{"key": k, "value": v} for [k, v] in enumerate(services)]:
runbooks.append(newrelic.Notebook(f"runbooks-{runbooks_range['key']}",
title=f"{runbooks_range['value']} - Runbook",
content=json.dumps({
"type": "declarative",
"version": 1,
"content": [{
"type": "container",
"props": {
"layout": "stack",
},
"content": [
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": f"""# {runbooks_range["value"]}
Add investigation steps and runbook content here.""",
},
},
},
{
"type": "widget",
"props": {
"title": "Error rate",
},
"content": {
"type": "visualization",
"id": "viz.billboard",
"props": {
"nrqlQueries": [{
"accountIds": [account_id],
"query": f"SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '{runbooks_range['value']}' SINCE 1 hour ago",
}],
},
},
},
],
}],
})))
package main
import (
"encoding/json"
"fmt"
"github.com/pulumi/pulumi-newrelic/sdk/v5/go/newrelic"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
cfg := config.New(ctx, "")
services := []string{
"checkout",
"inventory",
"payments",
}
if param := cfg.GetObject("services"); param != nil {
services = param
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"type": "declarative",
"version": 1,
"content": []map[string]interface{}{
map[string]interface{}{
"type": "container",
"props": map[string]string{
"layout": "stack",
},
"content": []interface{}{
map[string]interface{}{
"type": "widget",
"content": map[string]interface{}{
"type": "visualization",
"id": "viz.markdown",
"props": map[string]string{
"text": fmt.Sprintf("# %v\n\nAdd investigation steps and runbook content here.", val0),
},
},
},
map[string]interface{}{
"type": "widget",
"props": map[string]string{
"title": "Error rate",
},
"content": map[string]interface{}{
"type": "visualization",
"id": "viz.billboard",
"props": map[string][]map[string]interface{}{
"nrqlQueries": []map[string]interface{}{
map[string]interface{}{
"accountIds": []interface{}{
accountId,
},
"query": fmt.Sprintf("%v%v' SINCE 1 hour ago", "SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '", val0),
},
},
},
},
},
},
},
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
var runbooks []*newrelic.Notebook
for key0, val0 := range services {
__res, err := newrelic.NewNotebook(ctx, fmt.Sprintf("runbooks-%v", key0), &newrelic.NotebookArgs{
Title: pulumi.Sprintf("%v - Runbook", val0),
Content: pulumi.String(json0),
})
if err != nil {
return err
}
runbooks = append(runbooks, __res)
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using NewRelic = Pulumi.NewRelic;
return await Deployment.RunAsync(() =>
{
var config = new Config();
var services = config.GetObject<string[]>("services") ?? new[]
{
"checkout",
"inventory",
"payments",
};
var runbooks = new List<NewRelic.Notebook>();
foreach (var range in services.Select((v, k) => new { Key = k, Value = v }))
{
runbooks.Add(new NewRelic.Notebook($"runbooks-{range.Key}", new()
{
Title = $"{range.Value} - Runbook",
Content = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["type"] = "declarative",
["version"] = 1,
["content"] = new[]
{
new Dictionary<string, object?>
{
["type"] = "container",
["props"] = new Dictionary<string, object?>
{
["layout"] = "stack",
},
["content"] = new[]
{
new Dictionary<string, object?>
{
["type"] = "widget",
["content"] = new Dictionary<string, object?>
{
["type"] = "visualization",
["id"] = "viz.markdown",
["props"] = new Dictionary<string, object?>
{
["text"] = @$"# {range.Value}
Add investigation steps and runbook content here.",
},
},
},
new Dictionary<string, object?>
{
["type"] = "widget",
["props"] = new Dictionary<string, object?>
{
["title"] = "Error rate",
},
["content"] = new Dictionary<string, object?>
{
["type"] = "visualization",
["id"] = "viz.billboard",
["props"] = new Dictionary<string, object?>
{
["nrqlQueries"] = new[]
{
new Dictionary<string, object?>
{
["accountIds"] = new[]
{
accountId,
},
["query"] = $"SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '{range.Value}' SINCE 1 hour ago",
},
},
},
},
},
},
},
},
}),
}));
}
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.newrelic.Notebook;
import com.pulumi.newrelic.NotebookArgs;
import static com.pulumi.codegen.internal.Serialization.*;
import com.pulumi.codegen.internal.KeyedValue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var config = ctx.config();
final var services = config.get("services").orElse(Arrays.asList(
"checkout",
"inventory",
"payments"));
for (var range : KeyedValue.of(services)) {
new Notebook("runbooks-" + range.key(), NotebookArgs.builder()
.title(String.format("%s - Runbook", range.value()))
.content(serializeJson(
jsonObject(
jsonProperty("type", "declarative"),
jsonProperty("version", 1),
jsonProperty("content", jsonArray(jsonObject(
jsonProperty("type", "container"),
jsonProperty("props", jsonObject(
jsonProperty("layout", "stack")
)),
jsonProperty("content", jsonArray(
jsonObject(
jsonProperty("type", "widget"),
jsonProperty("content", jsonObject(
jsonProperty("type", "visualization"),
jsonProperty("id", "viz.markdown"),
jsonProperty("props", jsonObject(
jsonProperty("text", """
# %s
Add investigation steps and runbook content here.", range.value()))
))
))
),
jsonObject(
jsonProperty("type", "widget"),
jsonProperty("props", jsonObject(
jsonProperty("title", "Error rate")
)),
jsonProperty("content", jsonObject(
jsonProperty("type", "visualization"),
jsonProperty("id", "viz.billboard"),
jsonProperty("props", jsonObject(
jsonProperty("nrqlQueries", jsonArray(jsonObject(
jsonProperty("accountIds", jsonArray(accountId)),
jsonProperty("query", String.format("SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '%s' SINCE 1 hour ago", range.value()))
)))
))
))
)
))
)))
)))
.build());
}
}
}
configuration:
services:
type: list<string>
default:
- checkout
- inventory
- payments
resources:
runbooks:
type: newrelic:Notebook
properties:
title: ${range.value} - Runbook
content:
fn::toJSON:
type: declarative
version: 1
content:
- type: container
props:
layout: stack
content:
- type: widget
content:
type: visualization
id: viz.markdown
props:
text: |-
# ${range.value}
Add investigation steps and runbook content here.
- type: widget
props:
title: Error rate
content:
type: visualization
id: viz.billboard
props:
nrqlQueries:
- accountIds:
- ${accountId}
query: SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '${range.value}' SINCE 1 hour ago
options: {}
pulumi {
required_providers {
newrelic = {
source = "pulumi/newrelic"
}
}
}
resource "newrelic_notebook" "runbooks" {
for_each = { for __key, __value in var.services : tostring(__key) => __value }
title ="${each.value} - Runbook"
content = jsonencode({
"type" = "declarative"
"version" = 1
"content" = [{
"type" = "container"
"props" = {
"layout" = "stack"
}
"content" = [{
"type" = "widget"
"content" = {
"type" = "visualization"
"id" = "viz.markdown"
"props" = {
"text" ="# ${each.value}
Add investigation steps and runbook content here."
}
}
}, {
"type" = "widget"
"props" = {
"title" = "Error rate"
}
"content" = {
"type" = "visualization"
"id" = "viz.billboard"
"props" = {
"nrqlQueries" = [{
"accountIds" = [accountId]
"query" ="SELECT percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = '${each.value}' SINCE 1 hour ago"
}]
}
}
}]
}]
})
}
variable "services" {
type = list(string)
default = ["checkout", "inventory", "payments"]
}
APM health notebook - throughput, error rate, and latency
APM Health
A notebook for monitoring a single application’s golden signals: request rate, error percentage, and response time percentiles. Adapt the appName filter and account ID to your environment.
{
"type": "declarative",
"version": 1,
"content": [
{
"type": "container",
"props": {
"layout": "stack"
},
"content": [
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": "# APM Health\n\nThroughput, error rate, and latency for **Dummy App Two Max**."
}
}
},
{
"type": "widget",
"props": {
"title": "Throughput and Error Rate"
},
"content": {
"type": "visualization",
"id": "viz.billboard",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT rate(count(*), 1 minute) AS 'rpm', percentage(count(*), WHERE error IS true) AS 'Error %' FROM Transaction WHERE appName = 'Dummy App Two Max' SINCE 1 hour ago"
}
],
"thresholdsWithSeriesOverrides": {
"thresholds": [
{
"from": 1,
"severity": "critical"
}
],
"seriesOverrides": [
{
"seriesName": "Error %",
"from": 1,
"severity": "critical"
}
]
}
}
}
},
{
"type": "widget",
"props": {
"title": "Requests per minute"
},
"content": {
"type": "visualization",
"id": "viz.line",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT rate(count(*), 1 minute) AS 'rpm' FROM Transaction WHERE appName = 'Dummy App Two Max' TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"legend": {
"enabled": true
},
"yAxisLeft": {
"zero": true
},
"nullValues": {
"nullValue": "zero"
}
}
}
},
{
"type": "widget",
"props": {
"title": "Response time - P50 / P95 / P99"
},
"content": {
"type": "visualization",
"id": "viz.area",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT percentile(duration * 1000, 50) AS 'P50 ms', percentile(duration * 1000, 95) AS 'P95 ms', percentile(duration * 1000, 99) AS 'P99 ms' FROM Transaction WHERE appName = 'Dummy App Two Max' TIMESERIES 5 minutes SINCE 3 hours ago"
}
],
"legend": {
"enabled": true,
"position": "bottom"
},
"yAxisLeft": {
"zero": true
},
"nullValues": {
"nullValue": "zero"
},
"colors": {
"seriesOverrides": [
{
"seriesName": "P50 ms",
"color": "#11A600"
},
{
"seriesName": "P95 ms",
"color": "#FFB951"
},
{
"seriesName": "P99 ms",
"color": "#BF0016"
}
]
}
}
}
}
]
}
]
}
Use this JSON with content = file("apm-health.json") or inline using a heredoc.
Infrastructure health notebook - CPU, memory, and disk across hosts
Infrastructure Health
A notebook for host-level visibility across your environment: an at-a-glance table, CPU trend over time, and disk utilisation by host.
{
"type": "declarative",
"version": 1,
"content": [
{
"type": "container",
"props": {
"layout": "stack"
},
"content": [
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": "# Infrastructure Health\n\nHost-level CPU, memory, and disk across the environment."
}
}
},
{
"type": "widget",
"props": {
"title": "Host Health - CPU, Memory and Disk"
},
"content": {
"type": "visualization",
"id": "viz.table",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(cpuPercent) AS 'Avg CPU %', max(cpuPercent) AS 'Max CPU %', average(memoryUsedPercent) AS 'Avg Mem %', average(diskUsedPercent) AS 'Disk %' FROM SystemSample FACET hostname SINCE 30 minutes ago LIMIT 20"
}
],
"initialSorting": {
"name": "Avg CPU %",
"direction": "desc"
},
"thresholds": [
{
"columnName": "Avg CPU %",
"from": 80,
"severity": "critical"
},
{
"columnName": "Avg CPU %",
"from": 60,
"to": 80,
"severity": "warning"
},
{
"columnName": "Avg Mem %",
"from": 90,
"severity": "critical"
}
]
}
}
},
{
"type": "widget",
"props": {
"title": "CPU by Host"
},
"content": {
"type": "visualization",
"id": "viz.stacked-bar",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(cpuPercent) FROM SystemSample FACET hostname TIMESERIES 5 minutes SINCE 1 hour ago"
}
],
"legend": {
"enabled": true
},
"yAxisLeft": {
"zero": true,
"min": 0,
"max": 100
}
}
}
},
{
"type": "widget",
"props": {
"title": "Disk Utilisation"
},
"content": {
"type": "visualization",
"id": "viz.pie",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(diskUsedPercent) FROM StorageSample FACET hostname SINCE 30 minutes ago"
}
],
"facet": {
"showOtherSeries": false
},
"colors": {
"colorPalette": "consistent"
}
}
}
}
]
}
]
}
Incident investigation runbook - structured template with findings and action items
Incident Investigation Runbook
A structured investigation template. Fill in the severity and on-call fields at the top, run the diagnostic queries, record findings in the text block, and track action items through to resolution.
{
"type": "declarative",
"version": 1,
"content": [
{
"type": "container",
"props": {
"layout": "stack"
},
"content": [
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": "# Incident Investigation\n\n**Severity**: P1\n**Start time**: _fill in_\n**On-call**: _fill in_\n\nRun each query below, record findings in the text blocks, and track action items at the bottom."
}
}
},
{
"type": "widget",
"props": {
"title": "Current error rate"
},
"content": {
"type": "visualization",
"id": "viz.billboard",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT percentage(count(*), WHERE error IS true) AS 'Error Rate %', count(*) AS 'Total Requests' FROM Transaction SINCE 15 minutes ago"
}
],
"thresholdsWithSeriesOverrides": {
"thresholds": [
{
"to": 1,
"severity": "success"
},
{
"from": 1,
"to": 5,
"severity": "warning"
},
{
"from": 5,
"severity": "critical"
}
],
"seriesOverrides": [
{
"seriesName": "Error Rate %",
"from": 1,
"severity": "critical"
}
]
}
}
}
},
{
"type": "widget",
"props": {
"title": "Error rate over the last hour"
},
"content": {
"type": "visualization",
"id": "viz.line",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT percentage(count(*), WHERE error IS true) FROM Transaction TIMESERIES 1 minute SINCE 1 hour ago"
}
],
"legend": {
"enabled": false
},
"yAxisLeft": {
"zero": true
},
"thresholds": {
"isLabelVisible": true,
"thresholds": [
{
"name": "Alert threshold",
"from": 5,
"severity": "critical"
}
]
}
}
}
},
{
"type": "widget",
"props": {
"title": "Slowest transactions"
},
"content": {
"type": "visualization",
"id": "viz.table",
"props": {
"nrqlQueries": [
{
"accountIds": [
1234567
],
"query": "SELECT average(duration)*1000 AS 'Avg ms', max(duration)*1000 AS 'Max ms', count(*) AS 'Calls' FROM Transaction FACET name SINCE 30 minutes ago ORDER BY average(duration) DESC LIMIT 20"
}
],
"initialSorting": {
"name": "Avg ms",
"direction": "desc"
},
"thresholds": [
{
"columnName": "Avg ms",
"from": 500,
"severity": "critical"
},
{
"columnName": "Avg ms",
"from": 200,
"to": 500,
"severity": "warning"
}
]
}
}
},
{
"type": "widget",
"content": {
"type": "visualization",
"id": "viz.markdown",
"props": {
"text": "## Findings\n\n_Record what you've found - what's causing the spike, affected services, timeline._\n\n## Action Items\n\n- [ ] Identify root cause\n- [ ] Notify stakeholders\n- [ ] Apply mitigation\n- [ ] Schedule post-mortem"
}
}
}
]
}
]
}
Create Notebook Resource
Resources are created with functions called constructors. To learn more about declaring and configuring resources, see Resources.
Constructor syntax
new Notebook(name: string, args: NotebookArgs, opts?: CustomResourceOptions);@overload
def Notebook(resource_name: str,
args: NotebookArgs,
opts: Optional[ResourceOptions] = None)
@overload
def Notebook(resource_name: str,
opts: Optional[ResourceOptions] = None,
content: Optional[str] = None,
title: Optional[str] = None)func NewNotebook(ctx *Context, name string, args NotebookArgs, opts ...ResourceOption) (*Notebook, error)public Notebook(string name, NotebookArgs args, CustomResourceOptions? opts = null)
public Notebook(String name, NotebookArgs args)
public Notebook(String name, NotebookArgs args, CustomResourceOptions options)
type: newrelic:Notebook
properties: # The arguments to resource properties.
options: # Bag of options to control resource's behavior.
resource "newrelic_notebook" "name" {
# resource properties
}Parameters
- name string
- The unique name of the resource.
- args NotebookArgs
- The arguments to resource properties.
- opts CustomResourceOptions
- Bag of options to control resource's behavior.
- resource_name str
- The unique name of the resource.
- args NotebookArgs
- The arguments to resource properties.
- opts ResourceOptions
- Bag of options to control resource's behavior.
- ctx Context
- Context object for the current deployment.
- name string
- The unique name of the resource.
- args NotebookArgs
- The arguments to resource properties.
- opts ResourceOption
- Bag of options to control resource's behavior.
- name string
- The unique name of the resource.
- args NotebookArgs
- The arguments to resource properties.
- opts CustomResourceOptions
- Bag of options to control resource's behavior.
- name String
- The unique name of the resource.
- args NotebookArgs
- The arguments to resource properties.
- options CustomResourceOptions
- Bag of options to control resource's behavior.
Constructor example
The following reference example uses placeholder values for all input properties.
var notebookResource = new NewRelic.Notebook("notebookResource", new()
{
Content = "string",
Title = "string",
});
example, err := newrelic.NewNotebook(ctx, "notebookResource", &newrelic.NotebookArgs{
Content: pulumi.String("string"),
Title: pulumi.String("string"),
})
resource "newrelic_notebook" "notebookResource" {
lifecycle {
create_before_destroy = true
}
content = "string"
title = "string"
}
var notebookResource = new Notebook("notebookResource", NotebookArgs.builder()
.content("string")
.title("string")
.build());
notebook_resource = newrelic.Notebook("notebookResource",
content="string",
title="string")
const notebookResource = new newrelic.Notebook("notebookResource", {
content: "string",
title: "string",
});
type: newrelic:Notebook
properties:
content: string
title: string
Notebook Resource Properties
To learn more about resource properties and how to use them, see Inputs and Outputs in the Architecture and Concepts docs.
Inputs
In Python, inputs that are objects can be passed either as argument classes or as dictionary literals.
The Notebook resource accepts the following input properties:
- Content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - Title string
- The title of the notebook. Must be unique within the organization.
- Content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - Title string
- The title of the notebook. Must be unique within the organization.
- content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - title string
- The title of the notebook. Must be unique within the organization.
- content String
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - title String
- The title of the notebook. Must be unique within the organization.
- content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - title string
- The title of the notebook. Must be unique within the organization.
- content String
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - title String
- The title of the notebook. Must be unique within the organization.
Outputs
All input properties are implicitly available as output properties. Additionally, the Notebook resource produces the following output properties:
- Blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- Guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- Id string
- The provider-assigned unique ID for this managed resource.
- Organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- Blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- Guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- Id string
- The provider-assigned unique ID for this managed resource.
- Organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- blob_
id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- id string
- The provider-assigned unique ID for this managed resource.
- organization_
id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- blob
Id String - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- guid String
- The unique entity identifier (GUID) of the notebook in New Relic.
- id String
- The provider-assigned unique ID for this managed resource.
- organization
Id String - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- id string
- The provider-assigned unique ID for this managed resource.
- organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- blob_
id str - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- guid str
- The unique entity identifier (GUID) of the notebook in New Relic.
- id str
- The provider-assigned unique ID for this managed resource.
- organization_
id str - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- blob
Id String - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- guid String
- The unique entity identifier (GUID) of the notebook in New Relic.
- id String
- The provider-assigned unique ID for this managed resource.
- organization
Id String - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
Look up Existing Notebook Resource
Get an existing Notebook resource’s state with the given name, ID, and optional extra properties used to qualify the lookup.
public static get(name: string, id: Input<ID>, state?: NotebookState, opts?: CustomResourceOptions): Notebook@staticmethod
def get(resource_name: str,
id: str,
opts: Optional[ResourceOptions] = None,
blob_id: Optional[str] = None,
content: Optional[str] = None,
guid: Optional[str] = None,
organization_id: Optional[str] = None,
title: Optional[str] = None) -> Notebookfunc GetNotebook(ctx *Context, name string, id IDInput, state *NotebookState, opts ...ResourceOption) (*Notebook, error)public static Notebook Get(string name, Input<string> id, NotebookState? state, CustomResourceOptions? opts = null)public static Notebook get(String name, Output<String> id, NotebookState state, CustomResourceOptions options)resources: _: type: newrelic:Notebook get: id: ${id}import {
to = newrelic_notebook.example
id = "${id}"
}
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- resource_name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- name
- The unique name of the resulting resource.
- id
- The unique provider ID of the resource to lookup.
- state
- Any extra arguments used during the lookup.
- opts
- A bag of options that control this resource's behavior.
- Blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- Content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - Guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- Organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- Title string
- The title of the notebook. Must be unique within the organization.
- Blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- Content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - Guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- Organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- Title string
- The title of the notebook. Must be unique within the organization.
- blob_
id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- organization_
id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- title string
- The title of the notebook. Must be unique within the organization.
- blob
Id String - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- content String
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - guid String
- The unique entity identifier (GUID) of the notebook in New Relic.
- organization
Id String - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- title String
- The title of the notebook. Must be unique within the organization.
- blob
Id string - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- content string
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - guid string
- The unique entity identifier (GUID) of the notebook in New Relic.
- organization
Id string - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- title string
- The title of the notebook. Must be unique within the organization.
- blob_
id str - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- content str
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - guid str
- The unique entity identifier (GUID) of the notebook in New Relic.
- organization_
id str - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- title str
- The title of the notebook. Must be unique within the organization.
- blob
Id String - The blob identifier of the current notebook content, updated after each Terraform-managed write.
- content String
- The notebook body as a JSON string. Accepts the raw JSON exported from the New Relic UI, a
file()reference, or ajsonencode({...})expression. Produces line-level diffs of the normalized JSON inpulumi preview. - guid String
- The unique entity identifier (GUID) of the notebook in New Relic.
- organization
Id String - The New Relic organization ID the notebook belongs to. Resolved automatically from the provider credentials.
- title String
- The title of the notebook. Must be unique within the organization.
Import
Notebooks can be imported using their entity GUID:
$ pulumi import newrelic:index/notebook:Notebook example <guid>
After importing, run pulumi preview. The plan will show no changes if the content in your configuration matches the normalized content fetched from the API.
To learn more about importing existing cloud resources, see Importing resources.
Package Details
- Repository
- New Relic pulumi/pulumi-newrelic
- License
- Apache-2.0
- Notes
- This Pulumi package is based on the
newrelicTerraform Provider.
published on Saturday, Sep 19, 2026 by Pulumi