Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions plugins/OpenSearch/v1/README.md

This file was deleted.

18 changes: 18 additions & 0 deletions plugins/OpenSearch/v1/configValidation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"steps": [
{
"displayName": "Connect and authenticate",
"dataStream": { "name": "clusterInfo" },
"required": true,
"error": "Could not connect to OpenSearch. Check the Instance URL is reachable (from the relay agent, if one is selected), the credentials are valid, and whether Ignore certificate errors is needed for a self-signed certificate.",
"success": "Connected to OpenSearch."
},
{
"displayName": "Check cluster monitoring access",
"dataStream": { "name": "clusterHealth" },
"required": false,
"error": "Could not read cluster health. The cluster, node and index data streams need the readall_and_monitor role or equivalent monitoring permissions. Searching needs read permission on the indices queried, which this check does not test.",
"success": "Cluster monitoring permissions confirmed."
}
]
}
23 changes: 23 additions & 0 deletions plugins/OpenSearch/v1/custom_types.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[
{
"name": "Node",
"sourceType": "Node",
"icon": "server",
"singular": "Node",
"plural": "Nodes"
},
{
"name": "Index",
"sourceType": "Index",
"icon": "table-list",
"singular": "Index",
"plural": "Indices"
},
{
"name": "Service",
"sourceType": "Service",
"icon": "gears",
"singular": "Service",
"plural": "Services"
}
]
38 changes: 38 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/clusterHealth.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "clusterHealth",
"displayName": "Cluster Health",
"description": "Current cluster status with node and shard counts",
"tags": ["Cluster", "Health"],
"baseDataSourceName": "httpRequestUnscoped",
"config": {
"httpMethod": "get",
"endpointPath": "_cluster/health",
"getArgs": [],
"headers": []
},
"matches": "none",
"timeframes": false,
"metadata": [
{ "name": "cluster_name", "displayName": "Cluster", "shape": "string", "role": "label" },
{
"name": "status",
"displayName": "Status",
"shape": ["state", { "map": { "success": ["green"], "warning": ["yellow"], "error": ["red"] } }],
"role": "value"
},
{ "name": "number_of_nodes", "displayName": "Nodes", "shape": "number" },
{ "name": "number_of_data_nodes", "displayName": "Data Nodes", "shape": "number" },
{ "name": "active_primary_shards", "displayName": "Active Primary Shards", "shape": "number" },
{ "name": "active_shards", "displayName": "Active Shards", "shape": "number" },
{ "name": "relocating_shards", "displayName": "Relocating Shards", "shape": "number" },
{ "name": "initializing_shards", "displayName": "Initializing Shards", "shape": "number" },
{ "name": "unassigned_shards", "displayName": "Unassigned Shards", "shape": "number" },
{ "name": "delayed_unassigned_shards", "displayName": "Delayed Unassigned Shards", "shape": "number" },
{ "name": "active_shards_percent_as_number", "displayName": "Active Shards (%)", "shape": ["percent", { "decimalPlaces": 1 }] },
{ "name": "number_of_pending_tasks", "displayName": "Pending Tasks", "shape": "number" },
{ "name": "number_of_in_flight_fetch", "displayName": "In-flight Fetches", "shape": "number" },
{ "name": "task_max_waiting_in_queue_millis", "displayName": "Longest Task Wait", "shape": "milliseconds" },
{ "name": "discovered_cluster_manager", "displayName": "Cluster Manager Discovered", "shape": "boolean" },
{ "name": "timed_out", "displayName": "Timed Out", "shape": "boolean", "visible": false }
]
}
26 changes: 26 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/clusterInfo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "clusterInfo",
"displayName": "Cluster Info",
"description": "Cluster name, UUID and OpenSearch version",
"tags": ["Cluster"],
"baseDataSourceName": "httpRequestUnscoped",
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "",
"getArgs": [],
"headers": []
},
"matches": "none",
"timeframes": false,
"metadata": [
{ "name": "cluster_name", "displayName": "Cluster", "shape": "string", "role": "label" },
{ "name": "name", "displayName": "Responding Node", "shape": "string" },
{ "name": "version.number", "displayName": "Version", "shape": "string", "role": "value" },
{ "name": "version.distribution", "displayName": "Distribution", "shape": "string" },
{ "name": "version.build_type", "displayName": "Build Type", "shape": "string" },
{ "name": "version.build_date", "displayName": "Build Date", "shape": "date" },
{ "name": "version.lucene_version", "displayName": "Lucene Version", "shape": "string" },
{ "name": "cluster_uuid", "displayName": "Cluster UUID", "shape": "string", "visible": false }
]
}
57 changes: 57 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/documentCount.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "documentCount",
"displayName": "Document Count",
"description": "Number of documents in one or more indices, optionally matching a query",
"tags": ["Search"],
"baseDataSourceName": "httpRequestUnscoped",
"matches": "none",
"manualConfigApply": true,
"config": {
"httpMethod": "post",
"endpointPath": "{{index}}/_count",
"getArgs": [],
"headers": [],
"postBody": "{{ (() => { let raw = typeof query === 'undefined' || query === null || query === '' ? {} : query; if (typeof raw === 'string') { try { raw = JSON.parse(raw); } catch (e) { raw = {}; } } const clause = raw && raw.query ? raw.query : (raw && Object.keys(raw).length ? raw : { match_all: {} }); const field = typeof timeField === 'string' ? timeField.trim() : ''; const tf = typeof timeframe !== 'undefined' ? timeframe : null; if (!field || !tf || !tf.start || tf.enum === 'none') { return { query: clause }; } return { query: { bool: { must: [ clause ], filter: [ { range: { [field]: { gte: tf.start, lte: tf.end, format: 'strict_date_optional_time' } } } ] } } }; })() }}",
"errorHandling": { "type": "path", "realm": "payload", "path": "error.root_cause.0.reason" }
},
"ui": [
{
"name": "index",
"type": "autocomplete",
"label": "Index",
"validation": {
"required": true
},
"placeholder": "Select an index or pattern",
"isMulti": false,
"allowCustomValues": true,
"data": {
"source": "dataStream",
"dataStreamName": "indexNames",
"dataSourceConfig": {}
}
},
{
"name": "query",
"type": "json",
"label": "Query",
"defaultValue": {
"match_all": {}
},
"help": "Accepts a Query DSL clause, or a request body with a query property."
},
{
"name": "timeField",
"type": "text",
"label": "Time field",
"placeholder": "@timestamp",
"help": "Counts only documents in the tile's timeframe using this date field. Leave empty to ignore the timeframe."
}
],
"supportsNoneTimeframe": true,
"requiresParameterTimeframe": true,
"defaultTimeframe": "none",
"metadata": [
{ "name": "count", "displayName": "Documents", "shape": ["number", { "decimalPlaces": 0, "thousandsSeparator": true }], "role": "value" }
]
}
25 changes: 25 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/indexNames.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "indexNames",
"displayName": "Index Names",
"description": "Open, non-system index names, with wildcard patterns for date-suffixed index families",
"tags": ["Indices"],
"baseDataSourceName": "httpRequestUnscoped",
"config": {
"httpMethod": "get",
"endpointPath": "_cat/indices/*,-.*",
"getArgs": [
{ "key": "format", "value": "json" },
{ "key": "expand_wildcards", "value": "open" },
{ "key": "s", "value": "index" },
{ "key": "h", "value": "index" }
],
"postRequestScript": "indexNames.js"
},
"matches": "none",
"timeframes": false,
"visibility": { "type": "hidden" },
"metadata": [
{ "name": "value", "displayName": "Index", "shape": "string", "role": "value", "visible": false },
{ "name": "label", "displayName": "Index", "shape": "string", "role": "label" }
]
}
54 changes: 39 additions & 15 deletions plugins/OpenSearch/v1/dataStreams/indices.json
Original file line number Diff line number Diff line change
@@ -1,26 +1,50 @@
{
"name": "indices",
"displayName": "Indices",
"description": "Health, status, shard, document and storage statistics for each index (system indices excluded)",
"tags": ["Cluster", "Indices"],
"baseDataSourceName": "httpRequestUnscoped",
"config": {
"httpMethod": "get",
"expandInnerObjects": true,
"endpointPath": "_cat/indices",
"pathToData": "",
"getArgs": [],
"headers": []
"endpointPath": "_cat/indices/{{ (typeof index !== 'undefined' && Array.isArray(index) && index.length) ? index.map((o) => [].concat(o.rawId)[0]).join(',') : '*,-.*' }}",
"getArgs": [
{ "key": "format", "value": "json" },
{ "key": "bytes", "value": "b" },
{ "key": "expand_wildcards", "value": "open,closed" },
{ "key": "ignore_unavailable", "value": "true" },
{ "key": "s", "value": "index" },
{
"key": "h",
"value": "index,uuid,health,status,pri,rep,docs.count,docs.deleted,store.size,pri.store.size,creation.date.string"
}
]
},
"timeframes": false,
"matches": "none",
"visibility": {
"type": "hidden"
},
"metadata": [
"ui": [
{
"name": "index",
"shape": "string",
"displayName": "Index",
"role": "value"
"type": "objects",
"name": "index",
"label": "Index (optional)",
"matches": { "sourceType": { "type": "equals", "value": "Index" } }
}
],
"timeframes": false,
"metadata": [
{ "name": "index", "displayName": "Index", "shape": "string", "role": "label" },
{ "sourceId": "index", "sourceType": "Index", "name": "index" },
{
"name": "health",
"displayName": "Health",
"shape": ["state", { "map": { "success": ["green"], "warning": ["yellow"], "error": ["red"] } }]
},
{ "name": "status", "displayName": "Status", "shape": ["state", { "map": { "success": ["open"], "unknown": ["close"] } }] },
{ "name": "docs.count", "displayName": "Documents", "shape": ["number", { "decimalPlaces": 0, "thousandsSeparator": true }], "role": "value" },
{ "name": "docs.deleted", "displayName": "Deleted Documents", "shape": ["number", { "decimalPlaces": 0, "thousandsSeparator": true }] },
{ "name": "store.size", "displayName": "Size", "shape": "bytes" },
{ "name": "pri.store.size", "displayName": "Primary Size", "shape": "bytes" },
{ "name": "pri", "displayName": "Primary Shards", "shape": ["number", { "decimalPlaces": 0 }] },
{ "name": "rep", "displayName": "Replicas", "shape": ["number", { "decimalPlaces": 0 }] },
{ "name": "creation.date.string", "displayName": "Created", "shape": "date" },
{ "name": "uuid", "displayName": "UUID", "shape": "string", "visible": false }
]
}
}
56 changes: 56 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/nodes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"name": "nodes",
"displayName": "Nodes",
"description": "Current heap, memory, CPU, load and disk usage for each node in the cluster",
"tags": ["Cluster", "Nodes"],
"baseDataSourceName": "httpRequestUnscoped",
"config": {
"httpMethod": "get",
"endpointPath": "_cat/nodes",
"getArgs": [
{ "key": "format", "value": "json" },
{ "key": "full_id", "value": "true" },
{ "key": "bytes", "value": "b" },
{ "key": "time", "value": "ms" },
{ "key": "s", "value": "name" },
{
"key": "h",
"value": "id,name,ip,version,node.roles,cluster_manager,heap.percent,heap.current,heap.max,ram.percent,ram.current,ram.max,cpu,load_1m,load_5m,load_15m,disk.used,disk.total,disk.used_percent,uptime"
}
],
"postRequestScript": "nodes.js"
},
"matches": "none",
"ui": [
{
"type": "objects",
"name": "node",
"label": "Node (optional)",
"matches": { "sourceType": { "type": "equals", "value": "Node" } }
}
],
"timeframes": false,
"metadata": [
{ "name": "name", "displayName": "Node", "shape": "string", "role": "label" },
{ "sourceId": "id", "sourceType": "Node", "name": "name" },
{ "name": "id", "displayName": "Node ID", "shape": "string", "visible": false },
{ "name": "isClusterManager", "displayName": "Cluster Manager", "shape": "boolean" },
{ "name": "roles", "displayName": "Roles", "shape": ["array", { "itemShape": "string" }] },
{ "name": "heap.percent", "displayName": "Heap Used (%)", "shape": ["percent", { "decimalPlaces": 0 }], "role": "value" },
{ "name": "heap.current", "displayName": "Heap Used", "shape": "bytes" },
{ "name": "heap.max", "displayName": "Heap Max", "shape": "bytes" },
{ "name": "ram.percent", "displayName": "Memory Used (%)", "shape": ["percent", { "decimalPlaces": 0 }] },
{ "name": "ram.current", "displayName": "Memory Used", "shape": "bytes" },
{ "name": "ram.max", "displayName": "Memory Total", "shape": "bytes" },
{ "name": "cpu", "displayName": "CPU (%)", "shape": ["percent", { "decimalPlaces": 0 }] },
{ "name": "load_1m", "displayName": "Load (1m)", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "load_5m", "displayName": "Load (5m)", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "load_15m", "displayName": "Load (15m)", "shape": ["number", { "decimalPlaces": 2 }] },
{ "name": "disk.used_percent", "displayName": "Disk Used (%)", "shape": ["percent", { "decimalPlaces": 1 }] },
{ "name": "disk.used", "displayName": "Disk Used", "shape": "bytes" },
{ "name": "disk.total", "displayName": "Disk Total", "shape": "bytes" },
{ "name": "uptime", "displayName": "Uptime", "shape": ["milliseconds", { "formatDuration": true }] },
{ "name": "version", "displayName": "Version", "shape": "string" },
{ "name": "ip", "displayName": "IP Address", "shape": "string" }
]
}
26 changes: 26 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/scripts/indexNames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Time-series data usually lands in one index per day or rollover (otel-logs-2026.10.16,
// logs-000042), so offer a wildcard pattern for each family ahead of the individual names.
const FAMILY = [
/^(.+?[-_.])[0-9]{4}[-_.][0-9]{2}([-_.][0-9]{2})?([-_.].*)?$/, // date suffix
/^(.+?[-_])[0-9]{6}$/ // rollover counter
];

const names = (data || []).map((r) => r.index).filter(Boolean);
const families = new Map();
for (const name of names) {
for (const pattern of FAMILY) {
const match = name.match(pattern);
if (match) {
const wildcard = `${match[1]}*`;
families.set(wildcard, (families.get(wildcard) || 0) + 1);
break;
}
}
}

result = [
...[...families.entries()]
.filter(([, count]) => count > 1)
.map(([wildcard, count]) => ({ value: wildcard, label: `${wildcard} (${count} indices)` })),
...names.map((name) => ({ value: name, label: name }))
];
14 changes: 14 additions & 0 deletions plugins/OpenSearch/v1/dataStreams/scripts/nodes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// _cat/nodes has no node filter, so the optional Node picker is applied here.
// Selected objects arrive as an array, each rawId a single-element array.
const unwrap = (v) => (Array.isArray(v) ? v[0] : v);
const selected = (context.config && context.config.node) || [];
const nodeIds = new Set(selected.map((o) => unwrap(o.rawId)).filter(Boolean));

result = (data || [])
.filter((n) => nodeIds.size === 0 || nodeIds.has(n.id))
.map(({ 'node.roles': roles, cluster_manager: clusterManager, ...n }) => ({
...n,
roles: roles ? roles.split(',') : [],
// The elected cluster manager is marked "*", other nodes "-"
isClusterManager: clusterManager === '*'
}));
Loading
Loading