From 8cf5f458fa20e8c91f6d6cc3849575cb635d96cb Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Tue, 25 Nov 2025 10:50:28 +0545 Subject: [PATCH 1/8] improve views docs --- .../guide/views/concepts/cache-control.md | 254 ++++++- .../docs/guide/views/concepts/panels.md | 102 --- .../docs/guide/views/concepts/queries.md | 49 -- .../docs/guide/views/concepts/tables.md | 301 -------- .../docs/guide/views/concepts/templating.md | 466 +++++++++++++ mission-control/docs/guide/views/index.md | 18 +- .../docs/guide/views/queries/changes.md | 551 +++++++++++++++ .../docs/guide/views/queries/configs.md | 498 ++++++++++++++ .../docs/guide/views/queries/index.mdx | 11 + .../docs/guide/views/queries/prometheus.md | 650 ++++++++++++++++++ .../views/queries/view-table-selector.md | 591 ++++++++++++++++ .../docs/guide/views/table/badge.md | 547 +++++++++++++++ .../docs/guide/views/table/boolean.md | 370 ++++++++++ .../docs/guide/views/table/bytes.md | 488 +++++++++++++ .../docs/guide/views/table/config-item.md | 608 ++++++++++++++++ .../docs/guide/views/table/datetime.md | 408 +++++++++++ .../docs/guide/views/table/decimal.md | 518 ++++++++++++++ .../docs/guide/views/table/duration.md | 422 ++++++++++++ .../docs/guide/views/table/gauge.md | 567 +++++++++++++++ .../docs/guide/views/table/health.md | 410 +++++++++++ .../docs/guide/views/table/index.mdx | 11 + .../docs/guide/views/table/millicore.md | 418 +++++++++++ .../docs/guide/views/table/number.md | 330 +++++++++ .../docs/guide/views/table/status.md | 424 ++++++++++++ .../docs/guide/views/table/string.md | 314 +++++++++ mission-control/docs/guide/views/table/url.md | 518 ++++++++++++++ mission-control/package-lock.json | 76 +- 27 files changed, 9418 insertions(+), 502 deletions(-) delete mode 100644 mission-control/docs/guide/views/concepts/panels.md delete mode 100644 mission-control/docs/guide/views/concepts/queries.md delete mode 100644 mission-control/docs/guide/views/concepts/tables.md create mode 100644 mission-control/docs/guide/views/concepts/templating.md create mode 100644 mission-control/docs/guide/views/queries/changes.md create mode 100644 mission-control/docs/guide/views/queries/configs.md create mode 100644 mission-control/docs/guide/views/queries/index.mdx create mode 100644 mission-control/docs/guide/views/queries/prometheus.md create mode 100644 mission-control/docs/guide/views/queries/view-table-selector.md create mode 100644 mission-control/docs/guide/views/table/badge.md create mode 100644 mission-control/docs/guide/views/table/boolean.md create mode 100644 mission-control/docs/guide/views/table/bytes.md create mode 100644 mission-control/docs/guide/views/table/config-item.md create mode 100644 mission-control/docs/guide/views/table/datetime.md create mode 100644 mission-control/docs/guide/views/table/decimal.md create mode 100644 mission-control/docs/guide/views/table/duration.md create mode 100644 mission-control/docs/guide/views/table/gauge.md create mode 100644 mission-control/docs/guide/views/table/health.md create mode 100644 mission-control/docs/guide/views/table/index.mdx create mode 100644 mission-control/docs/guide/views/table/millicore.md create mode 100644 mission-control/docs/guide/views/table/number.md create mode 100644 mission-control/docs/guide/views/table/status.md create mode 100644 mission-control/docs/guide/views/table/string.md create mode 100644 mission-control/docs/guide/views/table/url.md diff --git a/mission-control/docs/guide/views/concepts/cache-control.md b/mission-control/docs/guide/views/concepts/cache-control.md index 3edc7ba6..6438f7a7 100644 --- a/mission-control/docs/guide/views/concepts/cache-control.md +++ b/mission-control/docs/guide/views/concepts/cache-control.md @@ -1,31 +1,23 @@ --- title: Cache Control -sidebar_position: 4 sidebar_custom_props: - icon: material-symbols:cached + icon: mdi:cached --- -Views implement a caching system that stores query results in dedicated database tables for fast retrieval and extra filtering. -You can control cache behavior through both view configuration and HTTP headers. +Views implement intelligent caching to minimize unnecessary data refreshes while keeping data reasonably fresh. Cache control settings help you balance data freshness with performance. -## How View Caching Works +## Overview -Views work like materialized views in traditional databases: +When a view is requested, the system follows this process: -1. User requests view data -2. System looks for cached data in the view's database table -3. If data exists and hasn't expired, return immediately - - **Cache Miss/Expired**: Execute view queries and wait up to `refreshTimeout` -4. **Timeout Handling**: If refresh exceeds timeout: - - Return stale data if available - - Return error if no cached data exists -5. **Hard Timeout Limit**: Refresh operations have a hard limit of 1 minute regardless of configuration +1. **Check cache validity** - Is the cached data still fresh? +2. **Return or refresh** - If fresh, return cached data; if stale, trigger a refresh +3. **Handle refresh timeout** - If refresh takes too long, return stale data instead +4. **Store results** - New data is cached for subsequent requests -## Cache Configuration +## Configuration -### View-Level Settings - -Configure cache behavior in your view specification: +Cache is configured in the view's `spec` section: ```yaml apiVersion: mission-control.flanksource.com/v1 @@ -34,21 +26,219 @@ metadata: name: my-view spec: cache: - maxAge: '30m' # Maximum cache age before refresh (default: 15m) - minAge: '30s' # Minimum age clients can request (default: 10s) - refreshTimeout: '10s' # How long to wait for refresh (default: 5s) - queries: - # ... your queries + # Maximum age before cache is considered stale (default: 15m) + maxAge: 15m + + # Minimum age a user can request refresh (default: 10s) + # Prevents over-refreshing from rapid user requests + minAge: 10s + + # Timeout for refresh operations (default: 5s) + # If refresh takes longer, stale data is returned instead + refreshTimeout: 5s +``` + +## Cache Parameters + +### maxAge +The maximum age of cached data before it's considered stale and needs refresh. + +- **Default**: `15m` +- **Format**: Go duration (e.g., `5m`, `1h`, `30s`) +- **Effect**: Determines how fresh your data is + - Shorter duration: More frequent refreshes, fresher data, higher load + - Longer duration: Less frequent refreshes, potentially stale data, lower load + +**Example**: +```yaml +cache: + maxAge: 5m # Refresh at least every 5 minutes +``` + +### minAge +The minimum age cached data must reach before a user can request a manual refresh. This prevents over-refreshing from rapid user clicks. + +- **Default**: `10s` +- **Format**: Go duration +- **Effect**: Throttles refresh requests from users + - Users cannot force a refresh faster than this interval + - Helps prevent accidental load spikes from aggressive clicking + +**Example**: +```yaml +cache: + minAge: 30s # Users can only refresh every 30 seconds +``` + +### refreshTimeout +How long to wait for a refresh operation to complete. If the refresh takes longer, stale data is returned instead of waiting. + +- **Default**: `5s` +- **Format**: Go duration +- **Effect**: Ensures response times don't degrade when refresh is slow + - Shorter timeout: Faster responses, but may return stale data + - Longer timeout: Fresher data, but slower responses if refresh is slow + +**Example**: +```yaml +cache: + refreshTimeout: 2s # Return stale data if refresh takes > 2 seconds +``` + +## Per-Variable Caching + +Each unique combination of template variables creates a separate cache entry. This allows different filters to maintain independent cache lifespans. + +**Example**: A view with a "cluster" variable will maintain separate cached data for: +- cluster=us-east-1 +- cluster=us-west-2 +- cluster=eu-central-1 + +Each cluster's data is cached independently, allowing users to switch between clusters without invalidating other cached results. + +## Cache Behavior Examples + +### Example 1: Fresh Data Request +``` +User requests view + ↓ +Cache check: Data is 5 minutes old, maxAge=15m + ↓ +Cache is valid → Return cached data immediately + ↓ +Response time: ~10ms +``` + +### Example 2: Stale Data with Quick Refresh +``` +User requests view + ↓ +Cache check: Data is 20 minutes old, maxAge=15m + ↓ +Cache is stale → Trigger refresh with 2s timeout + ↓ +Refresh completes in 1.5 seconds + ↓ +Return fresh data → Cache updated + ↓ +Response time: ~1.5s +``` + +### Example 3: Stale Data with Slow Refresh +``` +User requests view + ↓ +Cache check: Data is 20 minutes old, maxAge=15m + ↓ +Cache is stale → Trigger refresh with 2s timeout + ↓ +Refresh takes 4 seconds (slower than timeout) + ↓ +Timeout triggers after 2 seconds + ↓ +Return stale cached data instead of waiting + ↓ +Response time: ~2s + ↓ +Refresh continues in background, updates cache ``` -### Default Values +### Example 4: Manual Refresh Throttling +``` +User clicks refresh button + ↓ +Check minAge: Last refresh was 2 seconds ago, minAge=10s + ↓ +Too soon → Ignore refresh request + ↓ +User must wait 8 more seconds before refresh is allowed +``` + +## Recommended Settings + +### High-Frequency Monitoring (Every Minute) +Use shorter cache times for real-time dashboards: + +```yaml +cache: + maxAge: 1m + minAge: 10s + refreshTimeout: 5s +``` + +### Typical Dashboard (Every 5-15 Minutes) +Standard balance of freshness and performance: + +```yaml +cache: + maxAge: 15m + minAge: 30s + refreshTimeout: 5s +``` + +### Low-Frequency Reference Data (Hourly) +For relatively static data: + +```yaml +cache: + maxAge: 1h + minAge: 1m + refreshTimeout: 10s +``` + +### Real-Time Critical (Seconds) +For mission-critical live data: + +```yaml +cache: + maxAge: 30s + minAge: 5s + refreshTimeout: 2s +``` + +## Performance Impact + +Cache settings directly affect system performance: + +| Setting | ↓ Latency | ↓ Load | ↓ Freshness | +|---------|-----------|--------|------------| +| Shorter maxAge | ✗ | ✗ | ✓ | +| Longer maxAge | ✓ | ✓ | ✗ | +| Shorter refreshTimeout | ✓ | ✗ | ✗ | +| Longer refreshTimeout | ✗ | ✓ | ✓ | +| Higher minAge | ✓ | ✓ | ✗ | +| Lower minAge | ✗ | ✗ | ✓ | + +## Default Configuration + +If you don't specify cache settings, Mission Control uses these defaults: + +```yaml +cache: + maxAge: 15m # Refresh at least every 15 minutes + minAge: 10s # Throttle user refreshes to every 10 seconds + refreshTimeout: 5s # Return stale data if refresh takes > 5 seconds +``` + +These defaults work well for most use cases and provide a good balance between data freshness and system performance. + +## Cache Deduplication + +Mission Control uses **singleflight deduplication** to prevent multiple concurrent refresh requests for the same view and variable combination. This means: + +- If 10 users request the same view at the same time +- Only one database query is executed +- All 10 users receive the same cached result +- Significantly reduces database load + +## Cache Storage -| Setting | Default | Description | -| ---------------- | ---------- | ------------------------------------------ | -| `maxAge` | 15 minutes | Cache expires after this duration | -| `minAge` | 10 seconds | Minimum cache age that clients can request | -| `refreshTimeout` | 5 seconds | Timeout for background refresh operations | +View cache data is stored in: +- **Primary storage**: PostgreSQL database (persistent) +- **Format**: `view__` table per view +- **Tracking**: Request fingerprint (SHA256 hash of variable map) identifies unique variable combinations -:::info Hard Timeout Limit -Regardless of the configured `refreshTimeout`, view refresh operations have a hard limit of **1 minute**. This prevents long-running queries from blocking the system. -::: +This allows: +- Data to survive service restarts +- PostgREST API access to view data +- Historical tracking of different variable combinations diff --git a/mission-control/docs/guide/views/concepts/panels.md b/mission-control/docs/guide/views/concepts/panels.md deleted file mode 100644 index c4d11d78..00000000 --- a/mission-control/docs/guide/views/concepts/panels.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Panels -sidebar_position: 3 -sidebar_custom_props: - icon: material-symbols:dashboard ---- - -Views support different panel types for visualizing aggregated data. -Panels create interactive visualizations from your data sources and you can configure them with various display options. - -## Panel Types - -Views support the following panel types: - -- `piechart` - Pie chart visualizations for distribution analysis -- `table` - Tabular data presentations -- `number` - Single metric displays with units -- `gauge` - Gauge visualizations with thresholds - -## Basic Panel Structure - -All panels share a common structure. Here's an example from the gauge panel fixture: - -```yaml title="gauge.yaml" file=/modules/mission-control/fixtures/views/panels/gauge.yaml - -``` - -## Panel Configuration - -### Pie Chart - -Pie charts show data distribution across categories: - - - -```yaml title="piechart.yaml" file=/modules/mission-control/fixtures/views/panels/piechart.yaml - -``` - -#### Pie Chart Properties - -- `showLabels`: Display labels on pie slices -- `colors`: Custom color mapping for categories - -### Gauge - -Gauges display metrics with threshold-based color coding: - -```yaml title="gauge.yaml" file=/modules/mission-control/fixtures/views/panels/gauge.yaml - -``` - -#### Gauge Properties - -- `min`: Minimum value for the gauge -- `max`: Maximum value for the gauge -- `thresholds`: Array of threshold objects with `value` and `color` - -#### Supported Threshold Colors - -- `green` - Success/healthy state -- `yellow` - Warning state -- `red` - Critical/error state -- `blue` - Info state -- Custom hex colors (e.g., `#28C19B`) - -### Number - -Number panels display single metrics with units: - - - -```yaml title="number.yaml" file=/modules/mission-control/fixtures/views/panels/number.yaml - -``` - -#### Number Properties - -- `unit`: Display unit (e.g., "seconds", "MB", "%") -- `precision`: Number of decimal places - -### Table - -Tables display aggregated data in rows and columns: - - - -```yaml title="table.yaml" file=/modules/mission-control/fixtures/views/panels/table.yaml - -``` - -## Panel Queries - -Panels use SQL queries to aggregate data from the view's named queries. Each panel executes its SQL query against the data sources defined in the view's `queries` section. - -### Query Structure - -Panels reference query names as tables in SQL. Here's how the gauge example works: - -```yaml title="gauge.yaml" file=/modules/mission-control/fixtures/views/panels/gauge.yaml - -``` diff --git a/mission-control/docs/guide/views/concepts/queries.md b/mission-control/docs/guide/views/concepts/queries.md deleted file mode 100644 index 3b69f1d7..00000000 --- a/mission-control/docs/guide/views/concepts/queries.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Queries -sidebar_position: 1 -sidebar_custom_props: - icon: material-symbols:query-stats ---- - -Views use a powerful query system to aggregate and transform data from multiple sources. You can query config items, changes, and metrics to populate your views. - -## Query Types - -### Config Queries - -Query config items from your catalog: - -```yaml title="deployments.yaml" file=/modules/mission-control/fixtures/views/deployments.yaml {54-60} - -``` - -### Change Queries - -Query configuration changes and audit data: - -```yaml title="backups.yaml" file=/modules/mission-control/fixtures/views/backups.yaml {29-33} - -``` - -### Metric Queries - -Query time-series data from Prometheus and other sources. Metric queries are not yet implemented in the current version, but the structure would be: - -```yaml title="resource-usage.yaml" file=/modules/mission-control/fixtures/views/panels/resource-usage.yaml {7-15} - -``` - -## Multi-Source Queries - -Views can combine data from different sources and use SQL queries in panels to aggregate and analyze the data: - -```yaml title="pipelines.yaml" file=/modules/mission-control/fixtures/views/pipelines.yaml - -``` - -This example shows: - -- **Multiple query sources**: Combining workflow runs from changes -- **Panel queries**: Using SQL to aggregate repository data -- **CEL expressions**: Complex duration calculations in mappings -- **Data aggregation**: `COUNT` (count) and `AVG` (average) functions in panel queries diff --git a/mission-control/docs/guide/views/concepts/tables.md b/mission-control/docs/guide/views/concepts/tables.md deleted file mode 100644 index cb5afbd6..00000000 --- a/mission-control/docs/guide/views/concepts/tables.md +++ /dev/null @@ -1,301 +0,0 @@ ---- -title: Tables -sidebar_position: 2 -sidebar_custom_props: - icon: material-symbols:table-chart ---- - -A view can generate a single table. The table supports a rich set of column types that decide how data persists, displays, and formats in your dashboards. -Each column type provides specific formatting and visualization capabilities. - -## Columns - -Columns define the structure and data types of your view table. Each column has a name and type that determines how the data stores, displays, and formats in your dashboards. - -:::info -Column names must be valid SQL identifiers as they map directly to table columns in the underlying database. -::: - -### Column Properties - -Each column definition supports several properties: - -- `name`: Column name (must be a valid SQL identifier) -- `type`: Data type that determines formatting and visualization -- `primaryKey`: Whether this column is part of the primary key (default: false) -- `description`: Human-readable description of the column -- `hidden`: Whether to hide the column from the UI (default: false) -- `for`: Reference to another column this column provides data for (helper columns) -- `gauge`: Configuration for gauge visualization (only for `gauge` type) - -### Column Types - -#### `string` - -Text data with no extra formatting. - -```yaml -columns: - - name: application_name - type: string - description: The name of the application -``` - -#### `number` - -Numeric values with automatic formatting. - -```yaml -columns: - - name: replica_count - type: number -``` - -#### `boolean` - -True/false values displayed as checkmarks or status indicators. - -```yaml -columns: - - name: is_active - type: boolean -``` - -#### `datetime` - -Timestamp values with automatic date/time formatting. - -```yaml -columns: - - name: last_deployed - type: datetime -``` - -#### `duration` - -Time duration values with human-readable formatting (e.g., "2h 30m"). - -```yaml -columns: - - name: uptime - type: duration -``` - -#### `health` - -Health status indicators with color-coded visual representation. - -```yaml -columns: - - name: component_health - type: health -``` - -#### `status` - -General status information with visual indicators. - -```yaml -columns: - - name: deployment_status - type: status -``` - -#### `decimal` - -Decimal numbers with configurable precision. - -```yaml -columns: - - name: cpu_usage - type: decimal -``` - -#### `bytes` - -Byte values with automatic unit conversion (B, KB, MB, GB). - -```yaml -columns: - - name: memory_usage - type: bytes -``` - -#### `millicore` - -CPU `millicore` values with proper formatting. - -```yaml -columns: - - name: cpu_request - type: millicore -``` - -#### `gauge` - -Rich gauge visualizations with thresholds and color coding. - -```yaml -columns: - - name: disk_usage - type: gauge - gauge: - min: 0 - max: 100 - thresholds: - - value: 70 - color: 'yellow' - - value: 85 - color: 'orange' - - value: 95 - color: 'red' -``` - -:::note Gauge Configuration Required -When using `type: gauge`, the `gauge` configuration block is **required**. -::: - -##### Gauge Properties - -- `min`: Minimum value for the gauge -- `max`: Maximum value for the gauge -- `thresholds`: Array of threshold objects with `value` and `color` - -#### `url` - -URL values that render as clickable links. - -```yaml -columns: - - name: dashboard_link - type: url -``` - -### Helper Columns - -Helper columns are extra columns that give data for other columns without rendering directly in the UI. They use the `for` field to reference the column they support. - -The most common use case is providing URLs for other columns. When a column has a helper column of type `url`, the main column becomes clickable and links to the URL provided by the helper column. - -```yaml -columns: - - name: component_name - type: string - primaryKey: true - - name: component_url - type: url - for: component_name # This URL will make component_name clickable -``` - -In this example: - -- `component_name` displays as a regular string column -- `component_url` provides the URL data but doesn't render as a separate column -- When rendered, `component_name` becomes a clickable link using the URL from `component_url` - -### Hidden Columns - -You can mark columns as `hidden: true` to prevent them from appearing as separate columns in the table while still being available for internal operations. Primary keys like `UUIDs` are good candidates to hide since they're needed for data operations but not useful for display. - -```yaml -columns: - - name: component_name - type: string - - name: component_id - type: string - primaryKey: true - hidden: true - description: Internal UUID for the component -``` - -### Primary Keys - -Each view table must specify at least one column as the primary key. Primary keys support internal purposes including data `deduplication` and table operations. You can have multiple primary keys to create composite primary keys. - -#### Single Primary Key - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - name: namespace - type: string - - name: status - type: string -``` - -#### Composite Primary Keys - -When you need multiple columns to uniquely identify a row: - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true # First part of composite key - - name: namespace - type: string - primaryKey: true # Second part of composite key - - name: status - type: string -``` - -## Data Mapping - -Data mapping defines how data from your query results gets transformed and assigned to specific table columns. - -:::info -Mapping is **optional** - if not specified, Mission Control automatically looks for column names directly in the query results. -::: - -### How Data Mapping Works - -When Mission Control executes your queries, it returns raw data objects. For each column, the system: - -1. **Checks for explicit mapping** → If a CEL expression defines the column -2. **Falls back to direct lookup** → Looks for the column name directly in the query results -3. **Defaults to null** → If neither mapping nor direct column name exists - -The mapping section uses [CEL (Common Expression Language)](/docs/reference/scripting/cel) expressions where the query result data is available as `row`. - -### Mapping Behavior - -#### Automatic Column Mapping - -If you specify no mapping, columns are automatically populated from query results: - -```yaml -columns: - - name: name - type: string - primaryKey: true - - name: status - type: string - - name: created_at - type: datetime -# No mapping section needed - columns will be populated from query results automatically -``` - -#### Explicit Mapping - -When you need data transformation or the column names don't match query results: - -```yaml -mapping: - name: row.component_name # Map from different field name - status: row.health # Map from different field name - created_at: row.created_at # Direct mapping (same as automatic) -``` - -### CEL Expression Context - -In mapping expressions, query result data is available as `row`: - -```yaml -mapping: - database: row.name # Access top-level fields - date: row.created_at # Direct field access - status: row.details.status # Navigate nested objects - source: row.source # Simple field mapping -``` diff --git a/mission-control/docs/guide/views/concepts/templating.md b/mission-control/docs/guide/views/concepts/templating.md new file mode 100644 index 00000000..016c168b --- /dev/null +++ b/mission-control/docs/guide/views/concepts/templating.md @@ -0,0 +1,466 @@ +--- +title: Variables +sidebar_custom_props: + icon: mdi:variable +--- + +Variables make views interactive by allowing users to dynamically control which data is fetched. Variables are defined in the `templating` section and their values are substituted into queries using the `$(var.)` syntax. + +## Overview + +Variables in Mission Control allow you to: + +- Create interactive dropdowns users can adjust +- Populate options from static lists or dynamic sources +- Build dependent variables (e.g., filter namespaces by cluster) +- Use variable values in queries to control what data is fetched +- Maintain separate cache entries per variable combination + +## Variables vs Column Filters + +Mission Control has two ways to filter view data. Both are server-side, but they operate at different stages: + +``` +┌─────────────────────────────────────┐ +│ Sources │ +│ (configs, prometheus, checks, etc) │ +└──────────────────┬──────────────────┘ + │ + ▼ + ┌──────────────────┐ + │ Execute Queries │ ◀── Variables filter here + └────────┬─────────┘ (only matching data is fetched) + │ + ▼ + ┌────────────────────┐ + │ In-memory SQLite │ + │ (joins/merge) │ + └──────────┬─────────┘ + │ + ▼ +┌─────────────────────────────────────┐ +│ PostgreSQL Table │ +│ (view__) │ +└──────────────────┬──────────────────┘ + │ + ▼ + ┌────────────────┐ + │ PostgREST API │ ◀── Column Filters add WHERE clauses here + └───────┬────────┘ + │ + ▼ + ┌──────────┐ + │ UI │ + └──────────┘ +``` + +| | Variables | Column Filters | +| -------------------------- | ---------------------------------------------------------- | -------------------------------------------------------- | +| **Defined in** | `spec.templating` | `spec.columns[].filter` | +| **When filtering happens** | At source query time | At display time (PostgreSQL query) | +| **Effect** | Only matching data is fetched and stored in the view table | All data is in PostgreSQL; UI queries with WHERE clauses | +| **Use case** | Scoping large datasets (e.g., select a cluster/namespace) | Narrowing down within already-materialized results | +| **Cache impact** | Each variable combination has its own cache | No cache impact | + +**Example**: If you have 10,000 pods across 5 clusters: + +- **Variable** with `cluster` selection → Only pods from that cluster are fetched from the source and stored (~2,000 rows in PostgreSQL) +- **Column filter** on `cluster` → All 10,000 pods are stored in PostgreSQL; user's filter selection adds a WHERE clause to the query + +Use **variables** when you need to scope down large datasets at the source. Use **column filters** when you want users to explore within already-reasonable result sets. + +## Basic Variable Structure + +```yaml +templating: + # Simple static values variable + - key: environment + label: 'Environment' + values: ['dev', 'staging', 'prod'] + default: 'dev' + + # Dynamic values from config items + - key: cluster + label: 'Cluster' + valueFrom: + config: + types: ['Kubernetes::Cluster'] + default: 'us-east-1' +``` + +## Variable Properties + +### Required Properties + +| Property | Type | Description | +| -------- | ------ | ----------------------------------------------------------------- | +| `key` | string | Unique identifier for the variable (used in template expressions) | +| `label` | string | Display name shown to users | + +### Optional Properties + +| Property | Type | Description | +| ----------- | ------ | -------------------------------------------------------------------- | +| `default` | string | Default value when view loads | +| `values` | array | Static list of options (mutually exclusive with `valueFrom`) | +| `valueFrom` | object | Dynamic options from config items (mutually exclusive with `values`) | +| `dependsOn` | array | List of variable keys this depends on | + +## Variable Types + +### Static Values Variable + +Use predefined options: + +```yaml +- key: loglevel + label: 'Log Level' + values: ['debug', 'info', 'warning', 'error', 'fatal'] + default: 'info' +``` + +**Use cases**: Environments, log levels, predefined status filters, feature flags + +### Dynamic Values Variable + +Load options from configuration items: + +```yaml +- key: cluster + label: 'Kubernetes Cluster' + valueFrom: + config: + types: ['Kubernetes::Cluster'] # Search for Cluster config items + tagSelector: 'environment=prod' # Optional: filter configs + limit: 100 # Optional: limit results +``` + +**Use cases**: Select from actual resources, allow any config type as filter, dynamic lists + +The variable will be populated with config item names as options. Users can select one value. + +### Dependent Variables + +Create variables that depend on other variables: + +```yaml +templating: + # First variable (no dependencies) + - key: cluster + label: 'Cluster' + valueFrom: + config: + types: ['Kubernetes::Cluster'] + + # Dependent variable (filters based on cluster) + - key: namespace + label: 'Namespace' + valueFrom: + config: + types: ['Kubernetes::Namespace'] + tagSelector: 'cluster=$(var.cluster)' # Reference parent variable + dependsOn: ['cluster'] + default: 'default' + + # Another dependent variable + - key: pod + label: 'Pod' + valueFrom: + config: + types: ['Kubernetes::Pod'] + # Can depend on multiple variables + tagSelector: 'cluster=$(var.cluster),namespace=$(var.namespace)' + dependsOn: ['cluster', 'namespace'] +``` + +**How it works**: + +1. Cluster variable loads first (no dependencies) +2. User selects a cluster +3. Namespace variable's options are dynamically filtered by the selected cluster +4. User selects a namespace +5. Pod variable's options are filtered by both cluster AND namespace + +## Using Variables in Queries + +Variables are available in query definitions using the `$(var.)` syntax: + +### In Config Queries + +```yaml +queries: + pods: + configs: + types: ['Kubernetes::Pod'] + tagSelector: 'cluster=$(var.cluster),namespace=$(var.namespace)' + search: '$(var.pod_search)' +``` + +### In Prometheus Queries + +```yaml +queries: + metrics: + prometheus: + query: | + up{cluster="$(var.cluster)",namespace="$(var.namespace)"} +``` + +### In Custom Merge Queries + +```yaml +merge: | + SELECT * FROM configs + WHERE cluster = '$(var.cluster)' + AND namespace = '$(var.namespace)' +``` + +## Using Variables in Mappings + +Variables can also be used in column mapping expressions: + +```yaml +mapping: + cluster_display: "'$(var.cluster)'" + pod_name: 'row.name' +``` + +## Variable Dependency Resolution + +When views have multiple variables, Mission Control resolves them using topological sorting: + +1. **Level 0**: Variables with no dependencies load first +2. **Level 1**: Variables depending on Level 0 variables load next +3. **Level N**: Variables are resolved in dependency order + +**Circular dependency detection**: Mission Control validates that no circular dependencies exist and rejects invalid configurations. + +**Example resolution order**: + +``` +cluster (Level 0 - no deps) + ↓ +namespace (Level 1 - depends on cluster) +pod (Level 1 - depends on cluster) + ↓ +container (Level 2 - depends on pod) +``` + +## Variable Scope and Caching + +Each unique combination of variable values creates a separate cache entry: + +``` +cluster=us-east-1, namespace=default + → separate cache entry +cluster=us-east-1, namespace=kube-system + → different cache entry +cluster=eu-central-1, namespace=default + → another cache entry +``` + +This means: + +- Users switching between variable combinations get independent cached results +- No interference between different filter selections +- Each combination maintains its own [cache control](./cache-control.md) lifecycle + +## Examples + +### Example 1: Simple Static Variables + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: environment-filter +spec: + templating: + - key: env + label: 'Environment' + values: ['development', 'staging', 'production'] + default: 'development' + + - key: sort_by + label: 'Sort By' + values: ['name', 'status', 'age'] + default: 'name' + + queries: + items: + configs: + types: ['Application'] + tagSelector: 'environment=$(var.env)' + + columns: + - name: item_name + type: string + primaryKey: true + + mapping: + item_name: 'row.name' +``` + +### Example 2: Dynamic Cluster and Namespace Selection + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: pod-explorer +spec: + display: + title: 'Pod Explorer' + + templating: + # Level 0: No dependencies + - key: cluster + label: 'Cluster' + valueFrom: + config: + types: ['Kubernetes::Cluster'] + default: 'production' + + # Level 1: Depends on cluster + - key: namespace + label: 'Namespace' + valueFrom: + config: + types: ['Kubernetes::Namespace'] + tagSelector: 'cluster=$(var.cluster)' + dependsOn: ['cluster'] + default: 'default' + + columns: + - name: pod_name + type: string + primaryKey: true + - name: status + type: status + + queries: + pods: + configs: + types: ['Kubernetes::Pod'] + tagSelector: 'cluster=$(var.cluster),namespace=$(var.namespace)' + + mapping: + pod_name: 'row.name' + status: 'row.status' +``` + +### Example 3: Multiple Data Sources with Variables + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: pod-metrics +spec: + templating: + - key: cluster + label: 'Cluster' + values: ['us-east-1', 'us-west-2', 'eu-central-1'] + default: 'us-east-1' + + - key: metric_type + label: 'Metric Type' + values: ['cpu', 'memory', 'network'] + default: 'cpu' + + columns: + - name: pod + type: string + primaryKey: true + - name: value + type: gauge + + queries: + pods: + configs: + types: ['Kubernetes::Pod'] + tagSelector: 'cluster=$(var.cluster)' + + metrics: + prometheus: + query: | + $(var.metric_type)_usage{cluster="$(var.cluster)"} + columns: + pod: string + value: decimal + + merge: | + SELECT p.name as pod, m.value as value + FROM pods p + LEFT JOIN metrics m ON p.name = m.pod + + mapping: + pod: 'row.pod' + value: 'row.value' +``` + +## Best Practices + +1. **Use meaningful keys** - Choose variable keys that describe what they filter + + ```yaml + key: environment # ✓ Clear + key: env_filter # ✓ Also clear + key: x # ✗ Unclear + ``` + +2. **Provide helpful labels** - Give users context about what to select + + ```yaml + label: "Production Environment" # ✓ Descriptive + label: "Prod" # ✗ Too vague + ``` + +3. **Set sensible defaults** - Most users select default, so choose a good one + + ```yaml + default: "production" # ✓ Safe, commonly used + default: "dev" # ? May not be what most users need + ``` + +4. **Order variables logically** - Put base filters first, dependent filters later + + ```yaml + # ✓ Good order + - cluster # User selects cluster first + - namespace # Then narrows to namespace + - pod # Then finally a specific pod + + # ✗ Poor order + - pod # User can't narrow down pods first + - namespace + - cluster + ``` + +5. **Limit dynamic variable options** - Add reasonable limits to prevent huge lists + ```yaml + valueFrom: + config: + types: ['Kubernetes::Pod'] + limit: 100 # Don't load 10,000 pods + ``` + +## Variable Templating Syntax + +Variables use simple `$(var.key)` syntax for substitution: + +```yaml +# In tagSelector +tagSelector: "cluster=$(var.cluster),env=$(var.env)" + +# In search fields +search: "$(var.pod_search)" + +# In PromQL queries +query: 'up{cluster="$(var.cluster)"}' + +# In merge/custom SQL +WHERE cluster = '$(var.cluster)' +``` + +Note: String substitution happens before query execution, so values are injected as-is. For dynamic SQL, consider using parameterized queries if dealing with user input. diff --git a/mission-control/docs/guide/views/index.md b/mission-control/docs/guide/views/index.md index febadf12..be51452a 100644 --- a/mission-control/docs/guide/views/index.md +++ b/mission-control/docs/guide/views/index.md @@ -8,20 +8,18 @@ sidebar_custom_props: import View from "@site/docs/reference/views/\_view.mdx" -Views are a SQL-powered feature that allows you to create custom, dynamic dashboards from your Mission Control data. They collect data from multiple sources into an in-memory SQLite database, enabling you to run any SQL query for filtering, joining, and aggregating your observability data. +Views are dynamic, data-driven dashboards in Mission Control that aggregate and visualize data from multiple sources. +They collect data from multiple sources into an in-memory SQLite database, enabling you to run any SQL query for filtering, joining, and aggregating your observability data. -This view creates a dashboard showing Helm releases with their current status, health, and deployment information. +Views serve as a powerful data aggregation and visualization layer in Mission Control. They: -## Overview - -Views solve the challenge of creating custom dashboards and reports by providing: - -- **Dynamic Data Aggregation**: Combine data from multiple sources using SQL -- **Rich Visualizations**: Display data with gauges, charts, status indicators, and more -- **Structured Schema**: Define column types and constraints for consistent data presentation -- **Cached Results**: Views work like materialized views, caching query results in dedicated database tables for fast retrieval +- **Aggregate data** from multiple sources including configuration items, changes, and Prometheus metrics +- **Display data** as interactive tables and visualization panels (gauges, pie charts, ...) +- **Support templating** with variables that users can adjust to dynamically filter and update the view +- **Cache results** intelligently to balance data freshness with performance +- **Transform data** using expressions to map raw query results to meaningful display columns ## Key Features diff --git a/mission-control/docs/guide/views/queries/changes.md b/mission-control/docs/guide/views/queries/changes.md new file mode 100644 index 00000000..a5e5e1e8 --- /dev/null +++ b/mission-control/docs/guide/views/queries/changes.md @@ -0,0 +1,551 @@ +--- +title: Change Queries +sidebar_custom_props: + icon: diff +--- + +Change queries retrieve the audit trail of modifications to configuration items. They allow you to display what changed, when, how, and which resources were affected. + +## Overview + +Changes represent modifications to configuration items tracked in your catalog. They include version updates, property changes, deletions, and other modifications. Change queries let you build audit dashboards, change timelines, and impact analysis views. + +**Example**: +```yaml +queries: + recent_changes: + changes: + types: ["Kubernetes::Pod", "Kubernetes::Deployment"] + search: "update" + limit: 50 +``` + +## Query Properties + +### Basic Properties + +| Property | Type | Description | +|----------|------|-------------| +| `types` | array | Config item types to get changes for | +| `search` | string | Free text search across change summaries | +| `tagSelector` | string | Filter by tags of the affected config items | +| `status` | string | Filter by change status | +| `severity` | string | Filter by change severity (`info`, `warning`, `critical`) | +| `agent` | string | Filter by specific agent that captured the change | +| `limit` | integer | Maximum number of changes to return | + +## Query Examples + +### Recent Changes for a Resource Type + +```yaml +queries: + pod_changes: + changes: + types: ["Kubernetes::Pod"] + limit: 100 +``` + +Return the 100 most recent changes to pods. + +### Search for Specific Changes + +```yaml +queries: + deployment_updates: + changes: + types: ["Kubernetes::Deployment"] + search: "update" + limit: 50 +``` + +Return changes containing "update" in the summary. + +### Critical Changes Only + +```yaml +queries: + critical_changes: + changes: + types: ["Kubernetes::Pod", "Kubernetes::Node"] + severity: "critical" + limit: 200 +``` + +Return critical changes to pods and nodes. + +### Changes to Production Resources + +```yaml +queries: + prod_changes: + changes: + types: ["Kubernetes::Pod"] + tagSelector: "environment=production" + limit: 100 +``` + +Return changes to production resources only. + +### Combine Multiple Filters + +```yaml +queries: + analysis: + changes: + types: + - "Kubernetes::Deployment" + - "Kubernetes::StatefulSet" + - "Kubernetes::DaemonSet" + tagSelector: "environment=production,team=platform" + severity: "warning" + search: "config" + agent: "cluster-1" + limit: 100 +``` + +Return warning-level configuration changes to production deployments managed by platform team. + +## Auto-Mapped Columns + +Change queries automatically provide these columns: + +### Core Change Information +- `id` - Unique change identifier +- `config_id` - ID of the changed configuration item +- `config_name` - Name of the changed resource +- `config_type` - Type of the changed resource +- `change_type` - Type of change (e.g., `Created`, `Updated`, `Deleted`) +- `severity` - Change severity (`info`, `warning`, `critical`) +- `summary` - Human-readable summary of the change +- `description` - Detailed change description + +### Before/After Content +- `old_config` - Configuration before the change +- `new_config` - Configuration after the change +- `diff` - Computed diff showing what changed +- `patch` - Patch format showing the differences + +### Timestamps +- `created_at` - When the change was detected +- `first_seen_at` - First time this change was observed +- `last_seen_at` - Last time this change was observed + +### Related Information +- `tags` - Tags of the affected resource +- `labels` - Labels of the affected resource + +## Using Variables in Change Queries + +Make change queries dynamic with templating variables: + +```yaml +templating: + - key: resource_type + label: "Resource Type" + values: ["Kubernetes::Pod", "Kubernetes::Deployment"] + default: "Kubernetes::Pod" + + - key: severity_level + label: "Min Severity" + values: ["info", "warning", "critical"] + +queries: + changes: + changes: + types: ["$(var.resource_type)"] + severity: "$(var.severity_level)" +``` + +## Column Mapping Examples + +### Simple Change Timeline + +```yaml +columns: + - name: resource + type: string + primaryKey: true + - name: change_type + type: string + - name: severity + type: status + - name: changed_at + type: datetime + +queries: + changes: + changes: + types: ["Kubernetes::Pod", "Kubernetes::Deployment"] + limit: 100 + +mapping: + resource: "row.config_name" + change_type: "row.change_type" + severity: "row.severity" + changed_at: "row.created_at" +``` + +### Detailed Change View with Summary + +```yaml +columns: + - name: id + type: string + primaryKey: true + hidden: true + - name: resource + type: string + - name: type + type: string + - name: summary + type: text + - name: severity + type: health + - name: timestamp + type: datetime + +queries: + changes: + changes: + types: ["Kubernetes::*"] + limit: 200 + +mapping: + id: "row.id" + resource: "row.config_name" + type: "row.change_type" + summary: "row.summary" + severity: "row.severity == 'critical' ? 'critical' : row.severity == 'warning' ? 'warning' : 'healthy'" + timestamp: "row.created_at" +``` + +### Change Impact Analysis + +```yaml +columns: + - name: resource_id + type: string + primaryKey: true + hidden: true + - name: resource_name + type: string + - name: resource_type + type: string + - name: changes_count + type: number + - name: latest_change + type: datetime + +queries: + changes: + changes: + types: ["Kubernetes::Pod"] + limit: 1000 + +merge: | + SELECT + config_id as resource_id, + config_name as resource_name, + config_type as resource_type, + COUNT(*) as changes_count, + MAX(created_at) as latest_change + FROM changes + GROUP BY config_id, config_name, config_type + +mapping: + resource_id: "row.resource_id" + resource_name: "row.resource_name" + resource_type: "row.resource_type" + changes_count: "row.changes_count" + latest_change: "row.latest_change" +``` + +## Real-World Examples + +### Deployment Change Timeline + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: deployment-changes +spec: + display: + title: "Deployment Changes" + sidebar: true + + templating: + - key: environment + label: "Environment" + values: ["dev", "staging", "prod"] + default: "prod" + + columns: + - name: deployment + type: string + primaryKey: true + - name: change_type + type: string + - name: summary + type: text + - name: severity + type: health + - name: timestamp + type: datetime + + queries: + changes: + changes: + types: ["Kubernetes::Deployment"] + tagSelector: "environment=$(var.environment)" + limit: 100 + + mapping: + deployment: "row.config_name" + change_type: "row.change_type" + summary: "row.summary" + severity: "row.severity == 'critical' ? 'critical' : row.severity == 'warning' ? 'warning' : 'healthy'" + timestamp: "row.created_at" +``` + +### Production Incident Investigation + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: incident-changes +spec: + display: + title: "Incident Investigation Timeline" + + columns: + - name: timestamp + type: datetime + primaryKey: true + - name: resource + type: string + - name: resource_type + type: string + - name: change + type: text + - name: severity + type: health + + queries: + changes: + changes: + types: + - "Kubernetes::Pod" + - "Kubernetes::Node" + - "Kubernetes::Deployment" + tagSelector: "environment=production" + severity: "critical" + limit: 500 + + mapping: + timestamp: "row.created_at" + resource: "row.config_name" + resource_type: "row.config_type" + change: "row.summary" + severity: "row.severity == 'critical' ? 'critical' : 'warning'" +``` + +### Change Summary Dashboard with Panels + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: change-summary +spec: + display: + title: "Change Summary" + card: + columns: 2 + + columns: + - name: change_id + type: string + primaryKey: true + hidden: true + + queries: + changes: + changes: + types: ["Kubernetes::Pod", "Kubernetes::Deployment"] + limit: 1000 + + panels: + - name: "Total Changes (24h)" + type: number + query: | + SELECT COUNT(*) as value FROM changes + WHERE created_at > datetime('now', '-1 day') + + - name: "Changes by Severity" + type: piechart + query: | + SELECT severity, COUNT(*) as value FROM changes + WHERE created_at > datetime('now', '-1 day') + GROUP BY severity + + - name: "Critical Changes by Type" + type: bargauge + query: | + SELECT config_type, COUNT(*) as value FROM changes + WHERE severity = 'critical' + AND created_at > datetime('now', '-7 days') + GROUP BY config_type + + - name: "Most Changed Resources" + type: table + query: | + SELECT + config_name as resource, + COUNT(*) as change_count + FROM changes + WHERE created_at > datetime('now', '-7 days') + GROUP BY config_name + ORDER BY change_count DESC + LIMIT 10 +``` + +### Change Frequency Analysis + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: change-frequency +spec: + display: + title: "Change Frequency by Resource" + + templating: + - key: days_back + label: "Time Period" + values: ["1", "7", "30"] + default: "7" + + columns: + - name: resource_name + type: string + primaryKey: true + - name: resource_type + type: string + - name: total_changes + type: number + - name: last_changed + type: datetime + + queries: + changes: + changes: + types: ["Kubernetes::Pod", "Kubernetes::Deployment", "Kubernetes::StatefulSet"] + limit: 1000 + + merge: | + SELECT + config_name as resource_name, + config_type as resource_type, + COUNT(*) as total_changes, + MAX(created_at) as last_changed + FROM changes + WHERE created_at > datetime('now', '-$(var.days_back) days') + GROUP BY config_id, config_name, config_type + ORDER BY total_changes DESC + + mapping: + resource_name: "row.resource_name" + resource_type: "row.resource_type" + total_changes: "row.total_changes" + last_changed: "row.last_changed" +``` + +## Diff and Patch Analysis + +When mapping change configurations, you can access the diff and patch: + +```yaml +mapping: + # Show human-readable diff + changes_made: "row.diff" + + # Show patch format + patch_content: "row.patch" + + # Access old/new configs + old_value: "row.old_config" + new_value: "row.new_config" +``` + +## Performance Considerations + +### Use Limits +Always limit the number of changes to avoid loading entire history: + +```yaml +queries: + changes: + changes: + types: ["Kubernetes::Pod"] + limit: 100 # Don't load all changes +``` + +### Filter by Severity +When possible, filter to relevant changes: + +```yaml +# ✓ Specific - gets fewer results +changes: + types: ["Kubernetes::Pod"] + severity: "critical" + +# ✗ Broad - gets all changes +changes: + types: ["Kubernetes::Pod"] +``` + +### Use Time Windows in Merge +When aggregating changes, limit the time window: + +```yaml +merge: | + SELECT config_name, COUNT(*) as change_count + FROM changes + WHERE created_at > datetime('now', '-7 days') # Last 7 days only + GROUP BY config_name +``` + +## Common Use Cases + +### Audit Trail +Track all changes to critical resources for compliance: +```yaml +types: ["Kubernetes::Pod", "Kubernetes::Deployment"] +tagSelector: "environment=production" +``` + +### Incident Timeline +Find what changed around an incident time: +```yaml +types: ["Kubernetes::*"] +severity: "critical" +``` + +### Change Approval Workflows +Monitor changes that need approval: +```yaml +search: "requires-approval" +severity: "warning" +``` + +### SLA Tracking +Monitor change frequency against SLAs: +```yaml +# Count changes per resource +# Group by resource +# Compare against SLA targets +``` diff --git a/mission-control/docs/guide/views/queries/configs.md b/mission-control/docs/guide/views/queries/configs.md new file mode 100644 index 00000000..88d5f413 --- /dev/null +++ b/mission-control/docs/guide/views/queries/configs.md @@ -0,0 +1,498 @@ +--- +title: Config Queries +sidebar_custom_props: + icon: config +--- + +Config queries fetch configuration items (resources) from the Flanksource catalog. They allow you to display and analyze any type of infrastructure or application resource tracked in your catalog. + +## Overview + +Config queries retrieve resources from your catalog based on filters. The query results include all standard config item properties plus custom properties and tags you've defined. + +**Example**: +```yaml +queries: + myquery: + configs: + types: ["Kubernetes::Pod", "Kubernetes::Node"] + tagSelector: "environment=production" +``` + +## Query Properties + +### Basic Properties + +| Property | Type | Description | +|----------|------|-------------| +| `types` | array | Config types to query (e.g., `["Kubernetes::Pod"]`) | +| `search` | string | Free text search across config name and properties | +| `status` | string | Filter by status (`healthy`, `warning`, `critical`, `unhealthy`) | +| `health` | string | Filter by health status | +| `tagSelector` | string | Filter by tags using selector syntax | +| `labelSelector` | string | Filter by Kubernetes-style labels | +| `agent` | string | Filter by specific agent ID | +| `scope` | string | Filter by scraper/scope ID | +| `fieldSelector` | string | Advanced field-based filtering | +| `limit` | integer | Maximum number of results to return | + +## Query Examples + +### Query by Type + +```yaml +queries: + pods: + configs: + types: ["Kubernetes::Pod"] +``` + +Return all Kubernetes pods from the catalog. + +### Query Multiple Types + +```yaml +queries: + resources: + configs: + types: + - "Kubernetes::Pod" + - "Kubernetes::Deployment" + - "Kubernetes::StatefulSet" +``` + +Return pods, deployments, and stateful sets. + +### Filter by Tags + +```yaml +queries: + prod_pods: + configs: + types: ["Kubernetes::Pod"] + tagSelector: "environment=prod,team=platform" +``` + +Return production pods owned by the platform team. Multiple tags use AND logic. + +### Filter by Status + +```yaml +queries: + unhealthy: + configs: + types: ["Kubernetes::Pod"] + status: "critical" + limit: 100 +``` + +Return up to 100 pods with critical status. + +### Free Text Search + +```yaml +queries: + search_results: + configs: + types: ["Kubernetes::Pod"] + search: "postgres" +``` + +Return all pods with "postgres" in name or properties. + +### Combine Multiple Filters + +```yaml +queries: + complex_query: + configs: + types: ["Kubernetes::Deployment"] + tagSelector: "environment=production,region=us-east-1" + status: "warning" + search: "database" + agent: "cluster-1" + limit: 50 +``` + +Return the first 50 production deployments in us-east-1 with "database" in name and warning status. + +## Auto-Mapped Columns + +Config queries automatically provide these columns for use in table views: + +### Core Properties +- `id` - Unique config identifier +- `name` - Resource name +- `type` - Config type (e.g., `Kubernetes::Pod`) +- `namespace` - Kubernetes namespace (if applicable) +- `agent` - Agent that scraped the config +- `source` - Configuration source + +### Status & Health +- `status` - Current status (healthy/warning/critical/unhealthy) +- `health` - Health status +- `health_color` - Color code for health status + +### Timestamps +- `created_at` - When config was first discovered +- `updated_at` - Last time config was updated +- `deleted_at` - When config was deleted (if deleted) + +### Properties & Content +- `config` - Raw configuration content (often JSON/YAML) +- `properties` - Custom properties as JSON +- `tags` - Applied tags as JSON +- `labels` - Kubernetes-style labels as JSON + +### Cost Data +- `cost` - Current cost +- `cost_total_1d` - Cost over last day +- `cost_total_7d` - Cost over last 7 days +- `cost_total_30d` - Cost over last 30 days + +### Relationships +- `parent_id` - ID of parent config item +- `parent_name` - Name of parent config item +- `parent_type` - Type of parent config item + +### Computed Fields +- `summary` - Auto-generated summary of the config + +## Using Variables in Config Queries + +You can use templating variables to make queries dynamic: + +```yaml +templating: + - key: environment + label: "Environment" + values: ["dev", "staging", "prod"] + + - key: search_term + label: "Search" + values: ["", "database", "cache", "web"] + +queries: + resources: + configs: + types: ["Kubernetes::Pod"] + tagSelector: "environment=$(var.environment)" + search: "$(var.search_term)" +``` + +See [Templating & Variables](../concepts/templating.md) for more details. + +## Column Mapping Examples + +### Simple Table with Basic Columns + +```yaml +columns: + - name: name + type: string + primaryKey: true + - name: status + type: status + - name: health + type: health + +queries: + resources: + configs: + types: ["Kubernetes::Pod"] + +mapping: + name: "row.name" + status: "row.status" + health: "row.health" +``` + +### Display Cost Information + +```yaml +columns: + - name: name + type: string + primaryKey: true + - name: cost_30d + type: decimal + - name: health + type: health + +queries: + resources: + configs: + types: ["AWS::EC2Instance"] + +mapping: + name: "row.name" + cost_30d: "row.cost_total_30d" + health: "row.health" +``` + +### Show Custom Properties + +```yaml +columns: + - name: name + type: string + primaryKey: true + - name: version + type: string + - name: replicas + type: number + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + name: "row.name" + version: "row.properties.version" + replicas: "row.properties.replicas" +``` + +### Create Links to Related Resources + +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + - name: node_name + type: url + url: + config: "row.parent_id" + - name: health + type: health + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + node_name: "row.parent_name" + health: "row.health" +``` + +## Real-World Examples + +### Production Pod Dashboard + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: prod-pods +spec: + display: + title: "Production Pods" + sidebar: true + + templating: + - key: namespace + label: "Namespace" + valueFrom: + config: + types: ["Kubernetes::Namespace"] + tagSelector: "environment=production" + default: "default" + + columns: + - name: pod_name + type: string + primaryKey: true + - name: status + type: status + - name: health + type: health + - name: age + type: duration + + queries: + pods: + configs: + types: ["Kubernetes::Pod"] + tagSelector: "environment=production,namespace=$(var.namespace)" + + mapping: + pod_name: "row.name" + status: "row.status" + health: "row.health" + age: "now - row.created_at" +``` + +### AWS EC2 Inventory with Cost Tracking + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: aws-inventory +spec: + display: + title: "AWS EC2 Instances" + + templating: + - key: region + label: "Region" + values: ["us-east-1", "us-west-2", "eu-central-1"] + default: "us-east-1" + + columns: + - name: instance_id + type: string + primaryKey: true + - name: instance_type + type: string + - name: status + type: status + - name: monthly_cost + type: decimal + unit: "$" + + queries: + instances: + configs: + types: ["AWS::EC2Instance"] + tagSelector: "region=$(var.region)" + + mapping: + instance_id: "row.name" + instance_type: "row.properties.instance_type" + status: "row.status" + monthly_cost: "row.cost_total_30d" +``` + +### Multi-Cluster Resource View + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: multi-cluster-resources +spec: + display: + title: "Resources Across Clusters" + + templating: + - key: cluster + label: "Cluster" + valueFrom: + config: + types: ["Kubernetes::Cluster"] + default: "production" + + - key: resource_type + label: "Resource Type" + values: ["Pod", "Deployment", "StatefulSet", "DaemonSet"] + default: "Pod" + + columns: + - name: resource_name + type: string + primaryKey: true + - name: resource_type + type: string + - name: namespace + type: string + - name: status + type: status + - name: health + type: health + + queries: + resources: + configs: + types: + - "Kubernetes::Pod" + - "Kubernetes::Deployment" + - "Kubernetes::StatefulSet" + - "Kubernetes::DaemonSet" + tagSelector: "cluster=$(var.cluster)" + + mapping: + resource_name: "row.name" + resource_type: "row.type" + namespace: "row.namespace" + status: "row.status" + health: "row.health" +``` + +## Performance Considerations + +### Limit Results +Always use `limit` to avoid fetching huge result sets: + +```yaml +queries: + resources: + configs: + types: ["Kubernetes::Pod"] + limit: 100 # Don't fetch all pods +``` + +### Use Specific Types +Query specific resource types rather than all types: + +```yaml +# ✓ Specific - only gets pods +configs: + types: ["Kubernetes::Pod"] + +# ✗ Broad - might get everything +configs: + types: ["Kubernetes::*"] +``` + +### Filter Early +Apply restrictive filters to reduce data: + +```yaml +# ✓ Filters reduce results +configs: + types: ["Kubernetes::Pod"] + tagSelector: "environment=prod,team=platform" + status: "critical" + +# ✗ Broad - gets everything +configs: + types: ["Kubernetes::Pod"] +``` + +### Combine with Cache Control +Use [cache control](../concepts/cache-control.md) to avoid repeated expensive queries: + +```yaml +cache: + maxAge: 30m # Don't refresh too frequently +``` + +## Troubleshooting + +### No Results Returned + +Check: +1. Is the config type correct? (`Kubernetes::Pod` not `Pod`) +2. Are your filters too restrictive? Try removing tagSelector +3. Does your agent/scope exist and have permissions? +4. Are there any configs of this type in your catalog? + +### Unexpected Results + +Check: +1. Does tagSelector have correct key=value format? +2. Are multiple tags properly comma-separated? +3. Are variable substitutions working? (Try hardcoding a value) +4. Check the health/status filters aren't too restrictive + +### Performance Issues + +Check: +1. Is `limit` set? (Defaults to returning all matches) +2. Are you querying multiple expensive types? +3. Try adding more restrictive filters +4. Consider increasing `maxAge` in cache control diff --git a/mission-control/docs/guide/views/queries/index.mdx b/mission-control/docs/guide/views/queries/index.mdx new file mode 100644 index 00000000..554fff6e --- /dev/null +++ b/mission-control/docs/guide/views/queries/index.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 2 +title: Queries +sidebar_custom_props: + icon: sql +--- + + +import DocCardList from '@theme/DocCardList'; + + diff --git a/mission-control/docs/guide/views/queries/prometheus.md b/mission-control/docs/guide/views/queries/prometheus.md new file mode 100644 index 00000000..47789524 --- /dev/null +++ b/mission-control/docs/guide/views/queries/prometheus.md @@ -0,0 +1,650 @@ +--- +title: Prometheus Queries +sidebar_custom_props: + icon: prometheus +--- + +Prometheus queries fetch metrics directly from Prometheus using PromQL. They allow you to display real-time and historical metrics in your views. + +## Overview + +Prometheus queries execute PromQL expressions against your Prometheus instance and return time series data. Results can be visualized as tables, gauges, charts, and other panel types. + +**Example**: +```yaml +queries: + metrics: + prometheus: + connection: prometheus-prod + query: 'up{job="kubernetes-nodes"}' +``` + +## Query Properties + +| Property | Type | Description | +|----------|------|-------------| +| `connection` | string | Name of the Prometheus connection to use | +| `query` | string | PromQL query expression | +| `columns` | object | Optional: define column types for the results | + +## Connection Configuration + +Before using Prometheus queries, ensure you have a Prometheus connection configured in your Mission Control instance. Connections are typically defined at the system level. + +Reference a connection by its name: + +```yaml +prometheus: + connection: prometheus-prod + query: 'up{job="kubernetes"}' +``` + +## PromQL Queries + +Prometheus queries use standard PromQL syntax. The query results return: +- **Labels** from the metric as columns +- **Value** as a numeric column + +### Instant Queries + +Return the current value of metrics: + +```yaml +queries: + node_up: + prometheus: + connection: prod + query: 'up{job="kubernetes-nodes"}' +``` + +Returns: One row per node with `up` value and labels like `node`, `job`, `instance`. + +### Range Queries + +Return values over a time range (in panels/merge): + +```yaml +queries: + cpu_usage: + prometheus: + connection: prod + query: 'rate(node_cpu_seconds_total[5m])' +``` + +### Aggregation Queries + +Aggregate metrics across dimensions: + +```yaml +queries: + namespace_memory: + prometheus: + connection: prod + query: | + sum(container_memory_usage_bytes) by (namespace) +``` + +## Column Type Definitions + +For Prometheus queries, you can optionally define column types. This is useful when: +- You want to control how metrics are displayed +- The metric has no results yet (type inference would fail) +- You want to ensure specific formatting + +```yaml +queries: + metrics: + prometheus: + connection: prod + query: 'container_memory_usage_bytes{namespace="default"}' + columns: + pod: string + container: string + value: bytes +``` + +If you don't specify columns, types are inferred from the query results. + +## Query Examples + +### CPU Usage by Node + +```yaml +queries: + cpu_usage: + prometheus: + connection: prod + query: | + rate(node_cpu_seconds_total{mode="system"}[5m]) * 100 + columns: + node: string + value: decimal +``` + +### Memory Availability + +```yaml +queries: + memory_available: + prometheus: + connection: prod + query: | + node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 + columns: + instance: string + value: gauge +``` + +### Pod Count by Namespace + +```yaml +queries: + pods_per_ns: + prometheus: + connection: prod + query: | + count(kube_pod_info) by (namespace) + columns: + namespace: string + value: number +``` + +### Disk Usage Percentage + +```yaml +queries: + disk_usage: + prometheus: + connection: prod + query: | + (node_filesystem_size_bytes - node_filesystem_avail_bytes) + / node_filesystem_size_bytes * 100 + columns: + device: string + mountpoint: string + value: gauge +``` + +### Network Traffic + +```yaml +queries: + network_io: + prometheus: + connection: prod + query: | + rate(node_network_receive_bytes_total[5m]) + columns: + device: string + instance: string + value: bytes +``` + +## Using Variables in Prometheus Queries + +Make Prometheus queries dynamic with templating variables: + +```yaml +templating: + - key: job + label: "Job" + values: ["kubernetes-nodes", "kubernetes-pods", "prometheus"] + default: "kubernetes-nodes" + + - key: namespace + label: "Namespace" + values: ["default", "kube-system", "monitoring"] + default: "default" + +queries: + metrics: + prometheus: + connection: prod + query: | + up{job="$(var.job)",namespace="$(var.namespace)"} +``` + +## Column Mapping Examples + +### Simple Metric Display + +```yaml +columns: + - name: instance + type: string + primaryKey: true + - name: cpu_percent + type: gauge + gauge: + max: "100" + +queries: + cpu: + prometheus: + connection: prod + query: 'rate(node_cpu_seconds_total[5m]) * 100' + +mapping: + instance: "row.instance" + cpu_percent: "row.value" +``` + +### Metric with Multiple Labels + +```yaml +columns: + - name: pod + type: string + primaryKey: true + - name: namespace + type: string + - name: memory_mb + type: gauge + +queries: + memory: + prometheus: + connection: prod + query: | + container_memory_usage_bytes{pod!=""} / 1024 / 1024 + +mapping: + pod: "row.pod" + namespace: "row.namespace" + memory_mb: "row.value" +``` + +### Multiple Metrics Combined + +When combining multiple Prometheus queries: + +```yaml +columns: + - name: instance + type: string + primaryKey: true + - name: cpu_percent + type: gauge + - name: memory_percent + type: gauge + +queries: + cpu_usage: + prometheus: + connection: prod + query: 'rate(node_cpu_seconds_total[5m]) * 100' + columns: + instance: string + value: decimal + + memory_usage: + prometheus: + connection: prod + query: | + (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) + / node_memory_MemTotal_bytes * 100 + columns: + instance: string + value: decimal + +merge: | + SELECT + c.instance, + c.value as cpu_percent, + m.value as memory_percent + FROM cpu_usage c + LEFT JOIN memory_usage m ON c.instance = m.instance + +mapping: + instance: "row.instance" + cpu_percent: "row.cpu_percent" + memory_percent: "row.memory_percent" +``` + +## Real-World Examples + +### Node Resource Dashboard + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: node-metrics +spec: + display: + title: "Node Resources" + sidebar: true + + columns: + - name: node + type: string + primaryKey: true + - name: cpu_percent + type: gauge + gauge: + max: "100" + - name: memory_percent + type: gauge + gauge: + max: "100" + - name: disk_percent + type: gauge + gauge: + max: "100" + + queries: + cpu: + prometheus: + connection: prod + query: | + rate(node_cpu_seconds_total{mode="system"}[5m]) * 100 + columns: + node: string + value: decimal + + memory: + prometheus: + connection: prod + query: | + (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) + / node_memory_MemTotal_bytes * 100 + columns: + node: string + value: decimal + + disk: + prometheus: + connection: prod + query: | + (node_filesystem_size_bytes - node_filesystem_avail_bytes) + / node_filesystem_size_bytes * 100 + columns: + node: string + value: decimal + + merge: | + SELECT + c.node, + c.value as cpu_percent, + m.value as memory_percent, + d.value as disk_percent + FROM cpu c + LEFT JOIN memory m ON c.node = m.node + LEFT JOIN disk d ON c.node = d.node + + mapping: + node: "row.node" + cpu_percent: "row.cpu_percent" + memory_percent: "row.memory_percent" + disk_percent: "row.disk_percent" +``` + +### Pod Metrics by Namespace + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: pod-metrics +spec: + display: + title: "Pod Resource Usage" + + templating: + - key: namespace + label: "Namespace" + values: ["default", "kube-system", "monitoring"] + default: "default" + + columns: + - name: pod + type: string + primaryKey: true + - name: container + type: string + - name: cpu_cores + type: decimal + - name: memory_mb + type: decimal + + queries: + pod_metrics: + prometheus: + connection: prod + query: | + { + cpu: rate(container_cpu_usage_seconds_total{namespace="$(var.namespace)",pod!=""}[5m]), + memory: container_memory_usage_bytes{namespace="$(var.namespace)",pod!=""} / 1024 / 1024 + } + columns: + pod: string + container: string + cpu: decimal + memory: decimal + + mapping: + pod: "row.pod" + container: "row.container" + cpu_cores: "row.cpu" + memory_mb: "row.memory" +``` + +### Alert Metrics Dashboard + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: alert-metrics +spec: + display: + title: "Alert Status" + card: + columns: 3 + + columns: + - name: alert_id + type: string + primaryKey: true + hidden: true + + queries: + alerts: + prometheus: + connection: prod + query: | + ALERTS{severity=~"critical|warning"} + columns: + alertname: string + severity: string + instance: string + value: number + + panels: + - name: "Critical Alerts" + type: number + query: | + SELECT COUNT(*) as value FROM alerts + WHERE severity = 'critical' + + - name: "Warning Alerts" + type: number + query: | + SELECT COUNT(*) as value FROM alerts + WHERE severity = 'warning' + + - name: "Alerts by Severity" + type: piechart + query: | + SELECT severity, COUNT(*) as value FROM alerts + GROUP BY severity + + - name: "Most Common Alerts" + type: table + query: | + SELECT alertname, COUNT(*) as count + FROM alerts + GROUP BY alertname + ORDER BY count DESC + LIMIT 10 +``` + +### Service Health Monitoring + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: service-health +spec: + display: + title: "Service Health Status" + + templating: + - key: job + label: "Service" + values: ["api-server", "database", "cache", "queue"] + default: "api-server" + + columns: + - name: instance + type: string + primaryKey: true + - name: up + type: health + - name: last_scrape + type: datetime + - name: scrape_duration_ms + type: number + + queries: + service_health: + prometheus: + connection: prod + query: | + up{job="$(var.job)"} + columns: + instance: string + value: number + + scrape_info: + prometheus: + connection: prod + query: | + { + duration: scrape_duration_seconds{job="$(var.job)"} * 1000, + timestamp: scrape_timestamp{job="$(var.job)"} + } + columns: + instance: string + duration: decimal + timestamp: datetime + + merge: | + SELECT + s.instance, + s.value as up, + sc.timestamp as last_scrape, + sc.duration as scrape_duration_ms + FROM service_health s + LEFT JOIN scrape_info sc ON s.instance = sc.instance + + mapping: + instance: "row.instance" + up: "row.up == 1 ? 'healthy' : 'critical'" + last_scrape: "row.last_scrape" + scrape_duration_ms: "row.scrape_duration_ms" +``` + +## Performance Considerations + +### Limit Query Scope +Use specific label matchers to reduce data: + +```yaml +# ✓ Specific - only relevant metrics +query: 'up{job="kubernetes-nodes",region="us-east-1"}' + +# ✗ Broad - gets all data +query: 'up' +``` + +### Use Appropriate Time Windows +For rate() and other range functions: + +```yaml +# ✓ Reasonable 5-minute window +query: 'rate(requests_total[5m])' + +# ✗ Too long window +query: 'rate(requests_total[24h])' +``` + +### Cache Long-Running Queries +Use [cache control](../concepts/cache-control.md) appropriately: + +```yaml +cache: + maxAge: 5m # Refresh less frequently for expensive queries + refreshTimeout: 10s +``` + +### Aggregation Before Query +Aggregate in PromQL rather than after fetching: + +```yaml +# ✓ Aggregate in query +query: 'sum(rate(requests_total[5m])) by (job)' + +# ✗ Fetch all, aggregate later +query: 'rate(requests_total[5m])' +# then merge to aggregate +``` + +## Common PromQL Patterns + +### Rate of Change (Per Second) +```promql +rate(metric_total[5m]) +``` + +### Percentage +```promql +(used / total) * 100 +``` + +### Convert Units +```promql +bytes_value / 1024 / 1024 # Bytes to MB +milliseconds_value / 1000 # Milliseconds to seconds +``` + +### Conditional Values +```promql +metric_value > 0.8 or on() vector(1) # Returns 1 if metric > 0.8 +``` + +### Top N Results +Use `topk()` in PromQL or `LIMIT` in merge query. + +## Troubleshooting + +### Empty Results +Check: +1. Is the connection name correct? +2. Does the Prometheus instance have the metrics? +3. Try the query directly in Prometheus UI +4. Check label names and values (case-sensitive) + +### Wrong Column Types +Ensure column definitions match your PromQL output: +```yaml +columns: + instance: string # Label names are strings + value: decimal # Metric values are typically decimal +``` + +### Performance Issues +- Check Prometheus query performance directly +- Reduce time window or add more specific labels +- Consider using [view table selector](./view-table-selector.md) for cached data instead diff --git a/mission-control/docs/guide/views/queries/view-table-selector.md b/mission-control/docs/guide/views/queries/view-table-selector.md new file mode 100644 index 00000000..4ee21eac --- /dev/null +++ b/mission-control/docs/guide/views/queries/view-table-selector.md @@ -0,0 +1,591 @@ +--- +title: View Table Selector Queries +sidebar_custom_props: + icon: view-details +--- + +View table selector queries fetch data from other views that have already been cached. This allows you to reuse view data and build composite views without re-querying underlying data sources. + +## Overview + +Instead of fetching data directly from configs, metrics, or changes, view table selectors query previously cached view results. This is useful for: + +- Building views on top of other views (composition) +- Reusing expensive query results +- Creating drill-down dashboards +- Reducing database load + +**Example**: + +```yaml +queries: + pod_data: + viewTableSelector: + name: pod-inventory + namespace: default +``` + +## Query Properties + +| Property | Type | Description | +| ----------- | ------- | ------------------------------------------ | +| `name` | string | Name of the view to query | +| `namespace` | string | Namespace of the view (default: `default`) | +| `filter` | object | Optional: filter rows by column values | +| `limit` | integer | Maximum rows to return | + +## Query Examples + +### Query Another View + +```yaml +queries: + pods: + viewTableSelector: + name: pod-inventory + namespace: default +``` + +Returns all rows from the cached `pod-inventory` view. + +### Filter Results + +```yaml +queries: + prod_pods: + viewTableSelector: + name: pod-inventory + namespace: default + filter: + environment: 'production' + health: 'critical' +``` + +Return rows where environment=production AND health=critical. + +### Limit Results + +```yaml +queries: + top_pods: + viewTableSelector: + name: pod-inventory + namespace: default + limit: 50 +``` + +Return the first 50 rows from the view. + +### Combine Filters and Limits + +```yaml +queries: + recent_changes: + viewTableSelector: + name: change-summary + namespace: monitoring + filter: + severity: 'warning' + resource_type: 'Kubernetes::Deployment' + limit: 100 +``` + +## Using Variables with View Table Selectors + +Make view queries dynamic with templating variables: + +```yaml +templating: + - key: environment + label: 'Environment' + values: ['dev', 'staging', 'prod'] + default: 'prod' + +queries: + data: + viewTableSelector: + name: resource-inventory + filter: + environment: '$(var.environment)' +``` + +## Performance Benefits + +View table selectors are more efficient than re-querying sources: + +| Operation | Time | Data Transfer | +| ----------------------- | ----------- | ------------------ | +| Config query (uncached) | 1-5 seconds | Large | +| Config query (cached) | "< 100ms" | Large | +| View table selector | "< 100ms" | Only filtered rows | + +## Use Cases + +### Drill-Down Dashboards + +Create a hierarchy of views where higher-level views query lower-level views: + +```yaml +# Level 1: Simple pod inventory (queries configs) +kind: View +metadata: + name: pod-inventory +# queries configs directly + +--- +# Level 2: Pod metrics (queries pod-inventory + prometheus) +kind: View +metadata: + name: pod-metrics +queries: + pods: + viewTableSelector: + name: pod-inventory # Query cached pods + + metrics: + prometheus: + query: 'container_memory_usage_bytes' + +--- +# Level 3: Pod troubleshooting (queries pod-metrics) +kind: View +metadata: + name: pod-troubleshoot +queries: + data: + viewTableSelector: + name: pod-metrics # Query cached metrics +``` + +### Filter by Context Variables + +```yaml +# Resource inventory view with namespace filter +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: namespace-resources +spec: + templating: + - key: namespace + label: 'Namespace' + values: ['default', 'kube-system'] + + queries: + data: + viewTableSelector: + name: all-resources + filter: + namespace: '$(var.namespace)' +``` + +### Combine Multiple Views + +When building a view that needs data from multiple other views, use both viewTableSelector queries and merge: + +```yaml +queries: + configs: + viewTableSelector: + name: config-summary + filter: + status: 'critical' + + changes: + viewTableSelector: + name: recent-changes + filter: + severity: 'warning' + +merge: | + SELECT + c.id, + c.name, + c.status, + COUNT(ch.id) as change_count + FROM configs c + LEFT JOIN changes ch ON c.id = ch.config_id + GROUP BY c.id, c.name, c.status +``` + +## Column Mapping + +Columns from view table selectors work like any other query: + +```yaml +columns: + - name: name + type: string + primaryKey: true + - name: status + type: status + +queries: + data: + viewTableSelector: + name: resource-inventory + +mapping: + name: 'row.name' + status: 'row.status' +``` + +## Real-World Examples + +### High-Level Resource Status Dashboard + +First, create the base view that queries configs: + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: resource-inventory +spec: + columns: + - name: id + type: string + primaryKey: true + hidden: true + - name: name + type: string + - name: type + type: string + - name: status + type: status + - name: health + type: health + + queries: + resources: + configs: + types: ['Kubernetes::Pod', 'Kubernetes::Node'] + + mapping: + id: 'row.id' + name: 'row.name' + type: 'row.type' + status: 'row.status' + health: 'row.health' +``` + +Then create a summary view using viewTableSelector: + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: resource-summary +spec: + display: + title: 'Resource Summary' + card: + columns: 2 + + columns: + - name: type + type: string + primaryKey: true + - name: total_count + type: number + - name: healthy_count + type: number + - name: critical_count + type: number + + queries: + resources: + viewTableSelector: + name: resource-inventory + + merge: | + SELECT + type, + COUNT(*) as total_count, + SUM(CASE WHEN health = 'healthy' THEN 1 ELSE 0 END) as healthy_count, + SUM(CASE WHEN health = 'critical' THEN 1 ELSE 0 END) as critical_count + FROM resources + GROUP BY type + + mapping: + type: 'row.type' + total_count: 'row.total_count' + healthy_count: 'row.healthy_count' + critical_count: 'row.critical_count' +``` + +### Production Resource Drill-Down + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: prod-resources +spec: + display: + title: 'Production Resources' + sidebar: true + + templating: + - key: resource_type + label: 'Resource Type' + values: ['Pod', 'Deployment', 'Node'] + default: 'Pod' + + columns: + - name: resource_id + type: string + primaryKey: true + hidden: true + - name: name + type: string + - name: status + type: status + - name: health + type: health + - name: details_link + type: url + url: + view: + namespace: default + name: resource-details + filter: + resource_id: 'row.resource_id' + + queries: + data: + viewTableSelector: + name: resource-inventory + filter: + type: '$(var.resource_type)' + status: 'production' + + mapping: + resource_id: 'row.id' + name: 'row.name' + status: 'row.status' + health: 'row.health' + details_link: 'row.name' +``` + +### Composite Metrics View + +Base view with Prometheus metrics: + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: node-metrics +spec: + columns: + - name: node + type: string + primaryKey: true + - name: cpu_percent + type: gauge + + queries: + metrics: + prometheus: + connection: prod + query: 'rate(node_cpu_seconds_total[5m]) * 100' + + mapping: + node: 'row.node' + cpu_percent: 'row.value' +``` + +Composite view that adds more context: + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: nodes-with-metrics +spec: + columns: + - name: node_name + type: string + primaryKey: true + - name: node_type + type: string + - name: status + type: status + - name: cpu_usage + type: gauge + + queries: + nodes: + viewTableSelector: + name: node-inventory + + metrics: + viewTableSelector: + name: node-metrics + + merge: | + SELECT + n.name as node_name, + n.type as node_type, + n.status, + m.cpu_percent as cpu_usage + FROM nodes n + LEFT JOIN metrics m ON n.name = m.node + + mapping: + node_name: 'row.node_name' + node_type: 'row.node_type' + status: 'row.status' + cpu_usage: 'row.cpu_usage' +``` + +### Change Impact Analysis + +Query cached changes using viewTableSelector: + +```yaml +apiVersion: mission-control.flanksource.com/v1 +kind: View +metadata: + name: change-impact +spec: + display: + title: 'Change Impact Analysis' + + templating: + - key: severity + label: 'Minimum Severity' + values: ['info', 'warning', 'critical'] + default: 'warning' + + columns: + - name: change_id + type: string + primaryKey: true + hidden: true + - name: resource + type: string + - name: change_type + type: string + - name: impact + type: health + + queries: + changes: + viewTableSelector: + name: recent-changes + filter: + severity: '$(var.severity)' + + mapping: + change_id: 'row.id' + resource: 'row.resource_name' + change_type: 'row.change_type' + impact: 'row.severity' +``` + +## Performance Tips + +### Use Base Views for Heavy Queries + +Let specialized views handle expensive queries, then compose them: + +```yaml +# ✓ Good: Heavy query in base view +# pod-inventory (queries all configs once) + +# ✓ Good: Light queries on top +# pod-metrics (just adds a column from viewTableSelector) +# pod-summary (just aggregates viewTableSelector results) + +# ✗ Bad: Heavy query in composite view +# every-pod-view (duplicates the config query) +``` + +### Filter Early + +Use the `filter` property to reduce data: + +```yaml +# ✓ Filter in viewTableSelector +queries: + data: + viewTableSelector: + name: all-resources + filter: + status: 'critical' # Reduce data from start + +# ✗ Filter in merge query +# queries all rows, then filters +merge: | + SELECT * FROM data + WHERE status = 'critical' # Filters after loading all +``` + +### Cache Configuration + +Ensure base views have appropriate cache settings: + +```yaml +# Base view should cache longer +cache: + maxAge: 15m + +# Composite view can cache shorter +cache: + maxAge: 5m # Depends on base, but can be fresh more often +``` + +### Variable Dependency + +Use view templating variables for dependent filtering: + +```yaml +# ✓ Good: Variables filter viewTableSelector +templating: + - key: environment + values: ['prod', 'staging'] + +queries: + data: + viewTableSelector: + name: resources + filter: + environment: '$(var.environment)' +# ✗ Avoid: Multiple views don't coordinate variables +``` + +## Troubleshooting + +### View Not Found + +Check: + +1. Is the view name correct? (case-sensitive) +2. Is the namespace correct? +3. Has the base view cached data yet? (Run it manually) + +### No Results + +Check: + +1. Does the base view have data? +2. Are filter values correct? +3. Try removing filters temporarily +4. Check column names match exactly + +### Stale Data + +If you see old data: + +1. Verify base view cache timing +2. Check if base view is being refreshed +3. Consider reducing cache TTL on composite view + +## Limitations + +- Cannot filter on columns that don't exist in the source view +- Filter values must match exactly (case-sensitive) +- Can only query cached view results +- Column types are inherited from source view diff --git a/mission-control/docs/guide/views/table/badge.md b/mission-control/docs/guide/views/table/badge.md new file mode 100644 index 00000000..f160e653 --- /dev/null +++ b/mission-control/docs/guide/views/table/badge.md @@ -0,0 +1,547 @@ +--- +title: Badge +sidebar_custom_props: + icon: mdi:label +--- + +The `badge` column type displays text values as styled badge/tag elements. Badges are useful for displaying categories, labels, versions, or other short text values that benefit from visual distinction. + +## Basic Usage + +```yaml +columns: + - name: version_badge + type: badge +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"badge"` | +| `description` | string | Help text for column | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Version Badge + +```yaml +columns: + - name: version + type: badge + +mapping: + version: "row.properties.version" +``` + +### Label/Tag Badge + +```yaml +columns: + - name: environment + type: badge + +mapping: + environment: "row.properties.environment" +``` + +### Custom Badge from Expression + +```yaml +columns: + - name: tier_badge + type: badge + +mapping: + tier_badge: " + row.properties.tier == 'enterprise' ? 'Enterprise' : + row.properties.tier == 'premium' ? 'Premium' : + 'Free' + " +``` + +## Common Patterns + +### Application Versions +```yaml +columns: + - name: app_version + type: badge + description: "Application version" + +mapping: + app_version: "row.properties.version" +``` + +### Environment Labels +```yaml +columns: + - name: environment + type: badge + description: "Deployment environment" + + - name: region + type: badge + description: "Cloud region" + +mapping: + environment: "row.properties.environment" + region: "row.properties.region" +``` + +### Framework/Runtime Labels +```yaml +columns: + - name: runtime + type: badge + description: "Runtime environment" + + - name: framework + type: badge + description: "Application framework" + +mapping: + runtime: "row.properties.runtime_version" + framework: "row.properties.framework" +``` + +## Real-World Examples + +### Pod Runtime Versions +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: kubernetes_version + type: badge + description: "Kubernetes version" + + - name: container_runtime + type: badge + description: "Container runtime" + + - name: os + type: badge + description: "Operating system" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + kubernetes_version: "row.properties.kubernetes_version" + container_runtime: "row.properties.container_runtime" + os: "row.properties.os" +``` + +### Service Versions and Status +```yaml +columns: + - name: service_name + type: string + primaryKey: true + + - name: current_version + type: badge + description: "Running version" + + - name: target_version + type: badge + description: "Target version" + + - name: language + type: badge + description: "Programming language" + + - name: deployment_method + type: badge + description: "How it's deployed" + +queries: + services: + configs: + types: ["Service::Application"] + +mapping: + service_name: "row.name" + current_version: "row.properties.current_version" + target_version: "row.properties.target_version" + language: "row.properties.language" + deployment_method: "row.properties.deployment_strategy" +``` + +### Infrastructure Provider Tags +```yaml +columns: + - name: resource_id + type: string + primaryKey: true + + - name: provider + type: badge + description: "Cloud provider" + + - name: region + type: badge + description: "Region" + + - name: availability_zone + type: badge + description: "Availability zone" + + - name: instance_type + type: badge + description: "Instance/Machine type" + +queries: + instances: + configs: + types: ["AWS::EC2Instance", "GCP::Instance"] + +mapping: + resource_id: "row.id" + provider: "row.properties.provider" + region: "row.properties.region" + availability_zone: "row.properties.zone" + instance_type: "row.properties.instance_type" +``` + +### Database Configuration +```yaml +columns: + - name: database_name + type: string + primaryKey: true + + - name: engine + type: badge + description: "Database engine" + + - name: version + type: badge + description: "Database version" + + - name: replication_mode + type: badge + description: "Replication configuration" + + - name: backup_type + type: badge + description: "Backup method" + +queries: + databases: + configs: + types: ["Database::Instance"] + +mapping: + database_name: "row.name" + engine: "row.properties.engine" + version: "row.properties.version" + replication_mode: "row.properties.replication_mode" + backup_type: "row.properties.backup_type" +``` + +### Deployment Configuration +```yaml +columns: + - name: deployment + type: string + primaryKey: true + + - name: image_tag + type: badge + description: "Container image tag" + + - name: rollout_strategy + type: badge + description: "Rollout strategy" + + - name: scheduling_policy + type: badge + description: "Scheduling policy" + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment: "row.name" + image_tag: "row.properties.spec.template.spec.containers[0].image.split(':')[1]" + rollout_strategy: "row.properties.spec.strategy.type" + scheduling_policy: "row.properties.spec.template.spec.affinity.type" +``` + +## Badge Expressions in CEL + +### Extracting from Strings +```yaml +mapping: + # Extract image tag from full image name + image_tag: "row.image.split(':')[1]" + + # Extract version from version string + version: "row.version_string.split('-')[0]" +``` + +### Conditional Badges +```yaml +mapping: + # Badge based on condition + tier_badge: " + row.cpu_request > 500 ? 'High-Performance' : + row.cpu_request > 100 ? 'Standard' : + 'Minimal' + " + + # Badge based on multiple conditions + status_badge: " + row.in_maintenance ? 'Maintenance' : + row.failed_checks > 0 ? 'Issues' : + 'Normal' + " +``` + +### Version Comparison +```yaml +mapping: + # Show upgrade needed badge + upgrade_badge: " + row.current_version != row.target_version ? + 'Upgrade: ' + row.target_version : + 'Up-to-date' + " +``` + +## Badge Display Options + +Badges typically display as: +- Rounded rectangles with padding +- Background color (customizable by platform) +- Optional icons +- Text content centered + +Visual styling depends on the platform theme. + +## Filtering + +Enable users to filter by badge values: + +```yaml +columns: + - name: version + type: badge + filter: + type: "multiselect" + +mapping: + version: "row.properties.version" +``` + +Users can then filter to show specific badge values. + +## Best Practices + +1. **Keep badge text short** - Badges work best with short values + ```yaml + # ✓ Short, readable + mapping: + version: "row.version" # "1.25", "v2.0" + + # ✗ Too long + mapping: + description: "row.long_description" + ``` + +2. **Use consistent formatting** - Keep badge values standardized + ```yaml + # ✓ Consistent format + mapping: + version: "row.version" # Always "v1.0" format + + # ✗ Inconsistent + mapping: + version: "row.raw_version" # Sometimes "v1.0", sometimes "1.0" + ``` + +3. **Group related badges** - Show badges together + ```yaml + - name: runtime_version + type: badge + - name: framework_version + type: badge + - name: compiler_version + type: badge + ``` + +4. **Use for categories, not detailed info** - Keep content simple + ```yaml + # ✓ Badge-friendly data + type: badge + mapping: "row.environment" # "prod", "staging", "dev" + + # ✗ Too much detail for badge + type: badge + mapping: "row.full_configuration" # Too verbose + ``` + +5. **Add descriptions** - Explain what badges mean + ```yaml + - name: version + type: badge + description: "Application version" + ``` + +## Comparison with Other Label Types + +| Type | Use Case | +|------|----------| +| `badge` | Short label/tag values (versions, categories) | +| `string` | General text, longer values | +| `status` | Status states (pending, running, failed) | +| `health` | Health states (healthy, warning, critical) | + +Use `badge` for versions and tags. Use `string` for longer text. Use `status` for workflow states. Use `health` for operational health. + +## Common Badge Values + +### Environment Badges +``` +dev +staging +production +qa +integration-test +``` + +### Version Badges +``` +v1.0 +v1.1 +v2.0 +v2.1-beta +latest +``` + +### Provider Badges +``` +AWS +GCP +Azure +On-Premise +Hybrid +``` + +### Language Badges +``` +Go +Python +Java +Node.js +Rust +C++ +``` + +### Architecture Badges +``` +Monolith +Microservices +Serverless +Distributed +``` + +## Real Badge Examples in Views + +### Comprehensive Service View + +```yaml +columns: + - name: service_name + type: string + primaryKey: true + + - name: language + type: badge + description: "Programming language" + + - name: framework + type: badge + description: "Framework/runtime" + + - name: version + type: badge + description: "Current version" + + - name: environment + type: badge + description: "Deployed environment" + + - name: provider + type: badge + description: "Cloud provider" + +queries: + services: + configs: + types: ["Service::Application"] + +mapping: + service_name: "row.name" + language: "row.properties.language" + framework: "row.properties.framework" + version: "row.properties.version" + environment: "row.tags.environment" + provider: "row.tags.provider" +``` + +## Performance Considerations + +- Badge columns are very efficient to render +- Minimal UI overhead even with many badges +- Badge filtering is fast +- No performance impact from badge expressions + +## URL Encoding in Badges + +Badges typically don't need URL encoding unless they contain special characters: + +```yaml +mapping: + # Simple badge - no encoding needed + version: "row.version" # "1.0" + + # Badge with spaces + status_badge: "'Status: ' + row.status" # "Status: Active" +``` + +## Empty/Null Badge Handling + +```yaml +mapping: + # Show empty if null + version: "has(row.version) ? row.version : ''" + + # Show "Unknown" if null + version: "has(row.version) ? row.version : 'Unknown'" + + # Don't show anything if null + version: "has(row.version) ? row.version : null" +``` + +## Accessibility + +Badges should: +- Have sufficient color contrast +- Not rely only on color to convey information +- Include text descriptions in the view description +- Be readable at all zoom levels + +Mission Control handles most accessibility features automatically. diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/boolean.md new file mode 100644 index 00000000..319c7ab6 --- /dev/null +++ b/mission-control/docs/guide/views/table/boolean.md @@ -0,0 +1,370 @@ +--- +title: Boolean +sidebar_custom_props: + icon: mdi:checkbox-marked-outline +--- + +The `boolean` column type displays true/false values as checkboxes or text labels in the table. + +## Basic Usage + +```yaml +columns: + - name: is_running + type: boolean +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"boolean"` | +| `description` | string | Help text for column | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Boolean Display + +```yaml +columns: + - name: enabled + type: boolean + +mapping: + enabled: "row.properties.enabled" +``` + +### Boolean with Description + +```yaml +columns: + - name: has_ssl + type: boolean + description: "SSL/TLS enabled" + +mapping: + has_ssl: "row.properties.ssl_enabled" +``` + +### Boolean from Condition + +```yaml +columns: + - name: is_healthy + type: boolean + +mapping: + is_healthy: "row.health == 'healthy'" +``` + +### Boolean with Filtering + +```yaml +columns: + - name: is_active + type: boolean + filter: + type: "checkbox" + +mapping: + is_active: "row.status == 'active'" +``` + +## Common Patterns + +### Status-Based Boolean +```yaml +mapping: + is_running: "row.status == 'running'" + is_error: "row.status == 'error'" + is_pending: "row.status == 'pending'" +``` + +### Property-Based Boolean +```yaml +mapping: + has_gpu: "has(row.properties.gpu_enabled) ? row.properties.gpu_enabled : false" + is_public: "row.properties.visibility == 'public'" + is_encrypted: "row.properties.encryption_enabled" +``` + +### Complex Logic Boolean +```yaml +mapping: + needs_attention: "row.health != 'healthy' || row.replicas < row.desired_replicas" + is_overprovisioned: "row.actual_usage < (row.allocated * 0.2)" + has_warnings: "row.warning_count > 0" +``` + +## Display Formats + +Booleans typically display as: +- **Checked/Unchecked** - Checkbox-style display +- **True/False** - Text representation +- **Yes/No** - User-friendly text +- **On/Off** - State representation +- **Enabled/Disabled** - Feature state + +The exact display depends on your UI configuration. + +## Real-World Examples + +### Pod Readiness Status +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: is_ready + type: boolean + description: "Pod is ready to serve traffic" + + - name: has_resource_requests + type: boolean + description: "Resource requests are defined" + + - name: is_privileged + type: boolean + description: "Running in privileged mode" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + is_ready: "row.properties.status.conditions.ready" + has_resource_requests: "has(row.properties.spec.containers[0].resources.requests)" + is_privileged: "row.properties.spec.securityContext.privileged" +``` + +### Database Configuration +```yaml +columns: + - name: database_name + type: string + primaryKey: true + + - name: has_backups + type: boolean + description: "Automated backups enabled" + + - name: is_replicated + type: boolean + description: "Database replication enabled" + + - name: ssl_required + type: boolean + description: "SSL connections required" + + - name: audit_logging + type: boolean + description: "Audit logging enabled" + +queries: + databases: + configs: + types: ["Database::Instance"] + +mapping: + database_name: "row.name" + has_backups: "row.properties.backup_enabled" + is_replicated: "row.properties.replication.enabled" + ssl_required: "row.properties.ssl_requirement == 'required'" + audit_logging: "row.properties.audit_config.enabled" +``` + +### Container Security Settings +```yaml +columns: + - name: container + type: string + primaryKey: true + + - name: read_only_fs + type: boolean + description: "Read-only root filesystem" + + - name: run_as_nonroot + type: boolean + description: "Runs as non-root user" + + - name: no_new_privileges + type: boolean + description: "No new privileges flag" + + - name: drop_capabilities + type: boolean + description: "Dangerous capabilities dropped" + +queries: + containers: + configs: + types: ["Kubernetes::Container"] + +mapping: + container: "row.name" + read_only_fs: "row.properties.securityContext.readOnlyRootFilesystem" + run_as_nonroot: "row.properties.securityContext.runAsNonRoot" + no_new_privileges: "row.properties.securityContext.allowPrivilegeEscalation == false" + drop_capabilities: "size(row.properties.securityContext.capabilities.drop) > 0" +``` + +### Infrastructure Compliance +```yaml +columns: + - name: resource_id + type: string + primaryKey: true + + - name: is_compliant + type: boolean + description: "Passes all compliance checks" + + - name: has_monitoring + type: boolean + description: "Monitoring enabled" + + - name: has_tagging + type: boolean + description: "Required tags present" + + - name: encryption_enabled + type: boolean + description: "Encryption at rest" + +queries: + resources: + configs: + types: ["AWS::EC2Instance", "AWS::S3Bucket"] + +mapping: + resource_id: "row.id" + is_compliant: "row.properties.tags['compliance'] == 'true' && row.properties.encryption && row.properties.monitoring" + has_monitoring: "row.properties.monitoring_enabled" + has_tagging: "has(row.tags['compliance']) && has(row.tags['owner'])" + encryption_enabled: "row.properties.encryption.enabled" +``` + +## Filtering with Boolean + +Enable filtering to allow users to show only true or false values: + +```yaml +columns: + - name: is_critical + type: boolean + filter: + type: "checkbox" + +mapping: + is_critical: "row.properties.priority == 'critical'" +``` + +Users can then filter to show: +- All items +- Only `is_critical = true` +- Only `is_critical = false` + +## Boolean Expressions in CEL + +### Comparison Operators +```yaml +mapping: + is_old: "row.created_at < now - duration('90d')" + is_large: "row.size > 1000000" + is_matching: "row.name == 'production'" +``` + +### Logical Operators +```yaml +# AND +mapping: + is_problem: "row.health == 'critical' && row.replicas == 0" + +# OR +mapping: + needs_action: "row.status == 'failed' || row.status == 'pending'" + +# NOT +mapping: + is_not_running: "row.status != 'running'" +``` + +### Collection Checks +```yaml +mapping: + has_items: "size(row.tags) > 0" + contains_prod: "row.environments.contains('production')" +``` + +### Null Checks +```yaml +mapping: + is_set: "has(row.properties.owner)" + is_empty: "!has(row.properties.description) || row.properties.description == ''" +``` + +## Best Practices + +1. **Use meaningful names** - Boolean column names should start with `is_`, `has_`, or similar + ```yaml + - name: is_running # ✓ Clear + - name: enabled # ✓ Clear + - name: pod_bool # ✗ Unclear + ``` + +2. **Provide descriptions** - Always add a description for clarity + ```yaml + - name: is_ready + type: boolean + description: "Pod is ready to serve traffic" + ``` + +3. **Use consistent logic** - Keep true conditions positive + ```yaml + # ✓ True = something good + mapping: + is_healthy: "row.health == 'healthy'" + + # ✗ Confusing + mapping: + is_broken: "row.health == 'critical'" + ``` + +4. **Handle null gracefully** - Default to false when uncertain + ```yaml + mapping: + is_set: "has(row.value) ? row.value : false" + ``` + +## Comparison with Other Types + +| Type | Use Case | +|------|----------| +| `boolean` | Yes/no, true/false states | +| `health` | Health status (healthy/warning/critical) | +| `status` | General status badge | + +Use `boolean` when you have exactly two states. Use `health` or `status` for multiple states. + +## Performance Considerations + +- Boolean columns are extremely efficient +- Boolean filtering is fast even on large datasets +- Boolean values can be indexed for quick filtering +- No performance overhead for boolean calculations + +## UI Display + +Booleans typically render as: +- **Checked box** ☑ for true +- **Unchecked box** ☐ for false +- Or as text labels: "Yes"/"No" or "Enabled"/"Disabled" + +The exact rendering depends on the platform's UI theme. diff --git a/mission-control/docs/guide/views/table/bytes.md b/mission-control/docs/guide/views/table/bytes.md new file mode 100644 index 00000000..5947e575 --- /dev/null +++ b/mission-control/docs/guide/views/table/bytes.md @@ -0,0 +1,488 @@ +--- +title: Bytes +sidebar_custom_props: + icon: mdi:memory +--- + +The `bytes` column type displays byte sizes and automatically formats them with appropriate units (B, KB, MB, GB, TB). + +## Basic Usage + +```yaml +columns: + - name: file_size + type: bytes +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"bytes"` | +| `description` | string | Help text for column | +| `precision` | integer | Decimal places for display | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Byte Size Display + +```yaml +columns: + - name: file_size + type: bytes + +mapping: + file_size: "row.properties.size_bytes" +``` + +### Storage Size with Precision + +```yaml +columns: + - name: storage_used + type: bytes + precision: 2 + +mapping: + storage_used: "row.properties.used_bytes" +``` + +## Auto-Formatting + +The bytes column automatically formats values: + +| Input Value | Display | +|------------|---------| +| 512 | 512 B | +| 1024 | 1 KB | +| 1048576 | 1 MB | +| 1073741824 | 1 GB | +| 1099511627776 | 1 TB | +| 1234567890 | 1.15 GB | + +## Common Patterns + +### Storage Metrics +```yaml +columns: + - name: total_size + type: bytes + - name: used_size + type: bytes + - name: available_size + type: bytes + +mapping: + total_size: "row.properties.total_bytes" + used_size: "row.properties.used_bytes" + available_size: "row.properties.available_bytes" +``` + +### Container Image Sizes +```yaml +columns: + - name: image_name + type: string + primaryKey: true + - name: image_size + type: bytes + - name: compressed_size + type: bytes + +mapping: + image_name: "row.name" + image_size: "row.properties.uncompressed_bytes" + compressed_size: "row.properties.compressed_bytes" +``` + +### Database Storage +```yaml +columns: + - name: database_name + type: string + primaryKey: true + - name: data_size + type: bytes + - name: index_size + type: bytes + - name: total_size + type: bytes + +mapping: + database_name: "row.name" + data_size: "row.properties.data_bytes" + index_size: "row.properties.index_bytes" + total_size: "row.properties.data_bytes + row.properties.index_bytes" +``` + +## Real-World Examples + +### Kubernetes PVC Storage Status +```yaml +columns: + - name: pvc_name + type: string + primaryKey: true + + - name: capacity + type: bytes + description: "Total capacity" + + - name: used + type: bytes + description: "Currently used" + + - name: available + type: bytes + description: "Available space" + +queries: + pvcs: + configs: + types: ["Kubernetes::PersistentVolumeClaim"] + +mapping: + pvc_name: "row.name" + capacity: "row.properties.spec.resources.requests.storage" + used: "row.properties.status.used_bytes" + available: "row.properties.spec.resources.requests.storage - row.properties.status.used_bytes" +``` + +### Volume Snapshot Sizes +```yaml +columns: + - name: snapshot_name + type: string + primaryKey: true + + - name: snapshot_size + type: bytes + description: "Snapshot data size" + + - name: source_volume_size + type: bytes + description: "Original volume size" + +queries: + snapshots: + configs: + types: ["Storage::VolumeSnapshot"] + +mapping: + snapshot_name: "row.name" + snapshot_size: "row.properties.snapshot_bytes" + source_volume_size: "row.properties.source_volume_bytes" +``` + +### Object Storage Inventory +```yaml +columns: + - name: bucket_name + type: string + primaryKey: true + + - name: total_objects + type: number + + - name: total_size + type: bytes + description: "Total data stored" + + - name: avg_object_size + type: bytes + description: "Average object size" + +queries: + buckets: + configs: + types: ["Cloud::S3Bucket", "Cloud::GCSBucket"] + +mapping: + bucket_name: "row.name" + total_objects: "row.properties.object_count" + total_size: "row.properties.total_bytes" + avg_object_size: "row.properties.total_bytes / row.properties.object_count" +``` + +### Log Storage Analysis +```yaml +columns: + - name: log_stream + type: string + primaryKey: true + + - name: log_size + type: bytes + description: "Total log data size" + + - name: retention_bytes + type: bytes + description: "Retention limit" + + - name: age + type: duration + +queries: + logs: + configs: + types: ["Logging::Stream"] + +mapping: + log_stream: "row.name" + log_size: "row.properties.size_bytes" + retention_bytes: "row.properties.retention_bytes_limit" + age: "now - row.properties.first_record_time" +``` + +### Docker Image Statistics +```yaml +columns: + - name: image_id + type: string + primaryKey: true + hidden: true + + - name: image_name + type: string + + - name: size + type: bytes + description: "Uncompressed size" + + - name: virtual_size + type: bytes + description: "Virtual size" + +queries: + images: + prometheus: + connection: docker + query: | + container_image_size_bytes + columns: + image: string + size: number + +mapping: + image_id: "row.image" + image_name: "row.image" + size: "row.size" + virtual_size: "row.size" # Simplified for example +``` + +## Byte Size Expressions in CEL + +### Direct Byte Values +```yaml +mapping: + file_size: "row.properties.bytes" +``` + +### Unit Conversion +```yaml +mapping: + # Gigabytes to bytes + size_bytes: "row.properties.size_gb * 1024 * 1024 * 1024" + + # Megabytes to bytes + size_bytes: "row.properties.size_mb * 1024 * 1024" +``` + +### Byte Calculations +```yaml +mapping: + # Total from components + total_size: "row.properties.data_bytes + row.properties.index_bytes + row.properties.cache_bytes" + + # Percentage of capacity + # (Returns bytes, bytes column will format) + used_size: "(row.capacity_bytes * 0.75)" + + # With conditional + size: "row.type == 'file' ? row.file_bytes : row.directory_bytes" +``` + +## Precision Configuration + +Control decimal places in display: + +```yaml +columns: + - name: size + type: bytes + precision: 2 # Shows "1.23 GB" + +mapping: + size: "row.properties.bytes" +``` + +## Common Byte Sizes + +Reference for common values: +``` +1 KB = 1,024 bytes +1 MB = 1,024 KB = 1,048,576 bytes +1 GB = 1,024 MB = 1,073,741,824 bytes +1 TB = 1,024 GB = 1,099,511,627,776 bytes +1 PB = 1,024 TB = 1,125,899,906,842,624 bytes +``` + +## Real-World Examples with Calculations + +### Storage Utilization Percentage + +```yaml +columns: + - name: volume_name + type: string + primaryKey: true + + - name: total_capacity + type: bytes + + - name: used_space + type: bytes + + - name: utilization_percent + type: gauge + gauge: + max: "100" + thresholds: + - percent: 70 + color: "yellow" + - percent: 85 + color: "red" + +mapping: + volume_name: "row.name" + total_capacity: "row.properties.total_bytes" + used_space: "row.properties.used_bytes" + utilization_percent: "(row.properties.used_bytes / row.properties.total_bytes) * 100" +``` + +### Storage Growth Rate + +```yaml +columns: + - name: dataset_name + type: string + primaryKey: true + + - name: current_size + type: bytes + + - name: size_24h_ago + type: bytes + + - name: daily_growth + type: bytes + +mapping: + dataset_name: "row.name" + current_size: "row.properties.current_bytes" + size_24h_ago: "row.properties.size_24h_ago_bytes" + daily_growth: "row.properties.current_bytes - row.properties.size_24h_ago_bytes" +``` + +## Filtering + +Enable users to filter by size ranges: + +```yaml +columns: + - name: file_size + type: bytes + filter: + type: "range" # If supported, allows range filtering + +mapping: + file_size: "row.properties.bytes" +``` + +## Best Practices + +1. **Use bytes as base unit** - Always store values as bytes + ```yaml + # ✓ Store in bytes + mapping: + size: "row.size_bytes" + + # ✗ Store in MB + mapping: + size: "row.size_mb * 1024 * 1024" + ``` + +2. **Set appropriate precision** - Not too many decimals + ```yaml + # ✓ Reasonable precision + precision: 2 + + # ✗ Too many decimals + precision: 5 + ``` + +3. **Provide context** - Add related metrics + ```yaml + columns: + - name: total_size + type: bytes + - name: used_size + type: bytes + - name: utilization + type: gauge # Show usage too + ``` + +4. **Document limits** - Explain size constraints + ```yaml + - name: storage_used + type: bytes + description: "Current storage used (max 1TB)" + ``` + +5. **Handle edge cases** - Account for zero/null + ```yaml + mapping: + size: "has(row.bytes) ? row.bytes : 0" + ``` + +## Comparison with Other Numeric Types + +| Type | Use Case | +|------|----------| +| `bytes` | Storage sizes (auto-formatted as B, KB, MB, etc.) | +| `number` | Integer or decimal counts | +| `decimal` | Precise float values | + +Use `bytes` for storage, file, and memory sizes. Use `number` for counts. Use `decimal` for calculated percentages. + +## Performance Considerations + +- Byte formatting is very efficient +- Can display large datasets without performance issues +- Byte calculations in CEL are fast +- No significant UI rendering overhead + +## Null/Zero Handling + +```yaml +mapping: + # Default to 0 bytes if unknown + size: "has(row.bytes) ? row.bytes : 0" + + # Show as "Unknown" if null + size: "has(row.bytes) ? row.bytes : null" +``` + +## Display Units + +Bytes are automatically displayed with appropriate units based on size: +- 0-1023 B → Bytes (B) +- 1024-1MB → Kilobytes (KB) +- 1MB-1GB → Megabytes (MB) +- 1GB-1TB → Gigabytes (GB) +- 1TB+ → Terabytes (TB) + +This provides intuitive human-readable display without configuration. diff --git a/mission-control/docs/guide/views/table/config-item.md b/mission-control/docs/guide/views/table/config-item.md new file mode 100644 index 00000000..c398b0fd --- /dev/null +++ b/mission-control/docs/guide/views/table/config-item.md @@ -0,0 +1,608 @@ +--- +title: Config Item +sidebar_custom_props: + icon: config +--- + +The `config_item` column type displays clickable links to configuration item detail pages. It's used to navigate from one view to view details about specific configuration items in the catalog. + +## Basic Usage + +```yaml +columns: + - name: pod_link + type: config_item + configItem: + idField: "id" +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"config_item"` | +| `description` | string | Help text for column | +| `configItem` | object | Config item configuration | +| `for` | string | Column to use as link text | + +## ConfigItem Configuration + +```yaml +configItem: + # Required: which field contains the config item ID + idField: "id" +``` + +## Example Usage + +### Simple Config Link + +```yaml +columns: + - name: pod_detail + type: config_item + configItem: + idField: "id" + +mapping: + pod_detail: "row.id" +``` + +### Config Link with Custom Text + +```yaml +columns: + - name: pod_detail + type: config_item + for: "pod_name" # Use pod_name as display text + configItem: + idField: "id" + +mapping: + pod_name: "row.name" # Display text + pod_detail: "row.id" # The link target +``` + +## Common Patterns + +### Navigation from Summary to Details +```yaml +columns: + - name: resource_name + type: string + primaryKey: true + + - name: resource_detail + type: config_item + for: "resource_name" + configItem: + idField: "id" + +mapping: + resource_name: "row.name" + resource_detail: "row.id" +``` + +### Multiple Config Links +```yaml +columns: + - name: pod + type: string + primaryKey: true + + - name: pod_detail + type: config_item + for: "pod" + configItem: + idField: "id" + + - name: parent_node + type: config_item + for: "node_name" + configItem: + idField: "parent_id" + +mapping: + pod: "row.name" + pod_detail: "row.id" + node_name: "row.parent_name" + parent_node: "row.parent_id" +``` + +## Real-World Examples + +### Pod Summary with Drill-Down + +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: namespace + type: string + + - name: status + type: status + + - name: pod_details + type: config_item + for: "pod_name" + description: "View full pod details" + configItem: + idField: "id" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + namespace: "row.namespace" + status: "row.status" + pod_details: "row.id" +``` + +Clicking the pod name in the `pod_details` column opens the full pod configuration page. + +### Deployment and Related Pods + +```yaml +columns: + - name: deployment_name + type: string + primaryKey: true + + - name: replicas + type: number + + - name: status + type: status + + - name: deployment_config + type: config_item + for: "deployment_name" + description: "View deployment config" + configItem: + idField: "id" + + - name: owner_namespace + type: string + + - name: namespace_config + type: config_item + for: "owner_namespace" + description: "View namespace" + configItem: + idField: "namespace_id" + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment_name: "row.name" + replicas: "row.properties.spec.replicas" + status: "row.status" + deployment_config: "row.id" + owner_namespace: "row.namespace" + namespace_config: "row.namespace_id" +``` + +Users can navigate to either the deployment or namespace configuration details. + +### Container Images with Registry Links + +```yaml +columns: + - name: pod + type: string + primaryKey: true + + - name: image_registry + type: string + + - name: image_config + type: config_item + for: "image_name" + description: "View image details" + configItem: + idField: "image_config_id" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod: "row.name" + image_name: "row.properties.spec.containers[0].image" + image_registry: "row.properties.spec.containers[0].image.split('/')[0]" + image_config: "row.properties.image_config_id" +``` + +### Multi-Level Navigation + +```yaml +columns: + - name: instance_name + type: string + primaryKey: true + + - name: instance_detail + type: config_item + for: "instance_name" + configItem: + idField: "instance_id" + + - name: volume_name + type: string + + - name: volume_detail + type: config_item + for: "volume_name" + configItem: + idField: "volume_id" + + - name: availability_zone + type: string + + - name: az_detail + type: config_item + for: "availability_zone" + configItem: + idField: "az_id" + +queries: + instances: + configs: + types: ["AWS::EC2Instance"] + +mapping: + instance_name: "row.name" + instance_detail: "row.id" + volume_name: "row.properties.volume_name" + volume_detail: "row.properties.volume_id" + availability_zone: "row.properties.az" + az_detail: "row.properties.az_id" +``` + +Navigate from instance → volume → availability zone, drilling down at each level. + +### Service Mesh Components + +```yaml +columns: + - name: service_name + type: string + primaryKey: true + + - name: service_detail + type: config_item + for: "service_name" + configItem: + idField: "service_id" + + - name: virtual_service + type: string + + - name: vs_detail + type: config_item + for: "virtual_service" + configItem: + idField: "vs_id" + + - name: destination_rule + type: string + + - name: dr_detail + type: config_item + for: "destination_rule" + configItem: + idField: "dr_id" + +queries: + services: + configs: + types: ["Istio::Service"] + +mapping: + service_name: "row.name" + service_detail: "row.id" + virtual_service: "row.properties.virtualservice_name" + vs_detail: "row.properties.virtualservice_id" + destination_rule: "row.properties.destination_rule_name" + dr_detail: "row.properties.destination_rule_id" +``` + +Navigate between service, virtual service, and destination rule configurations. + +## Link Text Display + +The link text comes from the `for` property: + +```yaml +columns: + - name: resource_link + type: config_item + for: "resource_name" # Use this column's value as link text + configItem: + idField: "id" + +mapping: + resource_name: "row.name" # Display as link text + resource_link: "row.id" # Link target (not visible) +``` + +The user sees `row.name` as a clickable link. Clicking navigates to the configuration page for `row.id`. + +## Config Item Detail Pages + +Clicking a config_item link opens the configuration detail page for that resource, which includes: +- Full configuration in JSON/YAML +- Property explorer +- Related resources +- Change history +- Cost information (if available) +- Custom properties +- Tags and labels + +## Column Layout + +Typically you'll have: +1. **Display column** (string) - Shows the name/identifier +2. **Link column** (config_item) - Provides the navigation + +```yaml +columns: + # Display what the resource is + - name: pod_name + type: string + primaryKey: true + + # Clickable link to details + - name: pod_details + type: config_item + for: "pod_name" + configItem: + idField: "id" + +mapping: + pod_name: "row.name" + pod_details: "row.id" +``` + +Or combine them: + +```yaml +columns: + - name: pod_detail + type: config_item + for: "pod_name" # Show pod name as link text + configItem: + idField: "id" + +mapping: + pod_name: "row.name" # Display text + pod_detail: "row.id" # Link target +``` + +## Using Variables with Config Links + +You can use variables in config_item expressions: + +```yaml +columns: + - name: cluster_resource + type: config_item + configItem: + idField: "id" + +templating: + - key: cluster + label: "Cluster" + values: ["us-east-1", "us-west-2"] + +mapping: + cluster_resource: "row.id" # Same ID regardless of cluster variable +``` + +The config_item always links by ID; variables don't affect the link target, only which rows are displayed. + +## Best Practices + +1. **Use for navigation** - Make drill-down easy + ```yaml + # ✓ Easy navigation path + - name: pod_name + type: string + - name: pod_detail + type: config_item + ``` + +2. **Provide meaningful text** - Show what the link is about + ```yaml + # ✓ Clear link purpose + for: "pod_name" + + # ✗ Generic link text + for: "link" + ``` + +3. **Use consistent IDs** - ID field must be unique and valid + ```yaml + # ✓ Unique config IDs + idField: "id" + + # ✗ Might not be unique + idField: "name" + ``` + +4. **Add descriptions** - Explain what clicking does + ```yaml + - name: pod_details + type: config_item + description: "View complete pod configuration" + ``` + +5. **Combine with filters** - Use view filters for context + ```yaml + templating: + - key: cluster + values: ["prod", "staging"] + + # User selects cluster, then clicks config_item to drill down + ``` + +## Multiple Config Items + +You can have multiple config_item links in one view: + +```yaml +columns: + - name: pod_detail + type: config_item + for: "pod" + configItem: + idField: "pod_id" + + - name: node_detail + type: config_item + for: "node" + configItem: + idField: "node_id" + +mapping: + pod: "row.pod_name" + pod_detail: "row.pod_id" + node: "row.node_name" + node_detail: "row.node_id" +``` + +Users can navigate to either the pod or node details. + +## Column ID Mapping + +The `idField` property must match your config ID structure: + +```yaml +configItem: + idField: "id" # Simple ID field + # OR + idField: "row.properties.config_id" # Nested ID +``` + +Ensure the mapped value is a valid config ID in the catalog. + +## Filtering for Config Items + +Config items are typically not filtered directly, but you can filter the parent view: + +```yaml +columns: + - name: pod_detail + type: config_item + configItem: + idField: "id" + +# Filter shows/hides rows, which affects what config items are linked +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + status: "running" # Only show running pods + +mapping: + pod_detail: "row.id" +``` + +## Performance Considerations + +- Config_item columns are very efficient +- No performance impact from multiple config_item links +- Links resolve instantly when clicked +- Minimal UI overhead + +## Comparison with URL Column Type + +| Type | Use Case | +|------|----------| +| `config_item` | Navigate to Mission Control config detail page | +| `url` | Navigate to external URLs or custom views | + +Use `config_item` to drill into config details. Use `url` for external links. + +## Real-World Navigation Example + +### Complete Resource Hierarchy + +```yaml +columns: + - name: pod + type: string + primaryKey: true + + - name: pod_detail + type: config_item + for: "pod" + configItem: + idField: "pod_id" + + - name: deployment + type: string + + - name: deployment_detail + type: config_item + for: "deployment" + configItem: + idField: "deployment_id" + + - name: namespace + type: string + + - name: namespace_detail + type: config_item + for: "namespace" + configItem: + idField: "namespace_id" + + - name: cluster + type: string + + - name: cluster_detail + type: config_item + for: "cluster" + configItem: + idField: "cluster_id" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod: "row.name" + pod_detail: "row.id" + deployment: "row.deployment_name" + deployment_detail: "row.deployment_id" + namespace: "row.namespace" + namespace_detail: "row.namespace_id" + cluster: "row.cluster_name" + cluster_detail: "row.cluster_id" +``` + +User can navigate: Pod → Pod Details, Pod → Deployment Details, Pod → Namespace Details, Pod → Cluster Details + +All from a single summary view. + +## Error Handling + +If a config ID is invalid or doesn't exist: +- Link may appear disabled +- Clicking shows an error +- Ensure IDs are valid and exist in your catalog + +Test with sample data before deploying views. diff --git a/mission-control/docs/guide/views/table/datetime.md b/mission-control/docs/guide/views/table/datetime.md new file mode 100644 index 00000000..e3f01928 --- /dev/null +++ b/mission-control/docs/guide/views/table/datetime.md @@ -0,0 +1,408 @@ +--- +title: DateTime +sidebar_custom_props: + icon: mdi:calendar-clock +--- + +The `datetime` column type displays timestamp values formatted as human-readable dates and times. + +## Basic Usage + +```yaml +columns: + - name: created_at + type: datetime +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"datetime"` | +| `description` | string | Help text for column | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Timestamp Display + +```yaml +columns: + - name: created_at + type: datetime + +mapping: + created_at: "row.created_at" +``` + +### DateTime from Calculation + +```yaml +columns: + - name: last_updated + type: datetime + +mapping: + last_updated: "row.updated_at" +``` + +### DateTime with Description + +```yaml +columns: + - name: deployment_time + type: datetime + description: "When this resource was deployed" + +mapping: + deployment_time: "row.properties.deployment_timestamp" +``` + +## Common Patterns + +### Resource Lifecycle Timestamps +```yaml +columns: + - name: created_at + type: datetime + - name: updated_at + type: datetime + - name: deleted_at + type: datetime + +mapping: + created_at: "row.created_at" + updated_at: "row.updated_at" + deleted_at: "row.deleted_at" +``` + +### Event Timeline +```yaml +columns: + - name: event_time + type: datetime + - name: acknowledged_at + type: datetime + - name: resolved_at + type: datetime + +mapping: + event_time: "row.event_timestamp" + acknowledged_at: "row.acknowledgment_timestamp" + resolved_at: "row.resolution_timestamp" +``` + +### Calculated Timestamps +```yaml +columns: + - name: last_check + type: datetime + +mapping: + # Last time status was checked (from metrics) + last_check: "row.properties.last_status_check_time" +``` + +## DateTime Formatting + +The platform automatically formats datetime values. Examples: +- `2024-01-15T10:30:00Z` displays as `Jan 15, 2024 10:30 AM` +- Time zone information is preserved +- Relative times may be shown ("2 hours ago") + +## Real-World Examples + +### Pod Event Timeline +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: created_at + type: datetime + description: "Pod creation time" + + - name: ready_since + type: datetime + description: "When pod became ready" + + - name: last_transition + type: datetime + description: "Last status change" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + created_at: "row.created_at" + ready_since: "row.properties.status.conditions[0].lastTransitionTime" + last_transition: "row.updated_at" +``` + +### Deployment History +```yaml +columns: + - name: deployment + type: string + primaryKey: true + + - name: deployed_at + type: datetime + description: "Deployment time" + + - name: image_built_at + type: datetime + description: "Container image build time" + + - name: last_update + type: datetime + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment: "row.name" + deployed_at: "row.created_at" + image_built_at: "row.properties.image_build_time" + last_update: "row.updated_at" +``` + +### Certificate Expiration Tracking +```yaml +columns: + - name: certificate_name + type: string + primaryKey: true + + - name: issued_at + type: datetime + description: "Issue date" + + - name: expires_at + type: datetime + description: "Expiration date" + + - name: last_renewed + type: datetime + +queries: + certs: + configs: + types: ["Security::Certificate"] + +mapping: + certificate_name: "row.name" + issued_at: "row.properties.not_before" + expires_at: "row.properties.not_after" + last_renewed: "row.properties.renewal_timestamp" +``` + +### Change Audit Trail +```yaml +columns: + - name: change_id + type: string + primaryKey: true + hidden: true + + - name: resource + type: string + + - name: changed_at + type: datetime + description: "When change occurred" + + - name: first_seen + type: datetime + + - name: last_seen + type: datetime + +queries: + changes: + changes: + types: ["Kubernetes::Pod"] + limit: 100 + +mapping: + change_id: "row.id" + resource: "row.config_name" + changed_at: "row.created_at" + first_seen: "row.first_seen_at" + last_seen: "row.last_seen_at" +``` + +### System Events Timeline +```yaml +columns: + - name: event_id + type: string + primaryKey: true + hidden: true + + - name: event_type + type: string + + - name: resource + type: string + + - name: occurred_at + type: datetime + + - name: logged_at + type: datetime + +queries: + events: + configs: + types: ["System::Event"] + +mapping: + event_id: "row.id" + event_type: "row.properties.event_type" + resource: "row.properties.affected_resource" + occurred_at: "row.properties.event_time" + logged_at: "row.created_at" +``` + +## DateTime Filtering + +Enable users to filter by date ranges: + +```yaml +columns: + - name: created_at + type: datetime + filter: + type: "date" + +mapping: + created_at: "row.created_at" +``` + +Users can then filter to show: +- Items created before a date +- Items created after a date +- Items created within a date range + +## DateTime Expressions in CEL + +### Creating DateTime Values +```yaml +mapping: + # Use timestamp conversion + event_time: "timestamp('2024-01-15T10:30:00Z')" + + # Current time + now_time: "now" +``` + +### DateTime Calculations +```yaml +mapping: + # Age in days + age_days: "(now - row.created_at) / duration('24h')" + + # Is old (created more than 90 days ago) + is_old: "row.created_at < now - duration('90d')" + + # Days until expiration + days_until_expiry: "(row.expires_at - now) / duration('24h')" +``` + +### DateTime Comparisons +```yaml +mapping: + is_recent: "row.created_at > now - duration('7d')" + is_expired: "row.expires_at < now" + is_coming_due: "row.expires_at > now && row.expires_at < now + duration('30d')" +``` + +## Best Practices + +1. **Use meaningful names** - DateTime columns should indicate time aspect + ```yaml + - name: created_at # ✓ Clear + - name: last_updated # ✓ Clear + - name: timestamp # ✓ Acceptable + - name: time1 # ✗ Unclear + ``` + +2. **Provide descriptions** - Explain what the timestamp represents + ```yaml + - name: created_at + type: datetime + description: "When this resource was first created" + ``` + +3. **Show timezone** - Include timezone info when relevant + ```yaml + - name: created_at + type: datetime + description: "Creation time (UTC)" + ``` + +4. **Order chronologically** - Present timestamps in logical time order + ```yaml + - name: created_at + type: datetime + - name: updated_at + type: datetime + - name: deleted_at + type: datetime + ``` + +5. **Handle null timestamps** - Default gracefully when time is unknown + ```yaml + mapping: + deleted_at: "has(row.deleted_at) ? row.deleted_at : null" + ``` + +## Comparison with Other Time Types + +| Type | Use Case | +|------|----------| +| `datetime` | Specific point in time (when something happened) | +| `duration` | Length of time (how long something took) | + +Use `datetime` for "when" questions. Use `duration` for "how long" questions. + +## Performance Considerations + +- DateTime columns are efficient to store and retrieve +- DateTime filtering can be optimized with proper indexing +- DateTime calculations in CEL are fast +- No significant performance overhead for datetime operations + +## Timezone Handling + +- All datetimes are stored in UTC internally +- Display timezone depends on user's local settings +- When querying, assume UTC times in database +- CEL expressions work with UTC values + +## Auto-Generated Fields + +Many resources automatically provide: +- `created_at` - When resource was created +- `updated_at` - Last modification time +- `deleted_at` - When resource was deleted (if deleted) + +These are available directly from `row.created_at`, `row.updated_at`, etc. + +## Relative Time Display + +The UI may display datetime values as: +- Absolute: "Jan 15, 2024 10:30 AM" +- Relative: "2 hours ago" +- Combined: "Jan 15, 2024 10:30 AM (2 hours ago)" + +The exact display format depends on UI configuration. diff --git a/mission-control/docs/guide/views/table/decimal.md b/mission-control/docs/guide/views/table/decimal.md new file mode 100644 index 00000000..68760e08 --- /dev/null +++ b/mission-control/docs/guide/views/table/decimal.md @@ -0,0 +1,518 @@ +--- +title: Decimal +sidebar_custom_props: + icon: mdi:decimal +--- + +The `decimal` column type displays precise floating-point numbers with configurable decimal places. Use it for calculated values, percentages, ratios, and other decimal numbers. + +## Basic Usage + +```yaml +columns: + - name: cost_per_hour + type: decimal + precision: 2 +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"decimal"` | +| `description` | string | Help text for column | +| `precision` | integer | Number of decimal places | +| `unit` | string | Display unit (e.g., "$", "%") | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Cost Display + +```yaml +columns: + - name: monthly_cost + type: decimal + precision: 2 + unit: "$" + +mapping: + monthly_cost: "row.cost_total_30d" +``` + +### Percentage Calculation + +```yaml +columns: + - name: error_rate + type: decimal + precision: 2 + unit: "%" + +mapping: + error_rate: "(row.errors / row.total_requests) * 100" +``` + +### Ratio Display + +```yaml +columns: + - name: memory_ratio + type: decimal + precision: 3 + +mapping: + memory_ratio: "row.used_memory / row.total_memory" +``` + +## Common Patterns + +### Financial Calculations +```yaml +columns: + - name: unit_price + type: decimal + precision: 2 + unit: "$" + + - name: total_price + type: decimal + precision: 2 + unit: "$" + +mapping: + unit_price: "row.properties.price" + total_price: "row.properties.price * row.quantity" +``` + +### Performance Metrics +```yaml +columns: + - name: response_time_avg + type: decimal + precision: 2 + unit: "ms" + + - name: throughput + type: decimal + precision: 1 + unit: "req/s" + +mapping: + response_time_avg: "row.total_response_time / row.request_count" + throughput: "row.requests_per_second" +``` + +### Efficiency Metrics +```yaml +columns: + - name: cache_hit_ratio + type: decimal + precision: 3 + + - name: compression_ratio + type: decimal + precision: 2 + +mapping: + cache_hit_ratio: "row.cache_hits / (row.cache_hits + row.cache_misses)" + compression_ratio: "row.original_size / row.compressed_size" +``` + +## Real-World Examples + +### Cost Analysis Dashboard +```yaml +columns: + - name: resource_id + type: string + primaryKey: true + + - name: hourly_rate + type: decimal + precision: 4 + unit: "$" + + - name: daily_cost + type: decimal + precision: 2 + unit: "$" + + - name: monthly_cost + type: decimal + precision: 2 + unit: "$" + + - name: yearly_cost + type: decimal + precision: 2 + unit: "$" + +queries: + resources: + configs: + types: ["AWS::EC2Instance"] + +mapping: + resource_id: "row.id" + hourly_rate: "row.properties.hourly_cost" + daily_cost: "row.properties.hourly_cost * 24" + monthly_cost: "row.cost_total_30d" + yearly_cost: "row.cost_total_30d * 12" +``` + +### API Performance Metrics +```yaml +columns: + - name: endpoint + type: string + primaryKey: true + + - name: avg_response_ms + type: decimal + precision: 2 + unit: "ms" + + - name: p95_response_ms + type: decimal + precision: 2 + unit: "ms" + + - name: p99_response_ms + type: decimal + precision: 2 + unit: "ms" + + - name: error_rate_percent + type: decimal + precision: 3 + unit: "%" + +queries: + metrics: + prometheus: + connection: prod + query: | + { + avg: http_request_duration_seconds, + p95: histogram_quantile(0.95, http_request_duration_seconds), + p99: histogram_quantile(0.99, http_request_duration_seconds), + errors: rate(http_errors_total[5m]) + } + columns: + endpoint: string + avg: decimal + p95: decimal + p99: decimal + errors: decimal + +mapping: + endpoint: "row.endpoint" + avg_response_ms: "row.avg * 1000" + p95_response_ms: "row.p95 * 1000" + p99_response_ms: "row.p99 * 1000" + error_rate_percent: "row.errors * 100" +``` + +### Database Performance Metrics +```yaml +columns: + - name: query_name + type: string + primaryKey: true + + - name: avg_duration_ms + type: decimal + precision: 2 + unit: "ms" + + - name: avg_cpu_percent + type: decimal + precision: 1 + unit: "%" + + - name: avg_memory_mb + type: decimal + precision: 1 + unit: "MB" + +queries: + queries: + configs: + types: ["Database::QueryStatistic"] + +mapping: + query_name: "row.name" + avg_duration_ms: "row.properties.avg_duration_ms" + avg_cpu_percent: "row.properties.avg_cpu_percent" + avg_memory_mb: "row.properties.avg_memory_bytes / 1024 / 1024" +``` + +### Resource Efficiency Report +```yaml +columns: + - name: resource_name + type: string + primaryKey: true + + - name: requested_cpu + type: decimal + precision: 2 + unit: " cores" + + - name: actual_cpu_avg + type: decimal + precision: 2 + unit: " cores" + + - name: utilization_percent + type: decimal + precision: 1 + unit: "%" + + - name: waste_factor + type: decimal + precision: 2 + +mapping: + resource_name: "row.name" + requested_cpu: "row.properties.cpu_request / 1000" + actual_cpu_avg: "row.properties.cpu_avg / 1000" + utilization_percent: "(row.properties.cpu_avg / row.properties.cpu_request) * 100" + waste_factor: "row.properties.cpu_request / row.properties.cpu_avg" +``` + +## Decimal Expressions in CEL + +### Simple Division +```yaml +mapping: + ratio: "row.used / row.total" + percentage: "(row.used / row.total) * 100" +``` + +### Rounding +```yaml +mapping: + # Round to 2 decimal places + price: "round(row.calculated_price, 2)" + + # Round to nearest 0.5 + rating: "round(row.score * 2) / 2" +``` + +### Conditional Decimals +```yaml +mapping: + adjusted_rate: " + row.tier == 'enterprise' ? row.base_rate * 0.9 : + row.tier == 'premium' ? row.base_rate * 0.95 : + row.base_rate + " +``` + +### Range Normalization +```yaml +mapping: + # Normalize to 0-1 range + normalized: "(row.value - row.min) / (row.max - row.min)" + + # Clamp between 0 and 1 + clamped: "min(max(row.value / row.max, 0), 1)" +``` + +## Precision Guidelines + +Choose precision based on your data: + +```yaml +# Currency (cents) +precision: 2 +unit: "$" + +# Percentages (0.01%) +precision: 2 +unit: "%" + +# Time (milliseconds) +precision: 2 +unit: "ms" + +# Ratios (0.001) +precision: 3 + +# Scientific values +precision: 4 or more +``` + +## Real-World Precision Examples + +### Unit Price +```yaml +- name: unit_price + type: decimal + precision: 2 + unit: "$" +# Display: $19.99, $99.99 +``` + +### Efficiency Ratio +```yaml +- name: efficiency + type: decimal + precision: 3 +# Display: 0.950, 0.987, 1.025 +``` + +### Response Time +```yaml +- name: response_time_ms + type: decimal + precision: 2 + unit: "ms" +# Display: 125.43ms, 1250.80ms +``` + +### Error Rate +```yaml +- name: error_rate_percent + type: decimal + precision: 3 + unit: "%" +# Display: 0.123%, 5.456%, 25.000% +``` + +## Filtering + +Enable users to filter by numeric ranges: + +```yaml +columns: + - name: cost_per_month + type: decimal + filter: + type: "range" + +mapping: + cost_per_month: "row.cost_total_30d" +``` + +## Comparison with Other Numeric Types + +| Type | Use Case | +|------|----------| +| `decimal` | Precise floating-point (costs, percentages, ratios) | +| `number` | Integer or decimal counts | +| `gauge` | Percentage 0-100 with visual gauge | +| `bytes` | Storage sizes with auto-formatting | + +Use `decimal` for precise calculations. Use `number` for counts. Use `gauge` for percentages with visualization. + +## Performance Considerations + +- Decimal columns are very efficient +- Decimal calculations in CEL are fast +- Can handle large datasets +- Minimal UI rendering overhead + +## Null/Zero Handling + +```yaml +mapping: + # Default to 0 if unknown + rate: "has(row.rate) ? row.rate : 0" + + # Show as "N/A" if not applicable + ratio: "row.total > 0 ? row.used / row.total : null" + + # Prevent division by zero + percentage: "row.total > 0 ? (row.used / row.total) * 100 : 0" +``` + +## Unit Display + +Units display after the value: +- `19.99 $` (currency) +- `125.43 ms` (milliseconds) +- `0.987` (ratio, no unit) +- `45.50 %` (percentage) + +Configure with the `unit` property in your column definition. + +## Common Decimal Calculations + +### Percentage +```yaml +mapping: + percent: "(row.value / row.total) * 100" +``` + +### Ratio +```yaml +mapping: + ratio: "row.value / row.target" +``` + +### Moving Average +```yaml +mapping: + avg: "(row.sum_1d / row.count_1d)" +``` + +### Growth Rate +```yaml +mapping: + growth: "((row.current - row.previous) / row.previous) * 100" +``` + +### Cost Projection +```yaml +mapping: + monthly_estimate: "row.daily_cost * 30" +``` + +## Best Practices + +1. **Set appropriate precision** - Match your data accuracy + ```yaml + # ✓ Currency needs 2 decimal places + precision: 2 + unit: "$" + + # ✗ Too many decimals for currency + precision: 5 + ``` + +2. **Include units** - Make values understandable + ```yaml + # ✓ Clear what unit represents + unit: "$" + unit: "%" + unit: "ms" + + # ✗ No context + unit: "" + ``` + +3. **Prevent division by zero** - Use conditional logic + ```yaml + mapping: + ratio: "row.denominator > 0 ? row.numerator / row.denominator : 0" + ``` + +4. **Round appropriately** - Use round() for display + ```yaml + mapping: + price: "round(row.calculated, 2)" # Always 2 decimal places + ``` + +5. **Document calculations** - Add descriptions + ```yaml + - name: utilization_percent + type: decimal + precision: 1 + unit: "%" + description: "Actual usage divided by requested resources" + ``` diff --git a/mission-control/docs/guide/views/table/duration.md b/mission-control/docs/guide/views/table/duration.md new file mode 100644 index 00000000..81e64065 --- /dev/null +++ b/mission-control/docs/guide/views/table/duration.md @@ -0,0 +1,422 @@ +--- +title: Duration +sidebar_custom_props: + icon: mdi:timer-outline +--- + +The `duration` column type displays time spans and durations in a human-readable format (e.g., "2h 30m", "1d"). + +## Basic Usage + +```yaml +columns: + - name: uptime + type: duration +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"duration"` | +| `description` | string | Help text for column | +| `unit` | string | Default unit for display (optional) | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Duration Display + +```yaml +columns: + - name: build_time + type: duration + +mapping: + build_time: "row.properties.build_duration" +``` + +### Duration from Timestamp Difference + +```yaml +columns: + - name: pod_age + type: duration + +mapping: + pod_age: "now - row.created_at" +``` + +### Duration with Description + +```yaml +columns: + - name: sla_remaining + type: duration + description: "Time remaining for SLA compliance" + +mapping: + sla_remaining: "row.sla_deadline - now" +``` + +## Common Patterns + +### Resource Lifecycle Durations +```yaml +columns: + - name: uptime + type: duration + description: "Time since creation" + + - name: time_since_update + type: duration + description: "Time since last update" + +mapping: + uptime: "now - row.created_at" + time_since_update: "now - row.updated_at" +``` + +### Process Execution Times +```yaml +columns: + - name: build_time + type: duration + - name: deploy_time + type: duration + - name: total_time + type: duration + +mapping: + build_time: "row.properties.build_end - row.properties.build_start" + deploy_time: "row.properties.deploy_end - row.properties.deploy_start" + total_time: "row.properties.deploy_end - row.properties.build_start" +``` + +### Time to Compliance +```yaml +columns: + - name: sla_time_remaining + type: duration + - name: time_to_expiration + type: duration + +mapping: + sla_time_remaining: "row.sla_deadline - now" + time_to_expiration: "row.expires_at - now" +``` + +## Duration Formatting + +Durations are automatically formatted for readability: +- `3600s` displays as `1h` +- `5400s` displays as `1h 30m` +- `86400s` displays as `1d` +- `2h 30m 45s` displays as written + +## Real-World Examples + +### Pod Uptime Monitoring +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: uptime + type: duration + description: "Time since pod started" + + - name: ready_duration + type: duration + description: "How long pod has been ready" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + uptime: "now - row.created_at" + ready_duration: "now - row.properties.status.conditions[0].lastTransitionTime" +``` + +### CI/CD Pipeline Metrics +```yaml +columns: + - name: build_id + type: string + primaryKey: true + + - name: total_duration + type: duration + description: "Total build time" + + - name: compile_duration + type: duration + description: "Compilation time" + + - name: test_duration + type: duration + description: "Testing time" + + - name: deploy_duration + type: duration + description: "Deployment time" + +queries: + builds: + configs: + types: ["CI::BuildRun"] + +mapping: + build_id: "row.id" + total_duration: "row.properties.end_time - row.properties.start_time" + compile_duration: "row.properties.compile_end - row.properties.compile_start" + test_duration: "row.properties.test_end - row.properties.test_start" + deploy_duration: "row.properties.deploy_end - row.properties.deploy_start" +``` + +### Certificate Expiration Timeline +```yaml +columns: + - name: certificate + type: string + primaryKey: true + + - name: age + type: duration + description: "Certificate age" + + - name: time_until_expiry + type: duration + description: "Time remaining before expiration" + + - name: renewal_window_open + type: duration + description: "Time until renewal window opens" + +queries: + certs: + configs: + types: ["Security::Certificate"] + +mapping: + certificate: "row.name" + age: "now - row.properties.not_before" + time_until_expiry: "row.properties.not_after - now" + renewal_window_open: "(row.properties.not_after - duration('30d')) - now" +``` + +### Backup and Sync Operations +```yaml +columns: + - name: backup_name + type: string + primaryKey: true + + - name: duration_seconds + type: duration + description: "How long backup took" + + - name: age + type: duration + description: "How old the backup is" + + - name: next_backup_in + type: duration + description: "Time until next backup" + +queries: + backups: + configs: + types: ["Backup::Job"] + +mapping: + backup_name: "row.name" + duration_seconds: "row.properties.end_time - row.properties.start_time" + age: "now - row.properties.completed_at" + next_backup_in: "row.properties.next_scheduled - now" +``` + +### SLA Compliance Tracking +```yaml +columns: + - name: incident_id + type: string + primaryKey: true + + - name: time_to_resolution + type: duration + description: "Total time to resolve" + + - name: sla_deadline + type: datetime + + - name: time_to_deadline + type: duration + +queries: + incidents: + configs: + types: ["Incident::Report"] + +mapping: + incident_id: "row.id" + time_to_resolution: "row.properties.resolved_at - row.created_at" + sla_deadline: "row.created_at + duration('4h')" + time_to_deadline: "(row.created_at + duration('4h')) - now" +``` + +## Duration Expressions in CEL + +### Creating Durations +```yaml +mapping: + # Using duration literal + timeout: "duration('5m')" + + # Common durations + hour: "duration('1h')" + day: "duration('24h')" + week: "duration('168h')" + + # Custom calculations + two_hours: "duration('2h')" +``` + +### Duration Calculations +```yaml +mapping: + # Time difference + elapsed: "now - row.start_time" + + # Add duration to time + deadline: "now + duration('30d')" + + # Duration arithmetic + total_time: "(row.end_time - row.start_time) + duration('5m')" +``` + +### Duration Comparisons +```yaml +mapping: + is_old: "(now - row.created_at) > duration('90d')" + is_urgent: "(row.deadline - now) < duration('1h')" + requires_renewal: "(row.expires_at - now) < duration('30d')" +``` + +### Duration to Numeric Value +```yaml +mapping: + # Convert to seconds + seconds: "(now - row.created_at) / duration('1s')" + + # Convert to hours + hours: "(now - row.created_at) / duration('1h')" + + # Convert to days + days: "(now - row.created_at) / duration('24h')" +``` + +## Common Duration Values + +These duration literals are commonly used in CEL: + +``` +1s - 1 second +1m - 1 minute +1h - 1 hour +24h - 1 day +168h - 1 week +720h - 1 month (30 days) +8760h - 1 year (365 days) +``` + +Combine them: +``` +1h30m - 1 hour and 30 minutes +2h45m30s - 2 hours, 45 minutes, 30 seconds +``` + +## Best Practices + +1. **Use meaningful names** - Duration columns should indicate what duration they represent + ```yaml + - name: uptime # ✓ Clear + - name: build_time # ✓ Clear + - name: duration # ? Generic + - name: time1 # ✗ Unclear + ``` + +2. **Provide descriptions** - Explain what the duration measures + ```yaml + - name: uptime + type: duration + description: "Time since pod was created" + ``` + +3. **Handle negative durations** - Document what negative means + ```yaml + - name: time_to_deadline + type: duration + description: "Positive = time remaining, Negative = overdue" + ``` + +4. **Consider filtering** - Enable filtering for common durations + ```yaml + - name: pod_age + type: duration + filter: + type: "duration" + + mapping: + pod_age: "now - row.created_at" + ``` + +5. **Order chronologically** - Present durations in logical order + ```yaml + - name: created_duration # Oldest + - name: modified_duration # More recent + ``` + +## Comparison with Other Time Types + +| Type | Use Case | +|------|----------| +| `duration` | Length of time (how long) | +| `datetime` | Specific point in time (when) | + +Use `duration` for "how long did this take" or "how old is this". Use `datetime` for "when did this happen". + +## Performance Considerations + +- Duration columns are efficient to calculate and display +- Duration calculations in CEL expressions are fast +- No significant performance overhead + +## Display Examples + +How durations appear in the UI: +- `3600s` → `1h` +- `5400s` → `1h 30m` +- `90s` → `1m 30s` +- `86400s` → `1d` +- `604800s` → `7d` +- Negative durations might show as "Past" or display the difference + +## Null Duration Handling + +When duration is unknown or null: + +```yaml +mapping: + # Default to 0 if unknown + duration: "has(row.duration) ? row.duration : duration('0s')" + + # Show as "Not available" + duration: "has(row.duration) ? row.duration : null" +``` diff --git a/mission-control/docs/guide/views/table/gauge.md b/mission-control/docs/guide/views/table/gauge.md new file mode 100644 index 00000000..80afbe5a --- /dev/null +++ b/mission-control/docs/guide/views/table/gauge.md @@ -0,0 +1,567 @@ +--- +title: Gauge +sidebar_custom_props: + icon: mdi:gauge +--- + +The `gauge` column type displays numeric values (typically 0-100) as visual progress bars or gauge visualizations with customizable thresholds and colors. + +## Basic Usage + +```yaml +columns: + - name: cpu_usage + type: gauge + gauge: + max: "100" +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name | +| `type` | string | Set to `"gauge"` | +| `gauge` | object | Gauge configuration | + +## Gauge Configuration + +```yaml +gauge: + # Required: maximum value for the gauge + max: "100" + + # Optional: minimum value (default: 0) + min: "0" + + # Optional: decimal precision + precision: 1 + + # Optional: display unit + unit: "%" + + # Optional: color thresholds + thresholds: + - percent: 50 + color: "yellow" + - percent: 80 + color: "red" + + # Optional: show percentage + showPercent: true + + # Optional: show value + showValue: true +``` + +## Example Usage + +### CPU Usage Percentage + +```yaml +columns: + - name: cpu_percent + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 50 + color: "yellow" + - percent: 80 + color: "red" + +mapping: + cpu_percent: "row.cpu_usage" +``` + +### Memory Usage with Thresholds + +```yaml +columns: + - name: memory_usage + type: gauge + gauge: + max: "100" + precision: 1 + unit: "%" + thresholds: + - percent: 70 + color: "yellow" + - percent: 90 + color: "red" + +mapping: + memory_usage: "(row.memory_used / row.memory_total) * 100" +``` + +### Disk Space Percentage + +```yaml +columns: + - name: disk_usage + type: gauge + gauge: + max: "100" + unit: "%" + showPercent: true + +mapping: + disk_usage: "(row.disk_used / row.disk_total) * 100" +``` + +### Custom Scale Gauge + +```yaml +columns: + - name: connection_pool + type: gauge + gauge: + min: "0" + max: "100" # Max connections + unit: " connections" + showValue: true + +mapping: + connection_pool: "row.active_connections" +``` + +## Common Patterns + +### Resource Utilization +```yaml +columns: + - name: cpu_usage + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 75 + color: "yellow" + - percent: 90 + color: "red" + + - name: memory_usage + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 75 + color: "yellow" + - percent: 90 + color: "red" + +mapping: + cpu_usage: "row.cpu_percent" + memory_usage: "row.memory_percent" +``` + +### Health Score +```yaml +columns: + - name: health_score + type: gauge + gauge: + max: "100" + unit: " points" + thresholds: + - percent: 50 + color: "red" + - percent: 75 + color: "yellow" + +mapping: + health_score: "row.computed_health_score" +``` + +### Capacity Planning +```yaml +columns: + - name: utilization + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 80 + color: "orange" + - percent: 95 + color: "red" + +mapping: + utilization: "(row.used / row.capacity) * 100" +``` + +## Threshold Configuration + +Thresholds define when the gauge color changes: + +```yaml +gauge: + max: "100" + thresholds: + # At 0%, start with green (default) + # At 50%, change to yellow + - percent: 50 + color: "yellow" + # At 80%, change to red + - percent: 80 + color: "red" +``` + +The gauge automatically: +- Shows green (healthy) from 0 to first threshold +- Transitions through colors as value increases +- Shows red (critical) above the last threshold + +## Real-World Examples + +### Node Resource Monitoring +```yaml +columns: + - name: node_name + type: string + primaryKey: true + + - name: cpu_usage + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 70 + color: "yellow" + - percent: 85 + color: "red" + + - name: memory_usage + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 70 + color: "yellow" + - percent: 85 + color: "red" + + - name: disk_usage + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 80 + color: "yellow" + - percent: 90 + color: "red" + +queries: + nodes: + prometheus: + connection: prod + query: | + { + cpu: rate(node_cpu_seconds_total[5m]) * 100, + memory: (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100, + disk: (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 + } + columns: + node: string + cpu: decimal + memory: decimal + disk: decimal + +mapping: + node_name: "row.node" + cpu_usage: "row.cpu" + memory_usage: "row.memory" + disk_usage: "row.disk" +``` + +### Database Connection Pool Status +```yaml +columns: + - name: pool_name + type: string + primaryKey: true + + - name: utilization + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 70 + color: "yellow" + - percent: 90 + color: "red" + + - name: connections_used + type: number + + - name: connections_max + type: number + +queries: + pools: + configs: + types: ["Database::ConnectionPool"] + +mapping: + pool_name: "row.name" + utilization: "(row.properties.active / row.properties.max_connections) * 100" + connections_used: "row.properties.active" + connections_max: "row.properties.max_connections" +``` + +### Kubernetes Pod Resource Requests +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: cpu_allocated + type: gauge + gauge: + max: "2" # 2 CPU cores + unit: " cores" + precision: 2 + showValue: true + + - name: memory_allocated + type: gauge + gauge: + max: "8" # 8 GB + unit: " GB" + precision: 1 + showValue: true + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + cpu_allocated: "row.properties.spec.containers[0].resources.requests.cpu / 1000" + memory_allocated: "row.properties.spec.containers[0].resources.requests.memory / 1024 / 1024 / 1024" +``` + +### SLA Compliance Score +```yaml +columns: + - name: service_name + type: string + primaryKey: true + + - name: sla_compliance + type: gauge + gauge: + max: "100" + unit: "%" + precision: 1 + thresholds: + - percent: 95 + color: "red" # Below 95% SLA = warning + - percent: 99 + color: "yellow" # 95-99% = yellow + + - name: uptime_percent + type: gauge + gauge: + max: "100" + unit: "%" + +mapping: + service_name: "row.name" + sla_compliance: "row.properties.sla_compliance_percent" + uptime_percent: "row.properties.uptime_percent" +``` + +### Storage Capacity Planning +```yaml +columns: + - name: storage_system + type: string + primaryKey: true + + - name: capacity_used + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 70 + color: "yellow" + - percent: 85 + color: "red" + + - name: iops_utilization + type: gauge + gauge: + max: "100" + unit: "%" + thresholds: + - percent: 75 + color: "yellow" + - percent: 90 + color: "red" + +queries: + storage: + configs: + types: ["Storage::Volume"] + +mapping: + storage_system: "row.name" + capacity_used: "(row.properties.used_capacity / row.properties.total_capacity) * 100" + iops_utilization: "(row.properties.current_iops / row.properties.max_iops) * 100" +``` + +## Gauge Expressions in CEL + +### Percentage Calculation +```yaml +mapping: + # Simple percentage + usage_percent: "(row.used / row.total) * 100" + + # Capped at 100% + usage_capped: "min(row.used / row.total, 1.0) * 100" + + # With minimum + usage_min: "max(row.used / row.total, 0.0) * 100" +``` + +### Conditional Gauge Values +```yaml +mapping: + # Use different calculation based on condition + utilization: " + row.type == 'cpu' ? (row.used / 4) * 100 : + row.type == 'memory' ? (row.used / 16) * 100 : + (row.used / row.max) * 100 + " +``` + +## Best Practices + +1. **Set appropriate max values** - Match your scale + ```yaml + # CPU percentage + gauge: + max: "100" + + # Memory in GB + gauge: + max: "16" + + # Connections + gauge: + max: "1000" + ``` + +2. **Use meaningful thresholds** - Match your SLOs + ```yaml + # ✓ Clear thresholds for your use case + thresholds: + - percent: 70 + color: "yellow" + - percent: 85 + color: "red" + + # ✗ Unclear thresholds + thresholds: + - percent: 50 + color: "yellow" + ``` + +3. **Include units** - Make values understandable + ```yaml + gauge: + unit: "%" # ✓ Clear + unit: " GB" # ✓ Clear + unit: "" # ✗ No context + ``` + +4. **Add descriptions** - Explain what's being measured + ```yaml + - name: cpu_usage + type: gauge + description: "CPU utilization (0-100%)" + ``` + +5. **Pair with numeric columns** - Show the actual value too + ```yaml + - name: cpu_gauge + type: gauge + - name: cpu_cores + type: number + unit: " cores" # Show the actual value + ``` + +## Color Themes + +Standard color progression: +- **Green** - Healthy (0-50%) +- **Yellow** - Warning (50-80%) +- **Red** - Critical (80-100%) + +Customize based on your thresholds and needs. + +## Display Options + +Gauges can show: +- **Bar/Progress bar** - Horizontal gauge visualization +- **Circular gauge** - Speedometer-style visualization +- **Value and unit** - Numeric display with unit +- **Percentage** - Show as percentage + +Configuration options: +```yaml +gauge: + showPercent: true # Show % value + showValue: true # Show numeric value + # Display style depends on UI implementation +``` + +## Performance Considerations + +- Gauge calculations are very efficient +- Threshold evaluation is fast +- Can handle large datasets +- Minimal UI rendering overhead + +## Comparison with Other Numeric Types + +| Type | Use Case | +|------|----------| +| `gauge` | Percentage or 0-max range with visual representation | +| `decimal` | Precise numeric values without visualization | +| `number` | Integer or decimal counts | + +Use `gauge` for percentages and ratios. Use `number` for counts. Use `decimal` for precise calculations. + +## Gauge Formula Examples + +### CPU to Percentage +```yaml +mapping: + cpu_percent: "(row.cpu_nanocores / 1000 / 1000) / row.cpu_cores / 100" +``` + +### Memory Percentage +```yaml +mapping: + memory_percent: "(row.memory_bytes / (1024 * 1024 * 1024)) / row.memory_gb * 100" +``` + +### Normalized Score +```yaml +mapping: + score: "min(max(row.raw_score, 0), 100)" +``` diff --git a/mission-control/docs/guide/views/table/health.md b/mission-control/docs/guide/views/table/health.md new file mode 100644 index 00000000..4449deb7 --- /dev/null +++ b/mission-control/docs/guide/views/table/health.md @@ -0,0 +1,410 @@ +--- +title: Health +sidebar_custom_props: + icon: health +--- + +The `health` column type displays health status with color-coded badges showing three states: healthy (green), warning (yellow), and critical (red). + +## Basic Usage + +```yaml +columns: + - name: health_status + type: health +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"health"` | +| `description` | string | Help text for column | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Health States + +The health column supports three states: + +| State | Color | Meaning | +|-------|-------|---------| +| `healthy` | Green | Operating normally, no issues | +| `warning` | Yellow | Minor issues or degradation | +| `critical` | Red | Major issues, needs attention | + +## Example Usage + +### Direct Health Property + +```yaml +columns: + - name: health + type: health + +mapping: + health: "row.health" +``` + +### Health from Status + +```yaml +columns: + - name: pod_health + type: health + +mapping: + pod_health: "row.properties.status" +``` + +### Health from Condition + +```yaml +columns: + - name: cluster_health + type: health + +mapping: + cluster_health: "row.status == 'ready' ? 'healthy' : 'critical'" +``` + +## Common Patterns + +### Simple Health Status +```yaml +mapping: + health: "row.health" +``` + +### Health from Replica Mismatch +```yaml +mapping: + health: "row.replicas == row.ready_replicas ? 'healthy' : row.ready_replicas > 0 ? 'warning' : 'critical'" +``` + +### Health from Multiple Conditions +```yaml +mapping: + health: " + row.cpu_usage > 90 || row.memory_usage > 90 ? 'critical' : + row.cpu_usage > 75 || row.memory_usage > 75 ? 'warning' : + 'healthy' + " +``` + +### Health from Property +```yaml +mapping: + health: "row.properties.health_check_status" +``` + +## Real-World Examples + +### Kubernetes Pod Health +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: health + type: health + description: "Pod health status" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + health: "row.health" +``` + +### Deployment Replica Status +```yaml +columns: + - name: deployment + type: string + primaryKey: true + + - name: replica_health + type: health + description: "Replica status" + + - name: desired_replicas + type: number + + - name: ready_replicas + type: number + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment: "row.name" + replica_health: "row.properties.spec.replicas == row.properties.status.readyReplicas ? 'healthy' : row.properties.status.readyReplicas > 0 ? 'warning' : 'critical'" + desired_replicas: "row.properties.spec.replicas" + ready_replicas: "row.properties.status.readyReplicas" +``` + +### Database Connection Pool Health +```yaml +columns: + - name: pool_name + type: string + primaryKey: true + + - name: health + type: health + description: "Connection pool health" + + - name: active_connections + type: number + + - name: max_connections + type: number + +queries: + pools: + configs: + types: ["Database::ConnectionPool"] + +mapping: + pool_name: "row.name" + health: "row.active_connections >= row.max_connections * 0.9 ? 'critical' : row.active_connections >= row.max_connections * 0.75 ? 'warning' : 'healthy'" + active_connections: "row.properties.active" + max_connections: "row.properties.max_connections" +``` + +### Service Health from Multiple Metrics +```yaml +columns: + - name: service_name + type: string + primaryKey: true + + - name: health + type: health + description: "Overall service health" + + - name: error_rate + type: gauge + + - name: response_time + type: number + unit: "ms" + +queries: + services: + configs: + types: ["Service::Instance"] + +mapping: + service_name: "row.name" + health: " + row.properties.error_rate > 5 || row.properties.response_time > 1000 ? 'critical' : + row.properties.error_rate > 1 || row.properties.response_time > 500 ? 'warning' : + 'healthy' + " + error_rate: "row.properties.error_rate" + response_time: "row.properties.response_time" +``` + +### Infrastructure Node Health +```yaml +columns: + - name: node_name + type: string + primaryKey: true + + - name: health + type: health + description: "Node health" + + - name: cpu_usage + type: gauge + gauge: + max: "100" + + - name: memory_usage + type: gauge + gauge: + max: "100" + + - name: disk_usage + type: gauge + gauge: + max: "100" + +queries: + nodes: + configs: + types: ["Kubernetes::Node"] + +mapping: + node_name: "row.name" + health: " + row.cpu > 90 || row.memory > 90 || row.disk > 90 ? 'critical' : + row.cpu > 75 || row.memory > 75 || row.disk > 75 ? 'warning' : + 'healthy' + " + cpu_usage: "row.properties.cpu_percent" + memory_usage: "row.properties.memory_percent" + disk_usage: "row.properties.disk_percent" +``` + +## Health Filtering + +Enable users to filter by health status: + +```yaml +columns: + - name: health + type: health + filter: + type: "multiselect" + +mapping: + health: "row.health" +``` + +Users can then filter to show: +- All items +- Only healthy items +- Only warning items +- Only critical items +- Any combination of states + +## Health Expressions in CEL + +### Threshold-Based Health +```yaml +mapping: + # Simple threshold + health: "row.cpu_usage > 80 ? 'critical' : 'healthy'" + + # Range-based + health: "row.cpu_usage > 90 ? 'critical' : row.cpu_usage > 75 ? 'warning' : 'healthy'" + + # Multiple conditions + health: " + (row.cpu_usage > 90 || row.memory_usage > 90) ? 'critical' : + (row.cpu_usage > 75 || row.memory_usage > 75) ? 'warning' : + 'healthy' + " +``` + +### State-Based Health +```yaml +mapping: + # Health from status field + health: "row.status == 'active' ? 'healthy' : row.status == 'degraded' ? 'warning' : 'critical'" + + # Health from readiness + health: "row.is_ready ? 'healthy' : 'critical'" +``` + +### Time-Based Health +```yaml +mapping: + # Old items are critical + health: " + (now - row.last_check) > duration('1h') ? 'critical' : + (now - row.last_check) > duration('30m') ? 'warning' : + 'healthy' + " +``` + +## Best Practices + +1. **Use consistent thresholds** - Define thresholds once and reuse across views + ```yaml + # Define at the top level + # CPU: < 75% = healthy, 75-90% = warning, > 90% = critical + # Memory: similar thresholds + ``` + +2. **Document thresholds** - Use descriptions to explain what makes a resource healthy + ```yaml + - name: health + type: health + description: "CPU < 75% = healthy, < 90% = warning, >= 90% = critical" + ``` + +3. **Consider context** - Health meaning may vary by resource type + ```yaml + # For critical services, stricter thresholds + # For development resources, more lenient thresholds + ``` + +4. **Combine with details** - Show health alongside relevant metrics + ```yaml + - name: health + type: health + - name: cpu_usage + type: gauge # Show the actual value too + ``` + +5. **Avoid overcomplication** - Keep health logic understandable + ```yaml + # ✓ Clear and maintainable + health: "row.status == 'healthy' ? 'healthy' : 'critical'" + + # ✗ Complex and hard to understand + health: "size([x for x in row.conditions if x.status == 'ok']) == size(row.conditions) ? 'healthy' : size([x for x in row.conditions if x.status == 'ok']) > 0 ? 'warning' : 'critical'" + ``` + +## Comparison with Other Status Types + +| Type | Use Case | +|------|----------| +| `health` | Three-state health (healthy/warning/critical) | +| `status` | General status badges (any custom status) | +| `boolean` | Binary true/false states | + +Use `health` for operational health. Use `status` for custom statuses like "pending", "failed", "queued", etc. + +## Performance Considerations + +- Health columns are efficient to calculate and display +- Health filtering is fast even with large datasets +- No significant performance overhead for health expressions + +## Visual Representation + +Health states typically display as: +- **Green checkmark** ✓ for healthy +- **Yellow triangle** ⚠ for warning +- **Red X** ✗ for critical + +The exact icons and colors depend on the UI theme. + +## Combining Multiple Health Signals + +To combine multiple health indicators: + +```yaml +columns: + - name: overall_health + type: health + - name: cpu_health + type: health + - name: memory_health + type: health + - name: disk_health + type: health + +mapping: + overall_health: " + (row.cpu_health == 'critical' || row.memory_health == 'critical' || row.disk_health == 'critical') ? 'critical' : + (row.cpu_health == 'warning' || row.memory_health == 'warning' || row.disk_health == 'warning') ? 'warning' : + 'healthy' + " + cpu_health: "row.cpu > 90 ? 'critical' : row.cpu > 75 ? 'warning' : 'healthy'" + memory_health: "row.memory > 90 ? 'critical' : row.memory > 75 ? 'warning' : 'healthy'" + disk_health: "row.disk > 90 ? 'critical' : row.disk > 75 ? 'warning' : 'healthy'" +``` diff --git a/mission-control/docs/guide/views/table/index.mdx b/mission-control/docs/guide/views/table/index.mdx new file mode 100644 index 00000000..9525550c --- /dev/null +++ b/mission-control/docs/guide/views/table/index.mdx @@ -0,0 +1,11 @@ +--- +sidebar_position: 3 +title: Table +sidebar_custom_props: + icon: view-details +--- + + +import DocCardList from '@theme/DocCardList'; + + diff --git a/mission-control/docs/guide/views/table/millicore.md b/mission-control/docs/guide/views/table/millicore.md new file mode 100644 index 00000000..31760a29 --- /dev/null +++ b/mission-control/docs/guide/views/table/millicore.md @@ -0,0 +1,418 @@ +--- +title: Millicore +sidebar_custom_props: + icon: mdi:cpu-64-bit +--- + +The `millicore` column type displays CPU resources in millicores (m) with automatic formatting. 1000 millicores = 1 CPU core. + +## Basic Usage + +```yaml +columns: + - name: cpu_request + type: millicore +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"millicore"` | +| `description` | string | Help text for column | +| `precision` | integer | Decimal places for display | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### CPU Request Display + +```yaml +columns: + - name: cpu_request + type: millicore + +mapping: + cpu_request: "row.properties.cpu_request_m" +``` + +### CPU Limit Display + +```yaml +columns: + - name: cpu_limit + type: millicore + precision: 1 + +mapping: + cpu_limit: "row.properties.cpu_limit_m" +``` + +## Conversion + +Millicores are the standard unit for Kubernetes CPU requests/limits: + +| Value | Display | Meaning | +|-------|---------|---------| +| 100 | 100m | 0.1 CPU core (10% of a core) | +| 500 | 500m | 0.5 CPU core (50% of a core) | +| 1000 | 1000m or 1 | 1 full CPU core | +| 2000 | 2000m or 2 | 2 CPU cores | +| 2500 | 2500m or 2.5 | 2.5 CPU cores | + +## Common Patterns + +### Pod Resource Limits +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: cpu_request + type: millicore + + - name: cpu_limit + type: millicore + +mapping: + pod_name: "row.name" + cpu_request: "row.properties.spec.containers[0].resources.requests.cpu_m" + cpu_limit: "row.properties.spec.containers[0].resources.limits.cpu_m" +``` + +### Node CPU Capacity +```yaml +columns: + - name: node_name + type: string + primaryKey: true + + - name: allocatable_cpu + type: millicore + + - name: requested_cpu + type: millicore + + - name: available_cpu + type: millicore + +mapping: + node_name: "row.name" + allocatable_cpu: "row.properties.status.allocatable.cpu_m" + requested_cpu: "row.properties.status.requested.cpu_m" + available_cpu: "row.properties.status.allocatable.cpu_m - row.properties.status.requested.cpu_m" +``` + +## Real-World Examples + +### Pod CPU Requests and Limits +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: container + type: string + + - name: cpu_request + type: millicore + description: "Requested CPU (minimum guaranteed)" + + - name: cpu_limit + type: millicore + description: "CPU limit (maximum allowed)" + + - name: cpu_usage + type: millicore + description: "Current actual usage" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + container: "row.properties.spec.containers[0].name" + cpu_request: "row.properties.spec.containers[0].resources.requests.cpu * 1000" + cpu_limit: "row.properties.spec.containers[0].resources.limits.cpu * 1000" + cpu_usage: "row.properties.metrics.cpu_m" +``` + +### Node Resource Allocation +```yaml +columns: + - name: node_name + type: string + primaryKey: true + + - name: total_capacity + type: millicore + description: "Total CPU capacity" + + - name: allocatable + type: millicore + description: "CPU available for pods" + + - name: requested + type: millicore + description: "Sum of all pod requests" + + - name: available + type: millicore + description: "Remaining unallocated CPU" + +queries: + nodes: + configs: + types: ["Kubernetes::Node"] + +mapping: + node_name: "row.name" + total_capacity: "row.properties.status.capacity.cpu * 1000" + allocatable: "row.properties.status.allocatable.cpu * 1000" + requested: "row.properties.status.requested.cpu * 1000" + available: "(row.properties.status.allocatable.cpu - row.properties.status.requested.cpu) * 1000" +``` + +### Deployment CPU Planning +```yaml +columns: + - name: deployment_name + type: string + primaryKey: true + + - name: replicas + type: number + + - name: cpu_per_replica + type: millicore + + - name: total_cpu_requested + type: millicore + + - name: total_cpu_limit + type: millicore + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment_name: "row.name" + replicas: "row.properties.spec.replicas" + cpu_per_replica: "row.properties.spec.template.spec.containers[0].resources.requests.cpu * 1000" + total_cpu_requested: "row.properties.spec.replicas * row.properties.spec.template.spec.containers[0].resources.requests.cpu * 1000" + total_cpu_limit: "row.properties.spec.replicas * row.properties.spec.template.spec.containers[0].resources.limits.cpu * 1000" +``` + +### Resource Request Validation +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: cpu_request + type: millicore + + - name: is_request_reasonable + type: health + description: "Request is between 10m and 2000m" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + cpu_request: "row.properties.spec.containers[0].resources.requests.cpu * 1000" + is_request_reasonable: " + has(row.properties.spec.containers[0].resources.requests) && + row.cpu_request >= 10 && + row.cpu_request <= 2000 + ? 'healthy' : 'warning' + " +``` + +## Millicore Expressions in CEL + +### Convert from CPU Cores to Millicores +```yaml +mapping: + # From cores to millicores + cpu_m: "row.cpu_cores * 1000" + + # From string "0.5" to 500m + cpu_m: "float(row.cpu_string) * 1000" +``` + +### Calculate Total CPU +```yaml +mapping: + total_cpu_m: "row.replicas * row.cpu_per_replica_m" +``` + +### CPU Allocation Percentage +```yaml +mapping: + allocation_percent: "(row.requested_m / row.allocatable_m) * 100" +``` + +### CPU Headroom +```yaml +mapping: + available_m: "row.allocatable_m - row.requested_m" +``` + +## Comparison with Cores + +Millicore is Kubernetes' standard unit: + +```yaml +# ✓ Use millicores (Kubernetes standard) +cpu_request: "row.resources.requests.cpu * 1000" # Convert to millicore + +# ✗ Don't use cores for Kubernetes +cpu_request: "row.resources.requests.cpu" # Would be fractional + +# ✓ Display with millicore type +type: millicore +``` + +## Real-World Millicore Values + +Common CPU requests in Kubernetes: + +| Value | Typical Use Case | +|-------|-----------------| +| 10-50m | Sidecar containers, minimal overhead | +| 50-100m | Small services, non-critical apps | +| 100-250m | Standard services, small microservices | +| 250-500m | Medium services, moderate workloads | +| 500m-1 | Larger services, significant computation | +| 1-2 | CPU-intensive workloads | +| 2+ | High-performance applications | + +## Best Practices + +1. **Use millicore for Kubernetes CPU** - It's the standard unit + ```yaml + # ✓ Kubernetes standard + type: millicore + + # ✗ Avoid raw core values + type: decimal + ``` + +2. **Provide meaningful defaults** - Common requests + ```yaml + # ✓ Standard requests + - 100m (10% of a core) + - 250m (25% of a core) + - 500m (50% of a core) + - 1000m (1 full core) + ``` + +3. **Set request and limit together** - Show both + ```yaml + - name: cpu_request + type: millicore + - name: cpu_limit + type: millicore + ``` + +4. **Validate reasonable ranges** - Use health checks + ```yaml + - name: cpu_validity + type: health + description: "Request is reasonable" + ``` + +5. **Monitor node capacity** - Show what's available + ```yaml + - name: available_cpu + type: millicore + description: "Unallocated CPU on node" + ``` + +## Filtering + +Enable filtering by CPU ranges: + +```yaml +columns: + - name: cpu_request + type: millicore + filter: + type: "range" + +mapping: + cpu_request: "row.cpu_request_m" +``` + +Users can filter to find: +- Pods with excessive CPU requests +- Pods with too little CPU +- Nodes with low CPU availability + +## Performance Considerations + +- Millicore columns are very efficient +- Millicore calculations are fast +- Can handle large pod counts +- No significant UI overhead + +## Comparison with Other Resource Types + +| Type | Use Case | +|------|----------| +| `millicore` | CPU resources in millicores (Kubernetes standard) | +| `bytes` | Memory in bytes | +| `number` | Other numeric values | +| `decimal` | Floating-point calculations | + +Use `millicore` specifically for CPU. Use `bytes` for memory. Use `number` for counts. + +## Null/Zero Handling + +```yaml +mapping: + # Default to 0 if not specified + cpu_request: "has(row.cpu_request_m) ? row.cpu_request_m : 0" + + # Show "unlimited" if no limit + cpu_limit: "has(row.cpu_limit_m) ? row.cpu_limit_m : null" +``` + +## Common Millicore Calculations + +### Total CPU for Deployment +```yaml +mapping: + total_cpu: "row.spec.replicas * row.spec.containers[0].resources.requests.cpu * 1000" +``` + +### CPU Headroom on Node +```yaml +mapping: + available_cpu: "(row.allocatable.cpu - row.requested.cpu) * 1000" +``` + +### CPU Over-subscription Ratio +```yaml +mapping: + ratio: "row.requested.cpu / row.allocatable.cpu" +``` + +### CPU Burst Headroom +```yaml +mapping: + burst_available: "(row.allocatable.cpu - row.requested_limit.cpu) * 1000" +``` diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/number.md new file mode 100644 index 00000000..7ab163b9 --- /dev/null +++ b/mission-control/docs/guide/views/table/number.md @@ -0,0 +1,330 @@ +--- +title: Number +sidebar_custom_props: + icon: mdi:numeric +--- + +The `number` column type displays numeric values in a standard number format. This includes integers and decimal values. + +## Basic Usage + +```yaml +columns: + - name: pod_count + type: number +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"number"` | +| `description` | string | Help text for column | +| `unit` | string | Display unit (e.g., "pods", "requests/sec") | +| `precision` | integer | Decimal places to display | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Count Display + +```yaml +columns: + - name: replica_count + type: number + +mapping: + replica_count: "row.properties.replicas" +``` + +### Number with Precision + +```yaml +columns: + - name: cpu_cores + type: number + precision: 2 + +mapping: + cpu_cores: "row.properties.cpu_limit / 1000" +``` + +### Number with Unit + +```yaml +columns: + - name: request_rate + type: number + unit: "requests/sec" + +mapping: + request_rate: "row.properties.requests_per_second" +``` + +### Number from Calculation + +```yaml +columns: + - name: uptime_days + type: number + precision: 1 + +mapping: + uptime_days: "(now - row.created_at) / duration('24h')" +``` + +## Common Patterns + +### Pod/Replica Counts +```yaml +columns: + - name: desired_replicas + type: number + - name: ready_replicas + type: number + +mapping: + desired_replicas: "row.properties.spec.replicas" + ready_replicas: "row.properties.status.readyReplicas" +``` + +### Resource Quotas +```yaml +columns: + - name: cpu_allocated + type: number + unit: "cores" + - name: memory_allocated + type: number + unit: "GB" + +mapping: + cpu_allocated: "row.properties.cpu_limit / 1000" + memory_allocated: "row.properties.memory_limit / 1024 / 1024 / 1024" +``` + +### Calculated Metrics +```yaml +columns: + - name: average_response_time + type: number + unit: "ms" + precision: 2 + +mapping: + average_response_time: "row.total_response_time / row.request_count" +``` + +## Number Formatting + +### Whole Numbers +```yaml +columns: + - name: pod_count + type: number + precision: 0 + +mapping: + pod_count: "row.properties.pod_count" +``` + +### Decimal Values +```yaml +columns: + - name: cpu_usage + type: number + precision: 3 + unit: "cores" + +mapping: + cpu_usage: "row.properties.cpu_usage_cores" +``` + +## Filtering + +Enable users to filter by numeric ranges or exact values: + +```yaml +columns: + - name: replica_count + type: number + filter: + type: "number" # Enables numeric filtering + +mapping: + replica_count: "row.properties.replicas" +``` + +## Real-World Examples + +### Kubernetes Deployment Status +```yaml +columns: + - name: deployment + type: string + primaryKey: true + + - name: desired_replicas + type: number + + - name: ready_replicas + type: number + + - name: available_replicas + type: number + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment: "row.name" + desired_replicas: "row.properties.spec.replicas" + ready_replicas: "row.properties.status.readyReplicas" + available_replicas: "row.properties.status.availableReplicas" +``` + +### Database Connection Pool +```yaml +columns: + - name: pool_name + type: string + primaryKey: true + + - name: total_connections + type: number + + - name: active_connections + type: number + + - name: idle_connections + type: number + +queries: + pools: + configs: + types: ["Database::ConnectionPool"] + +mapping: + pool_name: "row.name" + total_connections: "row.properties.max_connections" + active_connections: "row.properties.active" + idle_connections: "row.properties.idle" +``` + +### API Request Metrics +```yaml +columns: + - name: endpoint + type: string + primaryKey: true + + - name: total_requests + type: number + unit: "requests" + + - name: error_rate_percent + type: number + unit: "%" + precision: 2 + + - name: avg_latency_ms + type: number + unit: "ms" + precision: 1 + +queries: + metrics: + prometheus: + connection: prod + query: | + { + requests: increase(http_requests_total[1h]), + errors: increase(http_errors_total[1h]), + latency: histogram_quantile(0.95, http_request_duration_seconds) + } + columns: + endpoint: string + requests: number + errors: number + latency: decimal + +mapping: + endpoint: "row.endpoint" + total_requests: "row.requests" + error_rate_percent: "(row.errors / row.requests) * 100" + avg_latency_ms: "row.latency * 1000" +``` + +## Comparison with Other Numeric Types + +| Type | Use Case | +|------|----------| +| `number` | General numeric values (counts, ratios, metrics) | +| `decimal` | Precise floating-point values (costs, percentages) | +| `gauge` | Percentage or 0-100 values with visual gauge | +| `bytes` | Binary storage sizes (auto-formatted as KB, MB, GB) | +| `millicore` | CPU resources in millicores | + +## Best Practices + +1. **Use appropriate precision** - Don't display unnecessary decimal places + ```yaml + - name: replica_count + type: number + precision: 0 # No decimals needed for counts + ``` + +2. **Add meaningful units** - Help users understand what they're viewing + ```yaml + - name: memory_mb + type: number + unit: "MB" + ``` + +3. **Validate ranges** - Consider using `gauge` for percentage-like values + ```yaml + - name: health_score # 0-100 + type: gauge # Better than number + ``` + +4. **Round appropriately** - Avoid very large or very small numbers + ```yaml + mapping: + # ✓ Round to reasonable precision + cpu_cores: "round(row.cpu_millis / 1000, 2)" + + # ✗ Too many decimals + cpu_cores: "row.cpu_millis / 1000" + ``` + +5. **Use negative values carefully** - Number can display negatives but document them + ```yaml + columns: + - name: balance_change + type: number + description: "Positive = increase, Negative = decrease" + ``` + +## Performance Considerations + +- Numeric columns are very efficient +- Numeric filtering can be optimized with database indexes +- Avoid complex calculations for large datasets +- Consider pre-calculating values in queries when possible + +## Null and Zero Handling + +Numbers default to 0 if null. Use CEL expressions to handle special cases: + +```yaml +mapping: + # ✓ Handle null values + count: "has(row.count) ? row.count : 0" + + # Display different text for zero + status_text: "row.count == 0 ? 'No items' : string(row.count) + ' items'" +``` diff --git a/mission-control/docs/guide/views/table/status.md b/mission-control/docs/guide/views/table/status.md new file mode 100644 index 00000000..59f93656 --- /dev/null +++ b/mission-control/docs/guide/views/table/status.md @@ -0,0 +1,424 @@ +--- +title: Status +sidebar_custom_props: + icon: mdi:list-status +--- + +The `status` column type displays custom status badges for any status values. Unlike `health` which is limited to three states, `status` supports any custom status string. + +## Basic Usage + +```yaml +columns: + - name: pod_status + type: status +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"status"` | +| `description` | string | Help text for column | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Direct Status Property + +```yaml +columns: + - name: status + type: status + +mapping: + status: "row.status" +``` + +### Status from Custom Field + +```yaml +columns: + - name: deployment_status + type: status + +mapping: + deployment_status: "row.properties.deployment_state" +``` + +### Status from Condition + +```yaml +columns: + - name: build_status + type: status + +mapping: + build_status: "row.properties.result == 0 ? 'success' : 'failed'" +``` + +## Common Patterns + +### Kubernetes Pod States +```yaml +mapping: + status: "row.status" # pending, running, succeeded, failed, unknown +``` + +### Build/Deployment States +```yaml +mapping: + status: "row.properties.state" # created, running, succeeded, failed, cancelled +``` + +### Replica States +```yaml +mapping: + status: "row.desired == row.ready ? 'ready' : row.ready > 0 ? 'updating' : 'not-ready'" +``` + +### Custom Status Values +```yaml +mapping: + status: "row.properties.status" # Can be any string +``` + +## Real-World Examples + +### Pod Status Display +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: status + type: status + description: "Current pod state" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + status: "row.status" # pending, running, succeeded, failed, unknown +``` + +### Build Pipeline Status +```yaml +columns: + - name: build_id + type: string + primaryKey: true + + - name: status + type: status + description: "Build state" + + - name: stage + type: status + description: "Current stage" + +queries: + builds: + configs: + types: ["CI::Build"] + +mapping: + build_id: "row.id" + status: "row.properties.state" # created, queued, running, succeeded, failed + stage: "row.properties.current_stage" # build, test, deploy +``` + +### Deployment Rollout Status +```yaml +columns: + - name: deployment + type: string + primaryKey: true + + - name: status + type: status + description: "Rollout status" + + - name: desired_replicas + type: number + + - name: ready_replicas + type: number + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment: "row.name" + status: "row.desired == row.ready ? 'ready' : row.ready > 0 ? 'updating' : 'pending'" + desired_replicas: "row.properties.spec.replicas" + ready_replicas: "row.properties.status.readyReplicas" +``` + +### Database Migration Status +```yaml +columns: + - name: migration_id + type: string + primaryKey: true + + - name: database + type: string + + - name: status + type: status + description: "Migration state" + +queries: + migrations: + configs: + types: ["Database::Migration"] + +mapping: + migration_id: "row.id" + database: "row.properties.database_name" + status: "row.properties.state" # pending, running, succeeded, failed, rolled_back +``` + +### Job Execution Status +```yaml +columns: + - name: job_id + type: string + primaryKey: true + + - name: job_name + type: string + + - name: status + type: status + description: "Job execution status" + + - name: attempt + type: number + +queries: + jobs: + configs: + types: ["Job::Run"] + +mapping: + job_id: "row.id" + job_name: "row.name" + status: "row.properties.execution_status" # pending, running, succeeded, failed, skipped + attempt: "row.properties.attempt_number" +``` + +## Complex Status Logic + +### Multi-Step Status Determination +```yaml +columns: + - name: resource + type: string + primaryKey: true + + - name: status + type: status + +mapping: + status: " + row.properties.state == 'error' ? 'error' : + row.properties.state == 'pending' ? 'pending' : + !row.properties.is_configured ? 'not-configured' : + !row.properties.is_healthy ? 'degraded' : + 'ready' + " +``` + +### Status from Resource Type +```yaml +mapping: + status: " + row.type == 'Kubernetes::Pod' ? row.status : + row.type == 'Kubernetes::Deployment' ? (row.desired == row.ready ? 'ready' : 'updating') : + row.type == 'Kubernetes::Node' ? (row.is_ready ? 'ready' : 'not-ready') : + 'unknown' + " +``` + +## Status Filtering + +Enable users to filter by status values: + +```yaml +columns: + - name: status + type: status + filter: + type: "multiselect" + +mapping: + status: "row.status" +``` + +Users can then filter to show: +- All statuses +- Only specific statuses (e.g., only "running" and "pending") +- Combinations of statuses + +## Status Values by Resource Type + +### Kubernetes Pod Status +- `pending` - Waiting for resources +- `running` - Pod is executing +- `succeeded` - Completed successfully +- `failed` - Execution failed +- `unknown` - Status unknown + +### Kubernetes Deployment Status +- `progressing` - Rolling out new version +- `available` - Deployment is available +- `replicas-failure` - Replica creation failed + +### CI/CD Pipeline Status +- `created` - Job created +- `queued` - Waiting to run +- `running` - Currently executing +- `succeeded` - Completed successfully +- `failed` - Failed to complete +- `cancelled` - Manually cancelled +- `skipped` - Skipped (conditional) + +### Database/Data Status +- `pending` - Waiting to start +- `running` - Currently executing +- `succeeded` - Completed +- `failed` - Failed +- `cancelled` - Cancelled +- `rolled_back` - Rolled back + +## Status Display + +Status values display as badges with: +- **Status text** - The status value itself +- **Color coding** - Varies by platform, typically: + - Green: success, succeeded, running, ready + - Yellow: warning, pending, updating, degraded + - Red: failed, error, critical + - Gray: unknown, cancelled, skipped + +## Best Practices + +1. **Use consistent naming** - Keep status values consistent across resources + ```yaml + # ✓ Consistent + succeeded/failed/pending + + # ✗ Inconsistent + success/fail/wait + ``` + +2. **Document possible values** - List all possible status values in descriptions + ```yaml + - name: status + type: status + description: "Can be: pending, running, succeeded, failed, unknown" + ``` + +3. **Keep values lowercase** - Use lowercase status values for consistency + ```yaml + # ✓ Good + status: "row.properties.state.toLowerCase()" + + # ✗ Inconsistent case + status: "row.properties.state" + ``` + +4. **Combine with details** - Show status alongside relevant information + ```yaml + - name: status + type: status + - name: reason + type: string # Why it has this status + - name: since + type: datetime # When it changed + ``` + +5. **Filter for investigation** - Enable filtering for troubleshooting + ```yaml + - name: status + type: status + filter: + type: "multiselect" + ``` + +## Comparison with Other Status Types + +| Type | Use Case | +|------|----------| +| `status` | Custom multi-value statuses (pending, running, failed, etc.) | +| `health` | Three-state operational health (healthy/warning/critical) | +| `boolean` | Binary true/false states | + +Use `status` for workflow states, execution states, or anything with 4+ possible values. Use `health` for operational health. Use `boolean` for simple on/off states. + +## Performance Considerations + +- Status columns are very efficient to display and filter +- Status filtering is optimized for common status values +- No performance overhead for status expressions + +## Status vs Health + +**Health** answers "Is this healthy?" (healthy/warning/critical) +**Status** answers "What is the current state?" (pending/running/failed/succeeded) + +Example: +- A pod with status `running` might have health `critical` (not enough resources) +- A pod with status `pending` might have health `warning` (taking a while to start) +- A pod with status `succeeded` has health `healthy` (completed successfully) + +You can use both together for complete information. + +## Practical Example: Multi-Status View + +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: pod_status + type: status + description: "Kubernetes pod state" + + - name: health + type: health + description: "Resource health" + + - name: reason + type: string + description: "Status reason" + + - name: since + type: datetime + description: "When status changed" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + pod_status: "row.status" # pending, running, succeeded, failed + health: "row.health" # healthy, warning, critical + reason: "row.properties.status.reason" + since: "row.properties.status.lastTransitionTime" +``` + +This provides complete visibility into both the current state and the health of the resource. diff --git a/mission-control/docs/guide/views/table/string.md b/mission-control/docs/guide/views/table/string.md new file mode 100644 index 00000000..84c9e898 --- /dev/null +++ b/mission-control/docs/guide/views/table/string.md @@ -0,0 +1,314 @@ +--- +title: String +sidebar_custom_props: + icon: mdi:format-text +--- + +The `string` column type displays text values as a simple text field in the table. + +## Basic Usage + +```yaml +columns: + - name: pod_name + type: string + primaryKey: true +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"string"` | +| `description` | string | Help text for column | +| `primaryKey` | boolean | Is this part of the unique identifier? | +| `hidden` | boolean | Hide column from UI | +| `unit` | string | Display unit suffix (e.g., "ms") | +| `filter` | object | Enable filtering on this column | +| `card` | object | Configure card layout position | + +## Example Usage + +### Simple Text Display + +```yaml +columns: + - name: name + type: string + primaryKey: true + +queries: + resources: + configs: + types: ["Kubernetes::Pod"] + +mapping: + name: "row.name" +``` + +### String with Description + +```yaml +columns: + - name: region + type: string + description: "AWS region" + +mapping: + region: "row.properties.region" +``` + +### String with Filtering + +Enable users to filter by string values: + +```yaml +columns: + - name: environment + type: string + filter: + type: "text" + +mapping: + environment: "row.properties.environment" +``` + +### String with Unit Display + +```yaml +columns: + - name: version + type: string + unit: "v" # Displays as "v1.25" + +mapping: + version: "row.properties.kubernetes_version" +``` + +### Composite Strings from Expressions + +Use CEL expressions to create formatted strings: + +```yaml +columns: + - name: display_name + type: string + primaryKey: true + +mapping: + display_name: "'Pod: ' + row.name + ' (' + row.namespace + ')'" +``` + +## Common Patterns + +### Display Config Item Type +```yaml +mapping: + type: "row.type" +``` + +### Namespace Display +```yaml +mapping: + namespace: "row.namespace" +``` + +### Custom Property +```yaml +mapping: + image: "row.properties.container_image" +``` + +### Formatted Status Message +```yaml +mapping: + message: "row.health == 'healthy' ? 'OK' : 'Check required'" +``` + +## Filtering + +When you add filter configuration, users can: +- Search for text values +- Filter by exact match +- Filter by partial match (if supported) + +```yaml +columns: + - name: pod_name + type: string + filter: + type: "text" + + - name: label + type: string + filter: + type: "multiselect" # Users can select multiple values +``` + +## String Mapping Examples + +### Simple Direct Mapping +```yaml +mapping: + name: "row.name" +``` + +### Concatenation +```yaml +mapping: + full_location: "row.region + '/' + row.zone" +``` + +### Conditional Values +```yaml +mapping: + status_text: "row.status == 'running' ? 'Active' : 'Inactive'" +``` + +### Extracted from Properties +```yaml +mapping: + owner: "row.properties.owner_email" +``` + +### Optional String with Default +```yaml +mapping: + description: "has(row.properties.description) ? row.properties.description : 'No description'" +``` + +## Real-World Examples + +### Pod Details View +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: namespace + type: string + + - name: node + type: string + + - name: image + type: string + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + namespace: "row.namespace" + node: "row.properties.node_name" + image: "row.properties.container_image" +``` + +### AWS Resource Labels +```yaml +columns: + - name: instance_id + type: string + primaryKey: true + + - name: instance_type + type: string + + - name: subnet_id + type: string + + - name: availability_zone + type: string + +queries: + instances: + configs: + types: ["AWS::EC2Instance"] + +mapping: + instance_id: "row.name" + instance_type: "row.properties.instance_type" + subnet_id: "row.properties.subnet_id" + availability_zone: "row.properties.availability_zone" +``` + +### Deployment Configuration +```yaml +columns: + - name: deployment_name + type: string + primaryKey: true + + - name: replicas_config + type: string + description: "Configured replicas" + + - name: image_registry + type: string + description: "Container image registry" + +queries: + deployments: + configs: + types: ["Kubernetes::Deployment"] + +mapping: + deployment_name: "row.name" + replicas_config: "string(row.properties.spec.replicas)" + image_registry: "row.properties.spec.containers[0].image" +``` + +## Best Practices + +1. **Use primaryKey for identifiers** - Make the primary identifier string a primaryKey + ```yaml + - name: id + type: string + primaryKey: true + ``` + +2. **Provide descriptions for clarity** - Help users understand what each string represents + ```yaml + - name: region + type: string + description: "AWS region identifier" + ``` + +3. **Consistent formatting** - Use CEL expressions for consistent formatting + ```yaml + mapping: + created_date: "row.created_at.format('2006-01-02')" + ``` + +4. **Hide internal IDs** - Mark non-user-friendly identifiers as hidden + ```yaml + - name: config_id + type: string + hidden: true + primaryKey: true + ``` + +5. **Use units for clarity** - Add units when values have implicit meaning + ```yaml + - name: version + type: string + unit: "v" + ``` + +## Performance Considerations + +- String columns are very fast - use freely +- String filtering can be slower with large datasets +- Consider limiting results with `limit` in queries +- Use `hidden: true` for primaryKey fields not needed in UI + +## String Length + +By default, strings are not truncated. Long strings will wrap or scroll in the table. Consider: +- Using descriptions instead of long content +- Storing long content in a separate detail view +- Truncating in mapping: `row.name.substring(0, 50)` diff --git a/mission-control/docs/guide/views/table/url.md b/mission-control/docs/guide/views/table/url.md new file mode 100644 index 00000000..fe425f34 --- /dev/null +++ b/mission-control/docs/guide/views/table/url.md @@ -0,0 +1,518 @@ +--- +title: URL +sidebar_custom_props: + icon: mdi:link +--- + +The `url` column type displays clickable links. Links can point to external URLs, other views, or configuration items. URLs can be parameterized with row data for dynamic linking. + +## Basic Usage + +```yaml +columns: + - name: dashboard_link + type: url + url: + href: "https://example.com" +``` + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column name (used in mapping) | +| `type` | string | Set to `"url"` | +| `description` | string | Help text for column | +| `url` | object | URL configuration | +| `for` | string | Column to use as link text | + +## URL Configuration + +```yaml +url: + # External URL + href: "https://example.com/resource" + + # OR internal view link + view: + namespace: "default" + name: "view-name" + filter: + param: "value" + + # OR link to config item + config: "row.id" +``` + +## Example Usage + +### External URL Link + +```yaml +columns: + - name: documentation + type: url + url: + href: "https://docs.example.com" + +mapping: + documentation: "row.name" # Link text +``` + +### Dynamic External URL + +```yaml +columns: + - name: grafana_link + type: url + for: "metric_name" # Use this column as link text + url: + href: "https://grafana.example.com/d/panel?pod=$(row.name)" + +mapping: + metric_name: "row.name" +``` + +### Link to Another View + +```yaml +columns: + - name: details_link + type: url + url: + view: + namespace: "default" + name: "pod-details" + filter: + pod_id: "row.id" + +mapping: + details_link: "row.name" # Link text = pod name +``` + +### Link to Config Item + +```yaml +columns: + - name: config_link + type: url + for: "resource_name" # Show resource name as link text + url: + config: "row.id" # Link to config by ID + +mapping: + resource_name: "row.name" +``` + +## Common Patterns + +### External Service Links +```yaml +columns: + - name: service_url + type: url + for: "service_name" + url: + href: "https://$(row.domain)/service/$(row.service_id)" + +mapping: + service_name: "row.name" +``` + +### Monitoring Dashboard Links +```yaml +columns: + - name: metrics_dashboard + type: url + for: "pod_name" + url: + href: "https://prometheus.example.com/graph?expr=pod_metrics%7Bpod%3D%22$(row.name)%22%7D" + +mapping: + pod_name: "row.name" +``` + +### Log Aggregation Links +```yaml +columns: + - name: logs_link + type: url + for: "pod_name" + url: + href: "https://logs.example.com/search?q=pod:$(row.name)" + +mapping: + pod_name: "row.name" +``` + +### View Navigation +```yaml +columns: + - name: pod_details + type: url + url: + view: + namespace: "default" + name: "pod-details" + filter: + pod_id: "row.id" + cluster: "$(var.cluster)" # Use variables too + +mapping: + pod_details: "row.name" +``` + +## Real-World Examples + +### Kubernetes Pod Dashboard Links +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: logs_link + type: url + for: "pod_name" + description: "View pod logs" + url: + href: "https://logs.example.com/search?pod=$(row.name)&namespace=$(row.namespace)" + + - name: metrics_link + type: url + for: "pod_name" + description: "View metrics" + url: + href: "https://metrics.example.com/dashboard?pod=$(row.name)" + + - name: pod_config + type: url + for: "pod_name" + description: "View config details" + url: + config: "row.id" + +queries: + pods: + configs: + types: ["Kubernetes::Pod"] + +mapping: + pod_name: "row.name" + logs_link: "row.name" + metrics_link: "row.name" + pod_config: "row.name" +``` + +### AWS Resource Links +```yaml +columns: + - name: instance_id + type: string + primaryKey: true + + - name: aws_console_link + type: url + for: "instance_id" + description: "Open in AWS Console" + url: + href: "https://console.aws.amazon.com/ec2/v2/home#Instances:instanceId=$(row.instance_id)" + + - name: cloudwatch_metrics + type: url + for: "instance_id" + description: "CloudWatch Metrics" + url: + href: "https://console.aws.amazon.com/cloudwatch/home#metricsV2:graph=~();query=$(row.instance_id)" + +queries: + instances: + configs: + types: ["AWS::EC2Instance"] + +mapping: + instance_id: "row.name" + aws_console_link: "row.name" + cloudwatch_metrics: "row.name" +``` + +### Application Links +```yaml +columns: + - name: app_name + type: string + primaryKey: true + + - name: production_url + type: url + for: "app_name" + description: "Open production app" + url: + href: "https://$(row.production_domain)/$(row.app_id)" + + - name: staging_url + type: url + for: "app_name" + description: "Open staging app" + url: + href: "https://staging-$(row.production_domain)/$(row.app_id)" + + - name: git_repository + type: url + for: "app_name" + description: "View source code" + url: + href: "$(row.git_repo_url)" + +queries: + apps: + configs: + types: ["Application::Service"] + +mapping: + app_name: "row.name" + production_url: "row.name" + staging_url: "row.name" + git_repository: "row.name" +``` + +### Incident Response Links +```yaml +columns: + - name: incident_id + type: string + primaryKey: true + + - name: related_configs + type: url + for: "incident_id" + description: "View affected resources" + url: + view: + namespace: "default" + name: "incident-resources" + filter: + incident_id: "row.id" + + - name: incident_timeline + type: url + for: "incident_id" + description: "View timeline" + url: + view: + namespace: "default" + name: "incident-timeline" + filter: + incident_id: "row.id" + + - name: external_issue_tracker + type: url + for: "incident_id" + description: "View in Jira" + url: + href: "https://jira.example.com/browse/INC-$(row.id)" + +queries: + incidents: + configs: + types: ["Incident::Report"] + +mapping: + incident_id: "row.id" + related_configs: "row.id" + incident_timeline: "row.id" + external_issue_tracker: "row.id" +``` + +## URL Syntax + +### Static URLs +```yaml +url: + href: "https://example.com/resource" +``` + +### Dynamic URLs with Row Data +```yaml +url: + href: "https://example.com/search?q=$(row.name)&id=$(row.id)" +``` + +### URLs with Variables +```yaml +url: + href: "https://example.com/cluster/$(var.cluster)/pod/$(row.name)" +``` + +### Internal View Links +```yaml +url: + view: + namespace: "default" + name: "view-name" + filter: + param: "value" +``` + +## Link Text + +The link text (what users see and click) comes from: + +1. **`for` property** - Use specified column as text + ```yaml + - name: link_column + type: url + for: "name_column" # Use name_column as link text + url: { ... } + ``` + +2. **Mapping value** - Use mapped value as text + ```yaml + mapping: + link: "row.name" # Show name as link text + ``` + +3. **Default** - Shows the URL itself if not specified + +## Internal View Links + +Link to other views with optional filters: + +```yaml +url: + view: + namespace: "default" # View namespace + name: "pod-details" # View name + filter: # Optional parameters + pod_id: "row.id" + cluster: "us-east-1" +``` + +Users clicking the link navigate to the specified view with filters applied. + +## Configuration Item Links + +Link directly to configuration item detail pages: + +```yaml +url: + config: "row.id" # Links to config detail page +``` + +## Real URL Parameters Example + +```yaml +columns: + - name: pod_name + type: string + primaryKey: true + + - name: logs + type: url + for: "pod_name" + url: + # This creates clickable pod names linking to logs + href: "https://logs.company.com/pods?name=$(row.name)&ns=$(row.namespace)" + +mapping: + pod_name: "row.name" +``` + +When rendered: +- Users see the pod name as a blue link +- Clicking takes them to logs.company.com with pod name and namespace in query params + +## Best Practices + +1. **Use meaningful link text** - Show what the link is about + ```yaml + # ✓ Clear what the link does + for: "pod_name" + + # ✗ Generic link text + for: "link" + ``` + +2. **Add descriptions** - Explain link purpose + ```yaml + - name: logs_link + type: url + description: "View pod logs in Datadog" + ``` + +3. **Use HTTPS** - Always use secure URLs + ```yaml + # ✓ Secure + href: "https://example.com" + + # ✗ Insecure + href: "http://example.com" + ``` + +4. **Parameterize URLs** - Make links dynamic + ```yaml + # ✓ Dynamic for each row + href: "https://example.com?pod=$(row.name)" + + # ✗ Static, same for all rows + href: "https://example.com?pod=my-pod" + ``` + +5. **Test links** - Verify they work before deploying + - Check URL formatting + - Verify query parameters + - Test with sample data + +## Escaping Special Characters + +In URLs, some characters need escaping: + +```yaml +# Space: %20 +href: "https://example.com?q=$(row.name)%20extra" + +# ? +href: "https://example.com?param1=value¶m2=value" + +# # +href: "https://example.com#section" +``` + +## URL Encoding Example + +```yaml +# Properly encoded URL with spaces and special chars +url: + href: "https://logs.example.com/search?query=$(urlEncode(row.name))&time=1h" +``` + +## Performance Considerations + +- URL columns are very efficient +- Link rendering has minimal overhead +- No performance impact on views with many links + +## Comparison with Other Link Types + +| Type | Use Case | +|------|----------| +| `url` | External links or custom URLs | +| `config_item` | Links to configuration detail page | + +Use `url` for external sites (logs, monitoring, etc.). Use `config_item` to link to Mission Control config pages. + +## Security Considerations + +- Always validate URL sources +- Use HTTPS for sensitive data +- Avoid exposing sensitive parameters in URLs +- Consider URL encoding for user-supplied data + +## Open Link Behavior + +By default, links: +- Open in a new browser tab/window +- Preserve the parent view +- Allow back navigation + +This can usually be configured at the platform level. diff --git a/mission-control/package-lock.json b/mission-control/package-lock.json index 10b13fc7..12766962 100644 --- a/mission-control/package-lock.json +++ b/mission-control/package-lock.json @@ -182,6 +182,7 @@ "version": "5.21.0", "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.21.0.tgz", "integrity": "sha512-nZfgJH4njBK98tFCmCW1VX/ExH4bNOl9DSboxeXGgvhoL0fG1+4DDr/mrLe21OggVCQqHwXBMh6fFInvBeyhiQ==", + "peer": true, "dependencies": { "@algolia/client-common": "5.21.0", "@algolia/requester-browser-xhr": "5.21.0", @@ -320,6 +321,7 @@ "version": "7.26.10", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -1974,6 +1976,7 @@ "url": "https://opencollective.com/csstools" } ], + "peer": true, "engines": { "node": ">=18" }, @@ -1995,6 +1998,7 @@ "url": "https://opencollective.com/csstools" } ], + "peer": true, "engines": { "node": ">=18" } @@ -2071,6 +2075,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2392,6 +2397,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3313,6 +3319,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz", "integrity": "sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ==", + "peer": true, "dependencies": { "@docusaurus/core": "3.7.0", "@docusaurus/logger": "3.7.0", @@ -4049,6 +4056,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -4331,6 +4339,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -4803,6 +4812,7 @@ "node_modules/@types/react": { "version": "18.2.48", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -5110,6 +5120,7 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5157,6 +5168,7 @@ "node_modules/ajv": { "version": "6.12.6", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5215,6 +5227,7 @@ "version": "5.21.0", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.21.0.tgz", "integrity": "sha512-hexLq2lSO1K5SW9j21Ubc+q9Ptx7dyRTY7se19U8lhIlVMLCNXWCyQ6C22p9ez8ccX0v7QVmwkl2l1CnuGoO2Q==", + "peer": true, "dependencies": { "@algolia/client-abtesting": "5.21.0", "@algolia/client-analytics": "5.21.0", @@ -5515,6 +5528,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6118,6 +6132,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -6352,9 +6367,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001755", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", - "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==", + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", "funding": [ { "type": "opencollective", @@ -6878,6 +6893,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7178,6 +7194,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -7267,6 +7284,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -15151,6 +15169,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -16450,6 +16469,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", @@ -17413,6 +17433,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -18298,6 +18319,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -18481,6 +18503,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -18543,6 +18566,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -18636,6 +18660,7 @@ "node_modules/react-router": { "version": "5.3.4", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -20707,6 +20732,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -20997,6 +21023,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -22079,6 +22106,7 @@ "version": "5.97.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -22179,6 +22207,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -22305,6 +22334,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -22841,6 +22871,7 @@ "version": "5.21.0", "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.21.0.tgz", "integrity": "sha512-nZfgJH4njBK98tFCmCW1VX/ExH4bNOl9DSboxeXGgvhoL0fG1+4DDr/mrLe21OggVCQqHwXBMh6fFInvBeyhiQ==", + "peer": true, "requires": { "@algolia/client-common": "5.21.0", "@algolia/requester-browser-xhr": "5.21.0", @@ -22943,6 +22974,7 @@ "version": "7.26.10", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "peer": true, "requires": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -23984,12 +24016,14 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.4.tgz", "integrity": "sha512-Up7rBoV77rv29d3uKHUIVubz1BTcgyUK72IvCQAbfbMv584xHcGKCKbWh7i8hPrRJ7qU4Y8IO3IY9m+iTB7P3A==", + "peer": true, "requires": {} }, "@csstools/css-tokenizer": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.3.tgz", - "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==" + "integrity": "sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==", + "peer": true }, "@csstools/media-query-list-parser": { "version": "4.0.2", @@ -24016,6 +24050,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -24146,6 +24181,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -24637,6 +24673,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz", "integrity": "sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ==", + "peer": true, "requires": { "@docusaurus/core": "3.7.0", "@docusaurus/logger": "3.7.0", @@ -25194,6 +25231,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "peer": true, "requires": { "@types/mdx": "^2.0.0" } @@ -25360,6 +25398,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "peer": true, "requires": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -25752,6 +25791,7 @@ }, "@types/react": { "version": "18.2.48", + "peer": true, "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -26044,7 +26084,8 @@ "acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "peer": true }, "acorn-jsx": { "version": "5.3.2", @@ -26072,6 +26113,7 @@ }, "ajv": { "version": "6.12.6", + "peer": true, "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -26113,6 +26155,7 @@ "version": "5.21.0", "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.21.0.tgz", "integrity": "sha512-hexLq2lSO1K5SW9j21Ubc+q9Ptx7dyRTY7se19U8lhIlVMLCNXWCyQ6C22p9ez8ccX0v7QVmwkl2l1CnuGoO2Q==", + "peer": true, "requires": { "@algolia/client-abtesting": "5.21.0", "@algolia/client-analytics": "5.21.0", @@ -26293,6 +26336,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -26730,6 +26774,7 @@ "version": "4.24.4", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "peer": true, "requires": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -26881,9 +26926,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001755", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001755.tgz", - "integrity": "sha512-44V+Jm6ctPj7R52Na4TLi3Zri4dWUljJd+RDm+j8LtNCc/ihLCT+X1TzoOAkRETEWqjuLnh9581Tl80FvK7jVA==" + "version": "1.0.30001756", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", + "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==" }, "caw": { "version": "2.0.1", @@ -27220,6 +27265,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -27391,6 +27437,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -27430,6 +27477,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -32393,6 +32441,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -33215,6 +33264,7 @@ "version": "8.4.49", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "peer": true, "requires": { "nanoid": "^3.3.7", "picocolors": "^1.1.1", @@ -33694,6 +33744,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -34248,6 +34299,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -34373,6 +34425,7 @@ "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" @@ -34419,6 +34472,7 @@ "version": "npm:@docusaurus/react-loadable@6.0.0", "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "peer": true, "requires": { "@types/react": "*" } @@ -34482,6 +34536,7 @@ }, "react-router": { "version": "5.3.4", + "peer": true, "requires": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -35927,6 +35982,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "dev": true, + "peer": true, "requires": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -36152,6 +36208,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.3.tgz", "integrity": "sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==", + "peer": true, "requires": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -36887,6 +36944,7 @@ "version": "5.97.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "peer": true, "requires": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -36971,6 +37029,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -37058,6 +37117,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "peer": true, "requires": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", From 376823952dbd3bb55955b4a974c14885b02ec382 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Tue, 25 Nov 2025 13:26:58 +0545 Subject: [PATCH 2/8] Add panel documentation for Views --- .../docs/guide/views/panels/bargauge.md | 41 +++++++++++++++++++ .../docs/guide/views/panels/duration.md | 20 +++++++++ .../docs/guide/views/panels/gauge.md | 38 +++++++++++++++++ .../docs/guide/views/panels/index.mdx | 37 +++++++++++++++++ .../docs/guide/views/panels/number.md | 33 +++++++++++++++ .../docs/guide/views/panels/piechart.md | 31 ++++++++++++++ .../docs/guide/views/panels/table.md | 20 +++++++++ 7 files changed, 220 insertions(+) create mode 100644 mission-control/docs/guide/views/panels/bargauge.md create mode 100644 mission-control/docs/guide/views/panels/duration.md create mode 100644 mission-control/docs/guide/views/panels/gauge.md create mode 100644 mission-control/docs/guide/views/panels/index.mdx create mode 100644 mission-control/docs/guide/views/panels/number.md create mode 100644 mission-control/docs/guide/views/panels/piechart.md create mode 100644 mission-control/docs/guide/views/panels/table.md diff --git a/mission-control/docs/guide/views/panels/bargauge.md b/mission-control/docs/guide/views/panels/bargauge.md new file mode 100644 index 00000000..3bf475eb --- /dev/null +++ b/mission-control/docs/guide/views/panels/bargauge.md @@ -0,0 +1,41 @@ +--- +title: Bar Gauge +sidebar_custom_props: + icon: mdi:chart-bar +--- + +The `bargauge` panel displays multiple values as horizontal bars with configurable thresholds. Useful for comparing related metrics like CPU real usage vs requests vs limits. + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `min` | string | Minimum value (can be a number or CEL expression) | +| `max` | string | Maximum value (can be a number or CEL expression) | +| `precision` | int | Decimal places to display | +| `unit` | string | Unit label (e.g., "%", "bytes") | +| `group` | string | Field to group bars by | +| `format` | string | Display format: `percentage` or `multiplier` | +| `thresholds` | array | Color thresholds based on percentage | + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` | number | The numeric value for each bar (required) | +| `name` | string | Label for each bar (required, or any other column will be used as label) | + +## Thresholds + +Thresholds define colors at percentage breakpoints: + +| Property | Type | Description | +|----------|------|-------------| +| `percent` | int | Percentage at which this threshold applies | +| `color` | string | Color name or hex code (e.g., "#10b981") | + +## Example + +```yaml title="bargauge.yaml" file=/modules/mission-control/fixtures/views/panels/bargauge.yaml + +``` diff --git a/mission-control/docs/guide/views/panels/duration.md b/mission-control/docs/guide/views/panels/duration.md new file mode 100644 index 00000000..03180ff0 --- /dev/null +++ b/mission-control/docs/guide/views/panels/duration.md @@ -0,0 +1,20 @@ +--- +title: Duration +sidebar_custom_props: + icon: mdi:timer-outline +--- + +The `duration` panel displays time duration values in a human-readable format (e.g., "2h 30m"). It has no additional configuration properties. + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` | number | Duration in **nanoseconds** (required) | +| `label` | string | Label for the panel (optional, defaults to panel name) | + +## Example + +```yaml title="pipelines.yaml" file=/modules/mission-control/fixtures/views/pipelines.yaml + +``` diff --git a/mission-control/docs/guide/views/panels/gauge.md b/mission-control/docs/guide/views/panels/gauge.md new file mode 100644 index 00000000..e00b9964 --- /dev/null +++ b/mission-control/docs/guide/views/panels/gauge.md @@ -0,0 +1,38 @@ +--- +title: Gauge +sidebar_custom_props: + icon: mdi:gauge +--- + +The `gauge` panel displays a single numeric value as a visual gauge with configurable min/max bounds and color thresholds. + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `min` | string | Minimum value (can be a number or CEL expression) | +| `max` | string | Maximum value (can be a number or CEL expression) | +| `precision` | int | Decimal places to display | +| `unit` | string | Unit label (e.g., "%", "pods") | +| `thresholds` | array | Color thresholds based on percentage | + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` | number | The numeric value to display on the gauge (required) | + +## Thresholds + +Thresholds define colors at percentage breakpoints (0-100%): + +| Property | Type | Description | +|----------|------|-------------| +| `percent` | int | Percentage at which this threshold applies | +| `color` | string | Color name or hex code (e.g., "green", "#10b981") | + +## Example + +```yaml title="gauge.yaml" file=/modules/mission-control/fixtures/views/panels/gauge.yaml + +``` diff --git a/mission-control/docs/guide/views/panels/index.mdx b/mission-control/docs/guide/views/panels/index.mdx new file mode 100644 index 00000000..977075ee --- /dev/null +++ b/mission-control/docs/guide/views/panels/index.mdx @@ -0,0 +1,37 @@ +--- +sidebar_position: 4 +title: Panels +sidebar_custom_props: + icon: mdi:chart-box +--- + +Panels display aggregated data visualizations above the main table. Each panel runs a SQL query against the view's query results and renders the data as a chart, gauge, or summary. + +## Panel Definition + +Panels are defined in `spec.panels`: + +```yaml +panels: + - name: Pod Count # Panel name + description: Total pods # Optional description + type: gauge # Panel type + query: SELECT COUNT(*) AS value FROM pods +``` + +## Common Properties + +All panel types support these properties: + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Panel name (required) | +| `description` | string | Optional description | +| `type` | string | Panel type (required) | +| `query` | string | SQL query against view data (required) | + +## Panel Types + +import DocCardList from '@theme/DocCardList'; + + diff --git a/mission-control/docs/guide/views/panels/number.md b/mission-control/docs/guide/views/panels/number.md new file mode 100644 index 00000000..f9bceedb --- /dev/null +++ b/mission-control/docs/guide/views/panels/number.md @@ -0,0 +1,33 @@ +--- +title: Number +sidebar_custom_props: + icon: mdi:numeric +--- + +The `number` panel displays a single numeric value with optional unit formatting. + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `unit` | string | Unit label (e.g., "bytes", "seconds", "pods") | +| `precision` | int | Decimal places to display | + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` or `count` | number | The numeric value to display (required) | +| `label` | string | Label for the panel (optional, defaults to panel name) | + +## Example + +```yaml title="number.yaml" file=/modules/mission-control/fixtures/views/panels/number.yaml + +``` + +## With Unit and Precision + +```yaml title="resource-usage.yaml" file=/modules/mission-control/fixtures/views/panels/resource-usage.yaml + +``` diff --git a/mission-control/docs/guide/views/panels/piechart.md b/mission-control/docs/guide/views/panels/piechart.md new file mode 100644 index 00000000..0706aa12 --- /dev/null +++ b/mission-control/docs/guide/views/panels/piechart.md @@ -0,0 +1,31 @@ +--- +title: Piechart +sidebar_custom_props: + icon: mdi:chart-pie +--- + +The `piechart` panel displays data distribution as a pie chart with customizable colors and labels. + +## Properties + +| Property | Type | Description | +|----------|------|-------------| +| `showLabels` | bool | Whether to display value labels on pie slices | +| `colors` | map | Custom color mapping by label name | + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `count` | number | The size of each pie slice (required) | +| Any other column | string | Used as the label for each slice (e.g., `health`, `status`) | + +## Colors + +The `colors` property maps label values to hex color codes. If not specified, colors are automatically assigned based on semantic meaning (e.g., "healthy" gets green, "error" gets red). + +## Example + +```yaml title="piechart.yaml" file=/modules/mission-control/fixtures/views/panels/piechart.yaml + +``` diff --git a/mission-control/docs/guide/views/panels/table.md b/mission-control/docs/guide/views/panels/table.md new file mode 100644 index 00000000..b0ee1bd1 --- /dev/null +++ b/mission-control/docs/guide/views/panels/table.md @@ -0,0 +1,20 @@ +--- +title: Table +sidebar_custom_props: + icon: mdi:table +--- + +The `table` panel displays query results as a simple key-value list. It has no additional configuration. + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` | any | The value displayed on the right side (required) | +| Any other column | string | Used as the label on the left side | + +## Example + +```yaml title="table.yaml" file=/modules/mission-control/fixtures/views/panels/table.yaml + +``` From c5602e4d8b51c4a8bbaead0b536ee991fc724bb4 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Tue, 25 Nov 2025 13:28:39 +0545 Subject: [PATCH 3/8] highlight lines --- .../docs/guide/views/queries/changes.md | 551 +-------------- .../docs/guide/views/queries/configs.md | 492 +------------- .../docs/guide/views/queries/prometheus.md | 639 +----------------- .../docs/guide/views/table/badge.md | 540 +-------------- .../docs/guide/views/table/boolean.md | 363 +--------- .../docs/guide/views/table/bytes.md | 473 +------------ .../docs/guide/views/table/config-item.md | 601 +--------------- .../docs/guide/views/table/datetime.md | 401 +---------- .../docs/guide/views/table/decimal.md | 504 +------------- .../docs/guide/views/table/duration.md | 415 +----------- .../docs/guide/views/table/gauge.md | 561 +-------------- .../docs/guide/views/table/health.md | 403 +---------- .../docs/guide/views/table/index.mdx | 51 +- .../docs/guide/views/table/millicore.md | 409 +---------- .../docs/guide/views/table/number.md | 318 +-------- .../docs/guide/views/table/status.md | 417 +----------- .../docs/guide/views/table/string.md | 307 +-------- mission-control/docs/guide/views/table/url.md | 503 +------------- 18 files changed, 165 insertions(+), 7783 deletions(-) diff --git a/mission-control/docs/guide/views/queries/changes.md b/mission-control/docs/guide/views/queries/changes.md index a5e5e1e8..4110657d 100644 --- a/mission-control/docs/guide/views/queries/changes.md +++ b/mission-control/docs/guide/views/queries/changes.md @@ -4,548 +4,47 @@ sidebar_custom_props: icon: diff --- -Change queries retrieve the audit trail of modifications to configuration items. They allow you to display what changed, when, how, and which resources were affected. - -## Overview - -Changes represent modifications to configuration items tracked in your catalog. They include version updates, property changes, deletions, and other modifications. Change queries let you build audit dashboards, change timelines, and impact analysis views. - -**Example**: -```yaml -queries: - recent_changes: - changes: - types: ["Kubernetes::Pod", "Kubernetes::Deployment"] - search: "update" - limit: 50 -``` +Change queries retrieve the audit trail of modifications to configuration items. ## Query Properties -### Basic Properties - -| Property | Type | Description | -|----------|------|-------------| -| `types` | array | Config item types to get changes for | -| `search` | string | Free text search across change summaries | -| `tagSelector` | string | Filter by tags of the affected config items | -| `status` | string | Filter by change status | -| `severity` | string | Filter by change severity (`info`, `warning`, `critical`) | -| `agent` | string | Filter by specific agent that captured the change | -| `limit` | integer | Maximum number of changes to return | - -## Query Examples - -### Recent Changes for a Resource Type +| Property | Type | Description | +| ------------- | ------- | ----------------------------------------------------------------- | +| `types` | array | Config types to get changes for | +| `search` | string | Free text search (supports `change_type=` and `@order=` prefixes) | +| `tagSelector` | string | Filter by tags of the affected config items | +| `severity` | string | Filter by severity (`info`, `warning`, `critical`) | +| `agent` | string | Filter by specific agent | +| `limit` | integer | Maximum changes to return | -```yaml -queries: - pod_changes: - changes: - types: ["Kubernetes::Pod"] - limit: 100 -``` +## Example -Return the 100 most recent changes to pods. +```yaml title="pipelines.yaml" file=/modules/mission-control/fixtures/views/pipelines.yaml {57-63} -### Search for Specific Changes - -```yaml -queries: - deployment_updates: - changes: - types: ["Kubernetes::Deployment"] - search: "update" - limit: 50 ``` -Return changes containing "update" in the summary. - -### Critical Changes Only - -```yaml -queries: - critical_changes: - changes: - types: ["Kubernetes::Pod", "Kubernetes::Node"] - severity: "critical" - limit: 200 -``` - -Return critical changes to pods and nodes. - -### Changes to Production Resources - -```yaml -queries: - prod_changes: - changes: - types: ["Kubernetes::Pod"] - tagSelector: "environment=production" - limit: 100 -``` - -Return changes to production resources only. - -### Combine Multiple Filters - -```yaml -queries: - analysis: - changes: - types: - - "Kubernetes::Deployment" - - "Kubernetes::StatefulSet" - - "Kubernetes::DaemonSet" - tagSelector: "environment=production,team=platform" - severity: "warning" - search: "config" - agent: "cluster-1" - limit: 100 -``` - -Return warning-level configuration changes to production deployments managed by platform team. - ## Auto-Mapped Columns -Change queries automatically provide these columns: +Change queries provide these columns: -### Core Change Information -- `id` - Unique change identifier -- `config_id` - ID of the changed configuration item -- `config_name` - Name of the changed resource -- `config_type` - Type of the changed resource +- `id` - Change identifier +- `config_id`, `config_name`, `config_type` - Affected resource - `change_type` - Type of change (e.g., `Created`, `Updated`, `Deleted`) -- `severity` - Change severity (`info`, `warning`, `critical`) -- `summary` - Human-readable summary of the change -- `description` - Detailed change description - -### Before/After Content -- `old_config` - Configuration before the change -- `new_config` - Configuration after the change -- `diff` - Computed diff showing what changed -- `patch` - Patch format showing the differences - -### Timestamps +- `severity` - Change severity +- `summary` - Human-readable summary +- `details` - Full change details (JSON) - `created_at` - When the change was detected -- `first_seen_at` - First time this change was observed -- `last_seen_at` - Last time this change was observed - -### Related Information -- `tags` - Tags of the affected resource -- `labels` - Labels of the affected resource +- `tags`, `labels` - Tags/labels of the affected resource -## Using Variables in Change Queries - -Make change queries dynamic with templating variables: - -```yaml -templating: - - key: resource_type - label: "Resource Type" - values: ["Kubernetes::Pod", "Kubernetes::Deployment"] - default: "Kubernetes::Pod" - - - key: severity_level - label: "Min Severity" - values: ["info", "warning", "critical"] - -queries: - changes: - changes: - types: ["$(var.resource_type)"] - severity: "$(var.severity_level)" -``` - -## Column Mapping Examples - -### Simple Change Timeline - -```yaml -columns: - - name: resource - type: string - primaryKey: true - - name: change_type - type: string - - name: severity - type: status - - name: changed_at - type: datetime - -queries: - changes: - changes: - types: ["Kubernetes::Pod", "Kubernetes::Deployment"] - limit: 100 - -mapping: - resource: "row.config_name" - change_type: "row.change_type" - severity: "row.severity" - changed_at: "row.created_at" -``` - -### Detailed Change View with Summary - -```yaml -columns: - - name: id - type: string - primaryKey: true - hidden: true - - name: resource - type: string - - name: type - type: string - - name: summary - type: text - - name: severity - type: health - - name: timestamp - type: datetime - -queries: - changes: - changes: - types: ["Kubernetes::*"] - limit: 200 - -mapping: - id: "row.id" - resource: "row.config_name" - type: "row.change_type" - summary: "row.summary" - severity: "row.severity == 'critical' ? 'critical' : row.severity == 'warning' ? 'warning' : 'healthy'" - timestamp: "row.created_at" -``` - -### Change Impact Analysis +## Search Syntax ```yaml -columns: - - name: resource_id - type: string - primaryKey: true - hidden: true - - name: resource_name - type: string - - name: resource_type - type: string - - name: changes_count - type: number - - name: latest_change - type: datetime - -queries: - changes: - changes: - types: ["Kubernetes::Pod"] - limit: 1000 - -merge: | - SELECT - config_id as resource_id, - config_name as resource_name, - config_type as resource_type, - COUNT(*) as changes_count, - MAX(created_at) as latest_change - FROM changes - GROUP BY config_id, config_name, config_type - -mapping: - resource_id: "row.resource_id" - resource_name: "row.resource_name" - resource_type: "row.resource_type" - changes_count: "row.changes_count" - latest_change: "row.latest_change" -``` - -## Real-World Examples - -### Deployment Change Timeline - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: deployment-changes -spec: - display: - title: "Deployment Changes" - sidebar: true - - templating: - - key: environment - label: "Environment" - values: ["dev", "staging", "prod"] - default: "prod" - - columns: - - name: deployment - type: string - primaryKey: true - - name: change_type - type: string - - name: summary - type: text - - name: severity - type: health - - name: timestamp - type: datetime +# Filter by change type +search: change_type=BackupSuccessful - queries: - changes: - changes: - types: ["Kubernetes::Deployment"] - tagSelector: "environment=$(var.environment)" - limit: 100 +# Ordering +search: "@order=-created_at" - mapping: - deployment: "row.config_name" - change_type: "row.change_type" - summary: "row.summary" - severity: "row.severity == 'critical' ? 'critical' : row.severity == 'warning' ? 'warning' : 'healthy'" - timestamp: "row.created_at" -``` - -### Production Incident Investigation - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: incident-changes -spec: - display: - title: "Incident Investigation Timeline" - - columns: - - name: timestamp - type: datetime - primaryKey: true - - name: resource - type: string - - name: resource_type - type: string - - name: change - type: text - - name: severity - type: health - - queries: - changes: - changes: - types: - - "Kubernetes::Pod" - - "Kubernetes::Node" - - "Kubernetes::Deployment" - tagSelector: "environment=production" - severity: "critical" - limit: 500 - - mapping: - timestamp: "row.created_at" - resource: "row.config_name" - resource_type: "row.config_type" - change: "row.summary" - severity: "row.severity == 'critical' ? 'critical' : 'warning'" -``` - -### Change Summary Dashboard with Panels - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: change-summary -spec: - display: - title: "Change Summary" - card: - columns: 2 - - columns: - - name: change_id - type: string - primaryKey: true - hidden: true - - queries: - changes: - changes: - types: ["Kubernetes::Pod", "Kubernetes::Deployment"] - limit: 1000 - - panels: - - name: "Total Changes (24h)" - type: number - query: | - SELECT COUNT(*) as value FROM changes - WHERE created_at > datetime('now', '-1 day') - - - name: "Changes by Severity" - type: piechart - query: | - SELECT severity, COUNT(*) as value FROM changes - WHERE created_at > datetime('now', '-1 day') - GROUP BY severity - - - name: "Critical Changes by Type" - type: bargauge - query: | - SELECT config_type, COUNT(*) as value FROM changes - WHERE severity = 'critical' - AND created_at > datetime('now', '-7 days') - GROUP BY config_type - - - name: "Most Changed Resources" - type: table - query: | - SELECT - config_name as resource, - COUNT(*) as change_count - FROM changes - WHERE created_at > datetime('now', '-7 days') - GROUP BY config_name - ORDER BY change_count DESC - LIMIT 10 -``` - -### Change Frequency Analysis - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: change-frequency -spec: - display: - title: "Change Frequency by Resource" - - templating: - - key: days_back - label: "Time Period" - values: ["1", "7", "30"] - default: "7" - - columns: - - name: resource_name - type: string - primaryKey: true - - name: resource_type - type: string - - name: total_changes - type: number - - name: last_changed - type: datetime - - queries: - changes: - changes: - types: ["Kubernetes::Pod", "Kubernetes::Deployment", "Kubernetes::StatefulSet"] - limit: 1000 - - merge: | - SELECT - config_name as resource_name, - config_type as resource_type, - COUNT(*) as total_changes, - MAX(created_at) as last_changed - FROM changes - WHERE created_at > datetime('now', '-$(var.days_back) days') - GROUP BY config_id, config_name, config_type - ORDER BY total_changes DESC - - mapping: - resource_name: "row.resource_name" - resource_type: "row.resource_type" - total_changes: "row.total_changes" - last_changed: "row.last_changed" -``` - -## Diff and Patch Analysis - -When mapping change configurations, you can access the diff and patch: - -```yaml -mapping: - # Show human-readable diff - changes_made: "row.diff" - - # Show patch format - patch_content: "row.patch" - - # Access old/new configs - old_value: "row.old_config" - new_value: "row.new_config" -``` - -## Performance Considerations - -### Use Limits -Always limit the number of changes to avoid loading entire history: - -```yaml -queries: - changes: - changes: - types: ["Kubernetes::Pod"] - limit: 100 # Don't load all changes -``` - -### Filter by Severity -When possible, filter to relevant changes: - -```yaml -# ✓ Specific - gets fewer results -changes: - types: ["Kubernetes::Pod"] - severity: "critical" - -# ✗ Broad - gets all changes -changes: - types: ["Kubernetes::Pod"] -``` - -### Use Time Windows in Merge -When aggregating changes, limit the time window: - -```yaml -merge: | - SELECT config_name, COUNT(*) as change_count - FROM changes - WHERE created_at > datetime('now', '-7 days') # Last 7 days only - GROUP BY config_name -``` - -## Common Use Cases - -### Audit Trail -Track all changes to critical resources for compliance: -```yaml -types: ["Kubernetes::Pod", "Kubernetes::Deployment"] -tagSelector: "environment=production" -``` - -### Incident Timeline -Find what changed around an incident time: -```yaml -types: ["Kubernetes::*"] -severity: "critical" -``` - -### Change Approval Workflows -Monitor changes that need approval: -```yaml -search: "requires-approval" -severity: "warning" -``` - -### SLA Tracking -Monitor change frequency against SLAs: -```yaml -# Count changes per resource -# Group by resource -# Compare against SLA targets +# Combine +search: "change_type=GitHubActionRun* @order=-created_at" ``` diff --git a/mission-control/docs/guide/views/queries/configs.md b/mission-control/docs/guide/views/queries/configs.md index 88d5f413..36f0e640 100644 --- a/mission-control/docs/guide/views/queries/configs.md +++ b/mission-control/docs/guide/views/queries/configs.md @@ -4,495 +4,35 @@ sidebar_custom_props: icon: config --- -Config queries fetch configuration items (resources) from the Flanksource catalog. They allow you to display and analyze any type of infrastructure or application resource tracked in your catalog. - -## Overview - -Config queries retrieve resources from your catalog based on filters. The query results include all standard config item properties plus custom properties and tags you've defined. - -**Example**: -```yaml -queries: - myquery: - configs: - types: ["Kubernetes::Pod", "Kubernetes::Node"] - tagSelector: "environment=production" -``` +Config queries fetch configuration items from the Flanksource catalog. ## Query Properties -### Basic Properties - | Property | Type | Description | |----------|------|-------------| | `types` | array | Config types to query (e.g., `["Kubernetes::Pod"]`) | -| `search` | string | Free text search across config name and properties | -| `status` | string | Filter by status (`healthy`, `warning`, `critical`, `unhealthy`) | +| `search` | string | Free text search (supports `@order=` for sorting) | +| `status` | string | Filter by status | | `health` | string | Filter by health status | -| `tagSelector` | string | Filter by tags using selector syntax | +| `tagSelector` | string | Filter by tags (e.g., `environment=prod,team=platform`) | | `labelSelector` | string | Filter by Kubernetes-style labels | -| `agent` | string | Filter by specific agent ID | -| `scope` | string | Filter by scraper/scope ID | -| `fieldSelector` | string | Advanced field-based filtering | -| `limit` | integer | Maximum number of results to return | - -## Query Examples - -### Query by Type +| `agent` | string | Filter by agent ID (use `all` for all agents) | +| `limit` | integer | Maximum results to return | -```yaml -queries: - pods: - configs: - types: ["Kubernetes::Pod"] -``` - -Return all Kubernetes pods from the catalog. +## Example -### Query Multiple Types +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {32-37} -```yaml -queries: - resources: - configs: - types: - - "Kubernetes::Pod" - - "Kubernetes::Deployment" - - "Kubernetes::StatefulSet" ``` -Return pods, deployments, and stateful sets. - -### Filter by Tags - -```yaml -queries: - prod_pods: - configs: - types: ["Kubernetes::Pod"] - tagSelector: "environment=prod,team=platform" -``` - -Return production pods owned by the platform team. Multiple tags use AND logic. - -### Filter by Status - -```yaml -queries: - unhealthy: - configs: - types: ["Kubernetes::Pod"] - status: "critical" - limit: 100 -``` - -Return up to 100 pods with critical status. - -### Free Text Search - -```yaml -queries: - search_results: - configs: - types: ["Kubernetes::Pod"] - search: "postgres" -``` - -Return all pods with "postgres" in name or properties. - -### Combine Multiple Filters - -```yaml -queries: - complex_query: - configs: - types: ["Kubernetes::Deployment"] - tagSelector: "environment=production,region=us-east-1" - status: "warning" - search: "database" - agent: "cluster-1" - limit: 50 -``` - -Return the first 50 production deployments in us-east-1 with "database" in name and warning status. - ## Auto-Mapped Columns -Config queries automatically provide these columns for use in table views: - -### Core Properties -- `id` - Unique config identifier -- `name` - Resource name -- `type` - Config type (e.g., `Kubernetes::Pod`) -- `namespace` - Kubernetes namespace (if applicable) -- `agent` - Agent that scraped the config -- `source` - Configuration source - -### Status & Health -- `status` - Current status (healthy/warning/critical/unhealthy) -- `health` - Health status -- `health_color` - Color code for health status - -### Timestamps -- `created_at` - When config was first discovered -- `updated_at` - Last time config was updated -- `deleted_at` - When config was deleted (if deleted) - -### Properties & Content -- `config` - Raw configuration content (often JSON/YAML) -- `properties` - Custom properties as JSON -- `tags` - Applied tags as JSON -- `labels` - Kubernetes-style labels as JSON - -### Cost Data -- `cost` - Current cost -- `cost_total_1d` - Cost over last day -- `cost_total_7d` - Cost over last 7 days -- `cost_total_30d` - Cost over last 30 days - -### Relationships -- `parent_id` - ID of parent config item -- `parent_name` - Name of parent config item -- `parent_type` - Type of parent config item - -### Computed Fields -- `summary` - Auto-generated summary of the config - -## Using Variables in Config Queries - -You can use templating variables to make queries dynamic: - -```yaml -templating: - - key: environment - label: "Environment" - values: ["dev", "staging", "prod"] - - - key: search_term - label: "Search" - values: ["", "database", "cache", "web"] - -queries: - resources: - configs: - types: ["Kubernetes::Pod"] - tagSelector: "environment=$(var.environment)" - search: "$(var.search_term)" -``` - -See [Templating & Variables](../concepts/templating.md) for more details. - -## Column Mapping Examples - -### Simple Table with Basic Columns - -```yaml -columns: - - name: name - type: string - primaryKey: true - - name: status - type: status - - name: health - type: health - -queries: - resources: - configs: - types: ["Kubernetes::Pod"] - -mapping: - name: "row.name" - status: "row.status" - health: "row.health" -``` - -### Display Cost Information - -```yaml -columns: - - name: name - type: string - primaryKey: true - - name: cost_30d - type: decimal - - name: health - type: health - -queries: - resources: - configs: - types: ["AWS::EC2Instance"] - -mapping: - name: "row.name" - cost_30d: "row.cost_total_30d" - health: "row.health" -``` - -### Show Custom Properties - -```yaml -columns: - - name: name - type: string - primaryKey: true - - name: version - type: string - - name: replicas - type: number - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - name: "row.name" - version: "row.properties.version" - replicas: "row.properties.replicas" -``` - -### Create Links to Related Resources - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - name: node_name - type: url - url: - config: "row.parent_id" - - name: health - type: health - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - node_name: "row.parent_name" - health: "row.health" -``` - -## Real-World Examples - -### Production Pod Dashboard - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: prod-pods -spec: - display: - title: "Production Pods" - sidebar: true - - templating: - - key: namespace - label: "Namespace" - valueFrom: - config: - types: ["Kubernetes::Namespace"] - tagSelector: "environment=production" - default: "default" - - columns: - - name: pod_name - type: string - primaryKey: true - - name: status - type: status - - name: health - type: health - - name: age - type: duration - - queries: - pods: - configs: - types: ["Kubernetes::Pod"] - tagSelector: "environment=production,namespace=$(var.namespace)" - - mapping: - pod_name: "row.name" - status: "row.status" - health: "row.health" - age: "now - row.created_at" -``` - -### AWS EC2 Inventory with Cost Tracking - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: aws-inventory -spec: - display: - title: "AWS EC2 Instances" - - templating: - - key: region - label: "Region" - values: ["us-east-1", "us-west-2", "eu-central-1"] - default: "us-east-1" - - columns: - - name: instance_id - type: string - primaryKey: true - - name: instance_type - type: string - - name: status - type: status - - name: monthly_cost - type: decimal - unit: "$" - - queries: - instances: - configs: - types: ["AWS::EC2Instance"] - tagSelector: "region=$(var.region)" - - mapping: - instance_id: "row.name" - instance_type: "row.properties.instance_type" - status: "row.status" - monthly_cost: "row.cost_total_30d" -``` - -### Multi-Cluster Resource View - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: multi-cluster-resources -spec: - display: - title: "Resources Across Clusters" - - templating: - - key: cluster - label: "Cluster" - valueFrom: - config: - types: ["Kubernetes::Cluster"] - default: "production" - - - key: resource_type - label: "Resource Type" - values: ["Pod", "Deployment", "StatefulSet", "DaemonSet"] - default: "Pod" - - columns: - - name: resource_name - type: string - primaryKey: true - - name: resource_type - type: string - - name: namespace - type: string - - name: status - type: status - - name: health - type: health - - queries: - resources: - configs: - types: - - "Kubernetes::Pod" - - "Kubernetes::Deployment" - - "Kubernetes::StatefulSet" - - "Kubernetes::DaemonSet" - tagSelector: "cluster=$(var.cluster)" - - mapping: - resource_name: "row.name" - resource_type: "row.type" - namespace: "row.namespace" - status: "row.status" - health: "row.health" -``` - -## Performance Considerations - -### Limit Results -Always use `limit` to avoid fetching huge result sets: - -```yaml -queries: - resources: - configs: - types: ["Kubernetes::Pod"] - limit: 100 # Don't fetch all pods -``` - -### Use Specific Types -Query specific resource types rather than all types: - -```yaml -# ✓ Specific - only gets pods -configs: - types: ["Kubernetes::Pod"] - -# ✗ Broad - might get everything -configs: - types: ["Kubernetes::*"] -``` - -### Filter Early -Apply restrictive filters to reduce data: - -```yaml -# ✓ Filters reduce results -configs: - types: ["Kubernetes::Pod"] - tagSelector: "environment=prod,team=platform" - status: "critical" - -# ✗ Broad - gets everything -configs: - types: ["Kubernetes::Pod"] -``` - -### Combine with Cache Control -Use [cache control](../concepts/cache-control.md) to avoid repeated expensive queries: - -```yaml -cache: - maxAge: 30m # Don't refresh too frequently -``` - -## Troubleshooting - -### No Results Returned - -Check: -1. Is the config type correct? (`Kubernetes::Pod` not `Pod`) -2. Are your filters too restrictive? Try removing tagSelector -3. Does your agent/scope exist and have permissions? -4. Are there any configs of this type in your catalog? - -### Unexpected Results - -Check: -1. Does tagSelector have correct key=value format? -2. Are multiple tags properly comma-separated? -3. Are variable substitutions working? (Try hardcoding a value) -4. Check the health/status filters aren't too restrictive - -### Performance Issues +Config queries provide these columns: -Check: -1. Is `limit` set? (Defaults to returning all matches) -2. Are you querying multiple expensive types? -3. Try adding more restrictive filters -4. Consider increasing `maxAge` in cache control +- `id`, `name`, `type`, `namespace` - Core identifiers +- `status`, `health` - Current state +- `created_at`, `updated_at` - Timestamps +- `config` - Raw configuration (JSON) +- `properties`, `tags`, `labels` - Metadata +- `cost_total_1d`, `cost_total_7d`, `cost_total_30d` - Cost data +- `parent_id`, `parent_name`, `parent_type` - Relationships diff --git a/mission-control/docs/guide/views/queries/prometheus.md b/mission-control/docs/guide/views/queries/prometheus.md index 47789524..fe02b972 100644 --- a/mission-control/docs/guide/views/queries/prometheus.md +++ b/mission-control/docs/guide/views/queries/prometheus.md @@ -4,647 +4,42 @@ sidebar_custom_props: icon: prometheus --- -Prometheus queries fetch metrics directly from Prometheus using PromQL. They allow you to display real-time and historical metrics in your views. - -## Overview - -Prometheus queries execute PromQL expressions against your Prometheus instance and return time series data. Results can be visualized as tables, gauges, charts, and other panel types. - -**Example**: -```yaml -queries: - metrics: - prometheus: - connection: prometheus-prod - query: 'up{job="kubernetes-nodes"}' -``` +Prometheus queries fetch metrics directly from Prometheus using PromQL. ## Query Properties | Property | Type | Description | |----------|------|-------------| -| `connection` | string | Name of the Prometheus connection to use | +| `connection` | string | Prometheus connection reference (e.g., `connection://mc/prometheus`) | | `query` | string | PromQL query expression | -| `columns` | object | Optional: define column types for the results | - -## Connection Configuration - -Before using Prometheus queries, ensure you have a Prometheus connection configured in your Mission Control instance. Connections are typically defined at the system level. - -Reference a connection by its name: - -```yaml -prometheus: - connection: prometheus-prod - query: 'up{job="kubernetes"}' -``` - -## PromQL Queries - -Prometheus queries use standard PromQL syntax. The query results return: -- **Labels** from the metric as columns -- **Value** as a numeric column - -### Instant Queries - -Return the current value of metrics: - -```yaml -queries: - node_up: - prometheus: - connection: prod - query: 'up{job="kubernetes-nodes"}' -``` - -Returns: One row per node with `up` value and labels like `node`, `job`, `instance`. - -### Range Queries - -Return values over a time range (in panels/merge): - -```yaml -queries: - cpu_usage: - prometheus: - connection: prod - query: 'rate(node_cpu_seconds_total[5m])' -``` - -### Aggregation Queries - -Aggregate metrics across dimensions: - -```yaml -queries: - namespace_memory: - prometheus: - connection: prod - query: | - sum(container_memory_usage_bytes) by (namespace) -``` - -## Column Type Definitions - -For Prometheus queries, you can optionally define column types. This is useful when: -- You want to control how metrics are displayed -- The metric has no results yet (type inference would fail) -- You want to ensure specific formatting - -```yaml -queries: - metrics: - prometheus: - connection: prod - query: 'container_memory_usage_bytes{namespace="default"}' - columns: - pod: string - container: string - value: bytes -``` - -If you don't specify columns, types are inferred from the query results. - -## Query Examples +| `columns` | object | Define column types for results (recommended) | -### CPU Usage by Node +## Example -```yaml -queries: - cpu_usage: - prometheus: - connection: prod - query: | - rate(node_cpu_seconds_total{mode="system"}[5m]) * 100 - columns: - node: string - value: decimal -``` - -### Memory Availability - -```yaml -queries: - memory_available: - prometheus: - connection: prod - query: | - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 - columns: - instance: string - value: gauge -``` +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {75-103} -### Pod Count by Namespace - -```yaml -queries: - pods_per_ns: - prometheus: - connection: prod - query: | - count(kube_pod_info) by (namespace) - columns: - namespace: string - value: number ``` -### Disk Usage Percentage - -```yaml -queries: - disk_usage: - prometheus: - connection: prod - query: | - (node_filesystem_size_bytes - node_filesystem_avail_bytes) - / node_filesystem_size_bytes * 100 - columns: - device: string - mountpoint: string - value: gauge -``` +## Column Definitions -### Network Traffic +Define column types to control display and handle empty results: ```yaml -queries: - network_io: - prometheus: - connection: prod - query: | - rate(node_network_receive_bytes_total[5m]) - columns: - device: string - instance: string - value: bytes -``` - -## Using Variables in Prometheus Queries - -Make Prometheus queries dynamic with templating variables: - -```yaml -templating: - - key: job - label: "Job" - values: ["kubernetes-nodes", "kubernetes-pods", "prometheus"] - default: "kubernetes-nodes" - - - key: namespace - label: "Namespace" - values: ["default", "kube-system", "monitoring"] - default: "default" - -queries: - metrics: - prometheus: - connection: prod - query: | - up{job="$(var.job)",namespace="$(var.namespace)"} -``` - -## Column Mapping Examples - -### Simple Metric Display - -```yaml -columns: - - name: instance - type: string - primaryKey: true - - name: cpu_percent - type: gauge - gauge: - max: "100" - -queries: - cpu: - prometheus: - connection: prod - query: 'rate(node_cpu_seconds_total[5m]) * 100' - -mapping: - instance: "row.instance" - cpu_percent: "row.value" -``` - -### Metric with Multiple Labels - -```yaml -columns: - - name: pod - type: string - primaryKey: true - - name: namespace - type: string - - name: memory_mb - type: gauge - queries: memory: + columns: + namespace: string + pod: string + value: decimal prometheus: - connection: prod - query: | - container_memory_usage_bytes{pod!=""} / 1024 / 1024 - -mapping: - pod: "row.pod" - namespace: "row.namespace" - memory_mb: "row.value" -``` - -### Multiple Metrics Combined - -When combining multiple Prometheus queries: - -```yaml -columns: - - name: instance - type: string - primaryKey: true - - name: cpu_percent - type: gauge - - name: memory_percent - type: gauge - -queries: - cpu_usage: - prometheus: - connection: prod - query: 'rate(node_cpu_seconds_total[5m]) * 100' - columns: - instance: string - value: decimal - - memory_usage: - prometheus: - connection: prod + connection: connection://mc/prometheus query: | - (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) - / node_memory_MemTotal_bytes * 100 - columns: - instance: string - value: decimal - -merge: | - SELECT - c.instance, - c.value as cpu_percent, - m.value as memory_percent - FROM cpu_usage c - LEFT JOIN memory_usage m ON c.instance = m.instance - -mapping: - instance: "row.instance" - cpu_percent: "row.cpu_percent" - memory_percent: "row.memory_percent" + sum by (namespace, pod) (container_memory_working_set_bytes{...}) ``` -## Real-World Examples - -### Node Resource Dashboard - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: node-metrics -spec: - display: - title: "Node Resources" - sidebar: true - - columns: - - name: node - type: string - primaryKey: true - - name: cpu_percent - type: gauge - gauge: - max: "100" - - name: memory_percent - type: gauge - gauge: - max: "100" - - name: disk_percent - type: gauge - gauge: - max: "100" - - queries: - cpu: - prometheus: - connection: prod - query: | - rate(node_cpu_seconds_total{mode="system"}[5m]) * 100 - columns: - node: string - value: decimal - - memory: - prometheus: - connection: prod - query: | - (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) - / node_memory_MemTotal_bytes * 100 - columns: - node: string - value: decimal - - disk: - prometheus: - connection: prod - query: | - (node_filesystem_size_bytes - node_filesystem_avail_bytes) - / node_filesystem_size_bytes * 100 - columns: - node: string - value: decimal +## Auto-Mapped Columns - merge: | - SELECT - c.node, - c.value as cpu_percent, - m.value as memory_percent, - d.value as disk_percent - FROM cpu c - LEFT JOIN memory m ON c.node = m.node - LEFT JOIN disk d ON c.node = d.node - - mapping: - node: "row.node" - cpu_percent: "row.cpu_percent" - memory_percent: "row.memory_percent" - disk_percent: "row.disk_percent" -``` - -### Pod Metrics by Namespace - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: pod-metrics -spec: - display: - title: "Pod Resource Usage" - - templating: - - key: namespace - label: "Namespace" - values: ["default", "kube-system", "monitoring"] - default: "default" - - columns: - - name: pod - type: string - primaryKey: true - - name: container - type: string - - name: cpu_cores - type: decimal - - name: memory_mb - type: decimal - - queries: - pod_metrics: - prometheus: - connection: prod - query: | - { - cpu: rate(container_cpu_usage_seconds_total{namespace="$(var.namespace)",pod!=""}[5m]), - memory: container_memory_usage_bytes{namespace="$(var.namespace)",pod!=""} / 1024 / 1024 - } - columns: - pod: string - container: string - cpu: decimal - memory: decimal - - mapping: - pod: "row.pod" - container: "row.container" - cpu_cores: "row.cpu" - memory_mb: "row.memory" -``` - -### Alert Metrics Dashboard - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: alert-metrics -spec: - display: - title: "Alert Status" - card: - columns: 3 - - columns: - - name: alert_id - type: string - primaryKey: true - hidden: true - - queries: - alerts: - prometheus: - connection: prod - query: | - ALERTS{severity=~"critical|warning"} - columns: - alertname: string - severity: string - instance: string - value: number - - panels: - - name: "Critical Alerts" - type: number - query: | - SELECT COUNT(*) as value FROM alerts - WHERE severity = 'critical' - - - name: "Warning Alerts" - type: number - query: | - SELECT COUNT(*) as value FROM alerts - WHERE severity = 'warning' - - - name: "Alerts by Severity" - type: piechart - query: | - SELECT severity, COUNT(*) as value FROM alerts - GROUP BY severity - - - name: "Most Common Alerts" - type: table - query: | - SELECT alertname, COUNT(*) as count - FROM alerts - GROUP BY alertname - ORDER BY count DESC - LIMIT 10 -``` - -### Service Health Monitoring - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: service-health -spec: - display: - title: "Service Health Status" - - templating: - - key: job - label: "Service" - values: ["api-server", "database", "cache", "queue"] - default: "api-server" - - columns: - - name: instance - type: string - primaryKey: true - - name: up - type: health - - name: last_scrape - type: datetime - - name: scrape_duration_ms - type: number - - queries: - service_health: - prometheus: - connection: prod - query: | - up{job="$(var.job)"} - columns: - instance: string - value: number - - scrape_info: - prometheus: - connection: prod - query: | - { - duration: scrape_duration_seconds{job="$(var.job)"} * 1000, - timestamp: scrape_timestamp{job="$(var.job)"} - } - columns: - instance: string - duration: decimal - timestamp: datetime - - merge: | - SELECT - s.instance, - s.value as up, - sc.timestamp as last_scrape, - sc.duration as scrape_duration_ms - FROM service_health s - LEFT JOIN scrape_info sc ON s.instance = sc.instance - - mapping: - instance: "row.instance" - up: "row.up == 1 ? 'healthy' : 'critical'" - last_scrape: "row.last_scrape" - scrape_duration_ms: "row.scrape_duration_ms" -``` - -## Performance Considerations - -### Limit Query Scope -Use specific label matchers to reduce data: - -```yaml -# ✓ Specific - only relevant metrics -query: 'up{job="kubernetes-nodes",region="us-east-1"}' - -# ✗ Broad - gets all data -query: 'up' -``` - -### Use Appropriate Time Windows -For rate() and other range functions: - -```yaml -# ✓ Reasonable 5-minute window -query: 'rate(requests_total[5m])' - -# ✗ Too long window -query: 'rate(requests_total[24h])' -``` - -### Cache Long-Running Queries -Use [cache control](../concepts/cache-control.md) appropriately: - -```yaml -cache: - maxAge: 5m # Refresh less frequently for expensive queries - refreshTimeout: 10s -``` - -### Aggregation Before Query -Aggregate in PromQL rather than after fetching: - -```yaml -# ✓ Aggregate in query -query: 'sum(rate(requests_total[5m])) by (job)' - -# ✗ Fetch all, aggregate later -query: 'rate(requests_total[5m])' -# then merge to aggregate -``` - -## Common PromQL Patterns - -### Rate of Change (Per Second) -```promql -rate(metric_total[5m]) -``` - -### Percentage -```promql -(used / total) * 100 -``` - -### Convert Units -```promql -bytes_value / 1024 / 1024 # Bytes to MB -milliseconds_value / 1000 # Milliseconds to seconds -``` - -### Conditional Values -```promql -metric_value > 0.8 or on() vector(1) # Returns 1 if metric > 0.8 -``` - -### Top N Results -Use `topk()` in PromQL or `LIMIT` in merge query. - -## Troubleshooting - -### Empty Results -Check: -1. Is the connection name correct? -2. Does the Prometheus instance have the metrics? -3. Try the query directly in Prometheus UI -4. Check label names and values (case-sensitive) - -### Wrong Column Types -Ensure column definitions match your PromQL output: -```yaml -columns: - instance: string # Label names are strings - value: decimal # Metric values are typically decimal -``` +Prometheus queries return: -### Performance Issues -- Check Prometheus query performance directly -- Reduce time window or add more specific labels -- Consider using [view table selector](./view-table-selector.md) for cached data instead +- **Labels** from the metric as string columns (e.g., `namespace`, `pod`, `instance`) +- **value** as a numeric column containing the metric value diff --git a/mission-control/docs/guide/views/table/badge.md b/mission-control/docs/guide/views/table/badge.md index f160e653..700adf22 100644 --- a/mission-control/docs/guide/views/table/badge.md +++ b/mission-control/docs/guide/views/table/badge.md @@ -4,544 +4,10 @@ sidebar_custom_props: icon: mdi:label --- -The `badge` column type displays text values as styled badge/tag elements. Badges are useful for displaying categories, labels, versions, or other short text values that benefit from visual distinction. +The `badge` column type displays text values as styled badge/tag elements. Useful for categories, labels, and versions. -## Basic Usage +## Example -```yaml -columns: - - name: version_badge - type: badge -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"badge"` | -| `description` | string | Help text for column | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Version Badge - -```yaml -columns: - - name: version - type: badge - -mapping: - version: "row.properties.version" -``` - -### Label/Tag Badge - -```yaml -columns: - - name: environment - type: badge - -mapping: - environment: "row.properties.environment" -``` - -### Custom Badge from Expression - -```yaml -columns: - - name: tier_badge - type: badge - -mapping: - tier_badge: " - row.properties.tier == 'enterprise' ? 'Enterprise' : - row.properties.tier == 'premium' ? 'Premium' : - 'Free' - " -``` - -## Common Patterns - -### Application Versions -```yaml -columns: - - name: app_version - type: badge - description: "Application version" - -mapping: - app_version: "row.properties.version" -``` - -### Environment Labels -```yaml -columns: - - name: environment - type: badge - description: "Deployment environment" - - - name: region - type: badge - description: "Cloud region" - -mapping: - environment: "row.properties.environment" - region: "row.properties.region" -``` - -### Framework/Runtime Labels -```yaml -columns: - - name: runtime - type: badge - description: "Runtime environment" - - - name: framework - type: badge - description: "Application framework" - -mapping: - runtime: "row.properties.runtime_version" - framework: "row.properties.framework" -``` - -## Real-World Examples - -### Pod Runtime Versions -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: kubernetes_version - type: badge - description: "Kubernetes version" - - - name: container_runtime - type: badge - description: "Container runtime" - - - name: os - type: badge - description: "Operating system" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - kubernetes_version: "row.properties.kubernetes_version" - container_runtime: "row.properties.container_runtime" - os: "row.properties.os" -``` - -### Service Versions and Status -```yaml -columns: - - name: service_name - type: string - primaryKey: true - - - name: current_version - type: badge - description: "Running version" - - - name: target_version - type: badge - description: "Target version" - - - name: language - type: badge - description: "Programming language" - - - name: deployment_method - type: badge - description: "How it's deployed" - -queries: - services: - configs: - types: ["Service::Application"] - -mapping: - service_name: "row.name" - current_version: "row.properties.current_version" - target_version: "row.properties.target_version" - language: "row.properties.language" - deployment_method: "row.properties.deployment_strategy" -``` - -### Infrastructure Provider Tags -```yaml -columns: - - name: resource_id - type: string - primaryKey: true - - - name: provider - type: badge - description: "Cloud provider" - - - name: region - type: badge - description: "Region" - - - name: availability_zone - type: badge - description: "Availability zone" - - - name: instance_type - type: badge - description: "Instance/Machine type" - -queries: - instances: - configs: - types: ["AWS::EC2Instance", "GCP::Instance"] - -mapping: - resource_id: "row.id" - provider: "row.properties.provider" - region: "row.properties.region" - availability_zone: "row.properties.zone" - instance_type: "row.properties.instance_type" -``` - -### Database Configuration -```yaml -columns: - - name: database_name - type: string - primaryKey: true - - - name: engine - type: badge - description: "Database engine" - - - name: version - type: badge - description: "Database version" - - - name: replication_mode - type: badge - description: "Replication configuration" - - - name: backup_type - type: badge - description: "Backup method" - -queries: - databases: - configs: - types: ["Database::Instance"] - -mapping: - database_name: "row.name" - engine: "row.properties.engine" - version: "row.properties.version" - replication_mode: "row.properties.replication_mode" - backup_type: "row.properties.backup_type" -``` - -### Deployment Configuration -```yaml -columns: - - name: deployment - type: string - primaryKey: true - - - name: image_tag - type: badge - description: "Container image tag" - - - name: rollout_strategy - type: badge - description: "Rollout strategy" - - - name: scheduling_policy - type: badge - description: "Scheduling policy" - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment: "row.name" - image_tag: "row.properties.spec.template.spec.containers[0].image.split(':')[1]" - rollout_strategy: "row.properties.spec.strategy.type" - scheduling_policy: "row.properties.spec.template.spec.affinity.type" -``` - -## Badge Expressions in CEL - -### Extracting from Strings -```yaml -mapping: - # Extract image tag from full image name - image_tag: "row.image.split(':')[1]" +```yaml title="backups.yaml" file=/modules/mission-control/fixtures/views/backups.yaml {30-32} - # Extract version from version string - version: "row.version_string.split('-')[0]" ``` - -### Conditional Badges -```yaml -mapping: - # Badge based on condition - tier_badge: " - row.cpu_request > 500 ? 'High-Performance' : - row.cpu_request > 100 ? 'Standard' : - 'Minimal' - " - - # Badge based on multiple conditions - status_badge: " - row.in_maintenance ? 'Maintenance' : - row.failed_checks > 0 ? 'Issues' : - 'Normal' - " -``` - -### Version Comparison -```yaml -mapping: - # Show upgrade needed badge - upgrade_badge: " - row.current_version != row.target_version ? - 'Upgrade: ' + row.target_version : - 'Up-to-date' - " -``` - -## Badge Display Options - -Badges typically display as: -- Rounded rectangles with padding -- Background color (customizable by platform) -- Optional icons -- Text content centered - -Visual styling depends on the platform theme. - -## Filtering - -Enable users to filter by badge values: - -```yaml -columns: - - name: version - type: badge - filter: - type: "multiselect" - -mapping: - version: "row.properties.version" -``` - -Users can then filter to show specific badge values. - -## Best Practices - -1. **Keep badge text short** - Badges work best with short values - ```yaml - # ✓ Short, readable - mapping: - version: "row.version" # "1.25", "v2.0" - - # ✗ Too long - mapping: - description: "row.long_description" - ``` - -2. **Use consistent formatting** - Keep badge values standardized - ```yaml - # ✓ Consistent format - mapping: - version: "row.version" # Always "v1.0" format - - # ✗ Inconsistent - mapping: - version: "row.raw_version" # Sometimes "v1.0", sometimes "1.0" - ``` - -3. **Group related badges** - Show badges together - ```yaml - - name: runtime_version - type: badge - - name: framework_version - type: badge - - name: compiler_version - type: badge - ``` - -4. **Use for categories, not detailed info** - Keep content simple - ```yaml - # ✓ Badge-friendly data - type: badge - mapping: "row.environment" # "prod", "staging", "dev" - - # ✗ Too much detail for badge - type: badge - mapping: "row.full_configuration" # Too verbose - ``` - -5. **Add descriptions** - Explain what badges mean - ```yaml - - name: version - type: badge - description: "Application version" - ``` - -## Comparison with Other Label Types - -| Type | Use Case | -|------|----------| -| `badge` | Short label/tag values (versions, categories) | -| `string` | General text, longer values | -| `status` | Status states (pending, running, failed) | -| `health` | Health states (healthy, warning, critical) | - -Use `badge` for versions and tags. Use `string` for longer text. Use `status` for workflow states. Use `health` for operational health. - -## Common Badge Values - -### Environment Badges -``` -dev -staging -production -qa -integration-test -``` - -### Version Badges -``` -v1.0 -v1.1 -v2.0 -v2.1-beta -latest -``` - -### Provider Badges -``` -AWS -GCP -Azure -On-Premise -Hybrid -``` - -### Language Badges -``` -Go -Python -Java -Node.js -Rust -C++ -``` - -### Architecture Badges -``` -Monolith -Microservices -Serverless -Distributed -``` - -## Real Badge Examples in Views - -### Comprehensive Service View - -```yaml -columns: - - name: service_name - type: string - primaryKey: true - - - name: language - type: badge - description: "Programming language" - - - name: framework - type: badge - description: "Framework/runtime" - - - name: version - type: badge - description: "Current version" - - - name: environment - type: badge - description: "Deployed environment" - - - name: provider - type: badge - description: "Cloud provider" - -queries: - services: - configs: - types: ["Service::Application"] - -mapping: - service_name: "row.name" - language: "row.properties.language" - framework: "row.properties.framework" - version: "row.properties.version" - environment: "row.tags.environment" - provider: "row.tags.provider" -``` - -## Performance Considerations - -- Badge columns are very efficient to render -- Minimal UI overhead even with many badges -- Badge filtering is fast -- No performance impact from badge expressions - -## URL Encoding in Badges - -Badges typically don't need URL encoding unless they contain special characters: - -```yaml -mapping: - # Simple badge - no encoding needed - version: "row.version" # "1.0" - - # Badge with spaces - status_badge: "'Status: ' + row.status" # "Status: Active" -``` - -## Empty/Null Badge Handling - -```yaml -mapping: - # Show empty if null - version: "has(row.version) ? row.version : ''" - - # Show "Unknown" if null - version: "has(row.version) ? row.version : 'Unknown'" - - # Don't show anything if null - version: "has(row.version) ? row.version : null" -``` - -## Accessibility - -Badges should: -- Have sufficient color contrast -- Not rely only on color to convey information -- Include text descriptions in the view description -- Be readable at all zoom levels - -Mission Control handles most accessibility features automatically. diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/boolean.md index 319c7ab6..2cfb6c5c 100644 --- a/mission-control/docs/guide/views/table/boolean.md +++ b/mission-control/docs/guide/views/table/boolean.md @@ -4,367 +4,10 @@ sidebar_custom_props: icon: mdi:checkbox-marked-outline --- -The `boolean` column type displays true/false values as checkboxes or text labels in the table. +The `boolean` column type displays true/false values as checkboxes or text labels. -## Basic Usage +## Example -```yaml -columns: - - name: is_running - type: boolean -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"boolean"` | -| `description` | string | Help text for column | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Boolean Display - -```yaml -columns: - - name: enabled - type: boolean - -mapping: - enabled: "row.properties.enabled" -``` - -### Boolean with Description - -```yaml -columns: - - name: has_ssl - type: boolean - description: "SSL/TLS enabled" - -mapping: - has_ssl: "row.properties.ssl_enabled" -``` - -### Boolean from Condition - -```yaml -columns: - - name: is_healthy - type: boolean - -mapping: - is_healthy: "row.health == 'healthy'" -``` - -### Boolean with Filtering - -```yaml -columns: - - name: is_active - type: boolean - filter: - type: "checkbox" - -mapping: - is_active: "row.status == 'active'" -``` - -## Common Patterns - -### Status-Based Boolean -```yaml -mapping: - is_running: "row.status == 'running'" - is_error: "row.status == 'error'" - is_pending: "row.status == 'pending'" -``` +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {11-31} -### Property-Based Boolean -```yaml -mapping: - has_gpu: "has(row.properties.gpu_enabled) ? row.properties.gpu_enabled : false" - is_public: "row.properties.visibility == 'public'" - is_encrypted: "row.properties.encryption_enabled" ``` - -### Complex Logic Boolean -```yaml -mapping: - needs_attention: "row.health != 'healthy' || row.replicas < row.desired_replicas" - is_overprovisioned: "row.actual_usage < (row.allocated * 0.2)" - has_warnings: "row.warning_count > 0" -``` - -## Display Formats - -Booleans typically display as: -- **Checked/Unchecked** - Checkbox-style display -- **True/False** - Text representation -- **Yes/No** - User-friendly text -- **On/Off** - State representation -- **Enabled/Disabled** - Feature state - -The exact display depends on your UI configuration. - -## Real-World Examples - -### Pod Readiness Status -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: is_ready - type: boolean - description: "Pod is ready to serve traffic" - - - name: has_resource_requests - type: boolean - description: "Resource requests are defined" - - - name: is_privileged - type: boolean - description: "Running in privileged mode" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - is_ready: "row.properties.status.conditions.ready" - has_resource_requests: "has(row.properties.spec.containers[0].resources.requests)" - is_privileged: "row.properties.spec.securityContext.privileged" -``` - -### Database Configuration -```yaml -columns: - - name: database_name - type: string - primaryKey: true - - - name: has_backups - type: boolean - description: "Automated backups enabled" - - - name: is_replicated - type: boolean - description: "Database replication enabled" - - - name: ssl_required - type: boolean - description: "SSL connections required" - - - name: audit_logging - type: boolean - description: "Audit logging enabled" - -queries: - databases: - configs: - types: ["Database::Instance"] - -mapping: - database_name: "row.name" - has_backups: "row.properties.backup_enabled" - is_replicated: "row.properties.replication.enabled" - ssl_required: "row.properties.ssl_requirement == 'required'" - audit_logging: "row.properties.audit_config.enabled" -``` - -### Container Security Settings -```yaml -columns: - - name: container - type: string - primaryKey: true - - - name: read_only_fs - type: boolean - description: "Read-only root filesystem" - - - name: run_as_nonroot - type: boolean - description: "Runs as non-root user" - - - name: no_new_privileges - type: boolean - description: "No new privileges flag" - - - name: drop_capabilities - type: boolean - description: "Dangerous capabilities dropped" - -queries: - containers: - configs: - types: ["Kubernetes::Container"] - -mapping: - container: "row.name" - read_only_fs: "row.properties.securityContext.readOnlyRootFilesystem" - run_as_nonroot: "row.properties.securityContext.runAsNonRoot" - no_new_privileges: "row.properties.securityContext.allowPrivilegeEscalation == false" - drop_capabilities: "size(row.properties.securityContext.capabilities.drop) > 0" -``` - -### Infrastructure Compliance -```yaml -columns: - - name: resource_id - type: string - primaryKey: true - - - name: is_compliant - type: boolean - description: "Passes all compliance checks" - - - name: has_monitoring - type: boolean - description: "Monitoring enabled" - - - name: has_tagging - type: boolean - description: "Required tags present" - - - name: encryption_enabled - type: boolean - description: "Encryption at rest" - -queries: - resources: - configs: - types: ["AWS::EC2Instance", "AWS::S3Bucket"] - -mapping: - resource_id: "row.id" - is_compliant: "row.properties.tags['compliance'] == 'true' && row.properties.encryption && row.properties.monitoring" - has_monitoring: "row.properties.monitoring_enabled" - has_tagging: "has(row.tags['compliance']) && has(row.tags['owner'])" - encryption_enabled: "row.properties.encryption.enabled" -``` - -## Filtering with Boolean - -Enable filtering to allow users to show only true or false values: - -```yaml -columns: - - name: is_critical - type: boolean - filter: - type: "checkbox" - -mapping: - is_critical: "row.properties.priority == 'critical'" -``` - -Users can then filter to show: -- All items -- Only `is_critical = true` -- Only `is_critical = false` - -## Boolean Expressions in CEL - -### Comparison Operators -```yaml -mapping: - is_old: "row.created_at < now - duration('90d')" - is_large: "row.size > 1000000" - is_matching: "row.name == 'production'" -``` - -### Logical Operators -```yaml -# AND -mapping: - is_problem: "row.health == 'critical' && row.replicas == 0" - -# OR -mapping: - needs_action: "row.status == 'failed' || row.status == 'pending'" - -# NOT -mapping: - is_not_running: "row.status != 'running'" -``` - -### Collection Checks -```yaml -mapping: - has_items: "size(row.tags) > 0" - contains_prod: "row.environments.contains('production')" -``` - -### Null Checks -```yaml -mapping: - is_set: "has(row.properties.owner)" - is_empty: "!has(row.properties.description) || row.properties.description == ''" -``` - -## Best Practices - -1. **Use meaningful names** - Boolean column names should start with `is_`, `has_`, or similar - ```yaml - - name: is_running # ✓ Clear - - name: enabled # ✓ Clear - - name: pod_bool # ✗ Unclear - ``` - -2. **Provide descriptions** - Always add a description for clarity - ```yaml - - name: is_ready - type: boolean - description: "Pod is ready to serve traffic" - ``` - -3. **Use consistent logic** - Keep true conditions positive - ```yaml - # ✓ True = something good - mapping: - is_healthy: "row.health == 'healthy'" - - # ✗ Confusing - mapping: - is_broken: "row.health == 'critical'" - ``` - -4. **Handle null gracefully** - Default to false when uncertain - ```yaml - mapping: - is_set: "has(row.value) ? row.value : false" - ``` - -## Comparison with Other Types - -| Type | Use Case | -|------|----------| -| `boolean` | Yes/no, true/false states | -| `health` | Health status (healthy/warning/critical) | -| `status` | General status badge | - -Use `boolean` when you have exactly two states. Use `health` or `status` for multiple states. - -## Performance Considerations - -- Boolean columns are extremely efficient -- Boolean filtering is fast even on large datasets -- Boolean values can be indexed for quick filtering -- No performance overhead for boolean calculations - -## UI Display - -Booleans typically render as: -- **Checked box** ☑ for true -- **Unchecked box** ☐ for false -- Or as text labels: "Yes"/"No" or "Enabled"/"Disabled" - -The exact rendering depends on the platform's UI theme. diff --git a/mission-control/docs/guide/views/table/bytes.md b/mission-control/docs/guide/views/table/bytes.md index 5947e575..38e54c53 100644 --- a/mission-control/docs/guide/views/table/bytes.md +++ b/mission-control/docs/guide/views/table/bytes.md @@ -4,485 +4,18 @@ sidebar_custom_props: icon: mdi:memory --- -The `bytes` column type displays byte sizes and automatically formats them with appropriate units (B, KB, MB, GB, TB). - -## Basic Usage - -```yaml -columns: - - name: file_size - type: bytes -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"bytes"` | -| `description` | string | Help text for column | -| `precision` | integer | Decimal places for display | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Byte Size Display - -```yaml -columns: - - name: file_size - type: bytes - -mapping: - file_size: "row.properties.size_bytes" -``` - -### Storage Size with Precision - -```yaml -columns: - - name: storage_used - type: bytes - precision: 2 - -mapping: - storage_used: "row.properties.used_bytes" -``` +The `bytes` column type displays byte sizes with automatic formatting (B, KB, MB, GB, TB). ## Auto-Formatting -The bytes column automatically formats values: - | Input Value | Display | |------------|---------| | 512 | 512 B | -| 1024 | 1 KB | | 1048576 | 1 MB | | 1073741824 | 1 GB | -| 1099511627776 | 1 TB | -| 1234567890 | 1.15 GB | - -## Common Patterns - -### Storage Metrics -```yaml -columns: - - name: total_size - type: bytes - - name: used_size - type: bytes - - name: available_size - type: bytes - -mapping: - total_size: "row.properties.total_bytes" - used_size: "row.properties.used_bytes" - available_size: "row.properties.available_bytes" -``` - -### Container Image Sizes -```yaml -columns: - - name: image_name - type: string - primaryKey: true - - name: image_size - type: bytes - - name: compressed_size - type: bytes - -mapping: - image_name: "row.name" - image_size: "row.properties.uncompressed_bytes" - compressed_size: "row.properties.compressed_bytes" -``` - -### Database Storage -```yaml -columns: - - name: database_name - type: string - primaryKey: true - - name: data_size - type: bytes - - name: index_size - type: bytes - - name: total_size - type: bytes - -mapping: - database_name: "row.name" - data_size: "row.properties.data_bytes" - index_size: "row.properties.index_bytes" - total_size: "row.properties.data_bytes + row.properties.index_bytes" -``` - -## Real-World Examples - -### Kubernetes PVC Storage Status -```yaml -columns: - - name: pvc_name - type: string - primaryKey: true - - - name: capacity - type: bytes - description: "Total capacity" - - - name: used - type: bytes - description: "Currently used" - - name: available - type: bytes - description: "Available space" +## Example -queries: - pvcs: - configs: - types: ["Kubernetes::PersistentVolumeClaim"] +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {41-44} -mapping: - pvc_name: "row.name" - capacity: "row.properties.spec.resources.requests.storage" - used: "row.properties.status.used_bytes" - available: "row.properties.spec.resources.requests.storage - row.properties.status.used_bytes" ``` - -### Volume Snapshot Sizes -```yaml -columns: - - name: snapshot_name - type: string - primaryKey: true - - - name: snapshot_size - type: bytes - description: "Snapshot data size" - - - name: source_volume_size - type: bytes - description: "Original volume size" - -queries: - snapshots: - configs: - types: ["Storage::VolumeSnapshot"] - -mapping: - snapshot_name: "row.name" - snapshot_size: "row.properties.snapshot_bytes" - source_volume_size: "row.properties.source_volume_bytes" -``` - -### Object Storage Inventory -```yaml -columns: - - name: bucket_name - type: string - primaryKey: true - - - name: total_objects - type: number - - - name: total_size - type: bytes - description: "Total data stored" - - - name: avg_object_size - type: bytes - description: "Average object size" - -queries: - buckets: - configs: - types: ["Cloud::S3Bucket", "Cloud::GCSBucket"] - -mapping: - bucket_name: "row.name" - total_objects: "row.properties.object_count" - total_size: "row.properties.total_bytes" - avg_object_size: "row.properties.total_bytes / row.properties.object_count" -``` - -### Log Storage Analysis -```yaml -columns: - - name: log_stream - type: string - primaryKey: true - - - name: log_size - type: bytes - description: "Total log data size" - - - name: retention_bytes - type: bytes - description: "Retention limit" - - - name: age - type: duration - -queries: - logs: - configs: - types: ["Logging::Stream"] - -mapping: - log_stream: "row.name" - log_size: "row.properties.size_bytes" - retention_bytes: "row.properties.retention_bytes_limit" - age: "now - row.properties.first_record_time" -``` - -### Docker Image Statistics -```yaml -columns: - - name: image_id - type: string - primaryKey: true - hidden: true - - - name: image_name - type: string - - - name: size - type: bytes - description: "Uncompressed size" - - - name: virtual_size - type: bytes - description: "Virtual size" - -queries: - images: - prometheus: - connection: docker - query: | - container_image_size_bytes - columns: - image: string - size: number - -mapping: - image_id: "row.image" - image_name: "row.image" - size: "row.size" - virtual_size: "row.size" # Simplified for example -``` - -## Byte Size Expressions in CEL - -### Direct Byte Values -```yaml -mapping: - file_size: "row.properties.bytes" -``` - -### Unit Conversion -```yaml -mapping: - # Gigabytes to bytes - size_bytes: "row.properties.size_gb * 1024 * 1024 * 1024" - - # Megabytes to bytes - size_bytes: "row.properties.size_mb * 1024 * 1024" -``` - -### Byte Calculations -```yaml -mapping: - # Total from components - total_size: "row.properties.data_bytes + row.properties.index_bytes + row.properties.cache_bytes" - - # Percentage of capacity - # (Returns bytes, bytes column will format) - used_size: "(row.capacity_bytes * 0.75)" - - # With conditional - size: "row.type == 'file' ? row.file_bytes : row.directory_bytes" -``` - -## Precision Configuration - -Control decimal places in display: - -```yaml -columns: - - name: size - type: bytes - precision: 2 # Shows "1.23 GB" - -mapping: - size: "row.properties.bytes" -``` - -## Common Byte Sizes - -Reference for common values: -``` -1 KB = 1,024 bytes -1 MB = 1,024 KB = 1,048,576 bytes -1 GB = 1,024 MB = 1,073,741,824 bytes -1 TB = 1,024 GB = 1,099,511,627,776 bytes -1 PB = 1,024 TB = 1,125,899,906,842,624 bytes -``` - -## Real-World Examples with Calculations - -### Storage Utilization Percentage - -```yaml -columns: - - name: volume_name - type: string - primaryKey: true - - - name: total_capacity - type: bytes - - - name: used_space - type: bytes - - - name: utilization_percent - type: gauge - gauge: - max: "100" - thresholds: - - percent: 70 - color: "yellow" - - percent: 85 - color: "red" - -mapping: - volume_name: "row.name" - total_capacity: "row.properties.total_bytes" - used_space: "row.properties.used_bytes" - utilization_percent: "(row.properties.used_bytes / row.properties.total_bytes) * 100" -``` - -### Storage Growth Rate - -```yaml -columns: - - name: dataset_name - type: string - primaryKey: true - - - name: current_size - type: bytes - - - name: size_24h_ago - type: bytes - - - name: daily_growth - type: bytes - -mapping: - dataset_name: "row.name" - current_size: "row.properties.current_bytes" - size_24h_ago: "row.properties.size_24h_ago_bytes" - daily_growth: "row.properties.current_bytes - row.properties.size_24h_ago_bytes" -``` - -## Filtering - -Enable users to filter by size ranges: - -```yaml -columns: - - name: file_size - type: bytes - filter: - type: "range" # If supported, allows range filtering - -mapping: - file_size: "row.properties.bytes" -``` - -## Best Practices - -1. **Use bytes as base unit** - Always store values as bytes - ```yaml - # ✓ Store in bytes - mapping: - size: "row.size_bytes" - - # ✗ Store in MB - mapping: - size: "row.size_mb * 1024 * 1024" - ``` - -2. **Set appropriate precision** - Not too many decimals - ```yaml - # ✓ Reasonable precision - precision: 2 - - # ✗ Too many decimals - precision: 5 - ``` - -3. **Provide context** - Add related metrics - ```yaml - columns: - - name: total_size - type: bytes - - name: used_size - type: bytes - - name: utilization - type: gauge # Show usage too - ``` - -4. **Document limits** - Explain size constraints - ```yaml - - name: storage_used - type: bytes - description: "Current storage used (max 1TB)" - ``` - -5. **Handle edge cases** - Account for zero/null - ```yaml - mapping: - size: "has(row.bytes) ? row.bytes : 0" - ``` - -## Comparison with Other Numeric Types - -| Type | Use Case | -|------|----------| -| `bytes` | Storage sizes (auto-formatted as B, KB, MB, etc.) | -| `number` | Integer or decimal counts | -| `decimal` | Precise float values | - -Use `bytes` for storage, file, and memory sizes. Use `number` for counts. Use `decimal` for calculated percentages. - -## Performance Considerations - -- Byte formatting is very efficient -- Can display large datasets without performance issues -- Byte calculations in CEL are fast -- No significant UI rendering overhead - -## Null/Zero Handling - -```yaml -mapping: - # Default to 0 bytes if unknown - size: "has(row.bytes) ? row.bytes : 0" - - # Show as "Unknown" if null - size: "has(row.bytes) ? row.bytes : null" -``` - -## Display Units - -Bytes are automatically displayed with appropriate units based on size: -- 0-1023 B → Bytes (B) -- 1024-1MB → Kilobytes (KB) -- 1MB-1GB → Megabytes (MB) -- 1GB-1TB → Gigabytes (GB) -- 1TB+ → Terabytes (TB) - -This provides intuitive human-readable display without configuration. diff --git a/mission-control/docs/guide/views/table/config-item.md b/mission-control/docs/guide/views/table/config-item.md index c398b0fd..f63e7fcc 100644 --- a/mission-control/docs/guide/views/table/config-item.md +++ b/mission-control/docs/guide/views/table/config-item.md @@ -4,605 +4,10 @@ sidebar_custom_props: icon: config --- -The `config_item` column type displays clickable links to configuration item detail pages. It's used to navigate from one view to view details about specific configuration items in the catalog. +The `config_item` column type displays clickable links to configuration item detail pages. -## Basic Usage +## Example -```yaml -columns: - - name: pod_link - type: config_item - configItem: - idField: "id" -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"config_item"` | -| `description` | string | Help text for column | -| `configItem` | object | Config item configuration | -| `for` | string | Column to use as link text | - -## ConfigItem Configuration - -```yaml -configItem: - # Required: which field contains the config item ID - idField: "id" -``` - -## Example Usage - -### Simple Config Link - -```yaml -columns: - - name: pod_detail - type: config_item - configItem: - idField: "id" - -mapping: - pod_detail: "row.id" -``` - -### Config Link with Custom Text - -```yaml -columns: - - name: pod_detail - type: config_item - for: "pod_name" # Use pod_name as display text - configItem: - idField: "id" - -mapping: - pod_name: "row.name" # Display text - pod_detail: "row.id" # The link target -``` - -## Common Patterns - -### Navigation from Summary to Details -```yaml -columns: - - name: resource_name - type: string - primaryKey: true - - - name: resource_detail - type: config_item - for: "resource_name" - configItem: - idField: "id" - -mapping: - resource_name: "row.name" - resource_detail: "row.id" -``` - -### Multiple Config Links -```yaml -columns: - - name: pod - type: string - primaryKey: true - - - name: pod_detail - type: config_item - for: "pod" - configItem: - idField: "id" - - - name: parent_node - type: config_item - for: "node_name" - configItem: - idField: "parent_id" - -mapping: - pod: "row.name" - pod_detail: "row.id" - node_name: "row.parent_name" - parent_node: "row.parent_id" -``` - -## Real-World Examples - -### Pod Summary with Drill-Down - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: namespace - type: string - - - name: status - type: status - - - name: pod_details - type: config_item - for: "pod_name" - description: "View full pod details" - configItem: - idField: "id" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - namespace: "row.namespace" - status: "row.status" - pod_details: "row.id" -``` - -Clicking the pod name in the `pod_details` column opens the full pod configuration page. - -### Deployment and Related Pods - -```yaml -columns: - - name: deployment_name - type: string - primaryKey: true - - - name: replicas - type: number - - - name: status - type: status - - - name: deployment_config - type: config_item - for: "deployment_name" - description: "View deployment config" - configItem: - idField: "id" - - - name: owner_namespace - type: string - - - name: namespace_config - type: config_item - for: "owner_namespace" - description: "View namespace" - configItem: - idField: "namespace_id" - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment_name: "row.name" - replicas: "row.properties.spec.replicas" - status: "row.status" - deployment_config: "row.id" - owner_namespace: "row.namespace" - namespace_config: "row.namespace_id" -``` - -Users can navigate to either the deployment or namespace configuration details. - -### Container Images with Registry Links - -```yaml -columns: - - name: pod - type: string - primaryKey: true - - - name: image_registry - type: string - - - name: image_config - type: config_item - for: "image_name" - description: "View image details" - configItem: - idField: "image_config_id" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod: "row.name" - image_name: "row.properties.spec.containers[0].image" - image_registry: "row.properties.spec.containers[0].image.split('/')[0]" - image_config: "row.properties.image_config_id" -``` - -### Multi-Level Navigation - -```yaml -columns: - - name: instance_name - type: string - primaryKey: true - - - name: instance_detail - type: config_item - for: "instance_name" - configItem: - idField: "instance_id" - - - name: volume_name - type: string - - - name: volume_detail - type: config_item - for: "volume_name" - configItem: - idField: "volume_id" - - - name: availability_zone - type: string - - - name: az_detail - type: config_item - for: "availability_zone" - configItem: - idField: "az_id" - -queries: - instances: - configs: - types: ["AWS::EC2Instance"] - -mapping: - instance_name: "row.name" - instance_detail: "row.id" - volume_name: "row.properties.volume_name" - volume_detail: "row.properties.volume_id" - availability_zone: "row.properties.az" - az_detail: "row.properties.az_id" -``` - -Navigate from instance → volume → availability zone, drilling down at each level. - -### Service Mesh Components - -```yaml -columns: - - name: service_name - type: string - primaryKey: true - - - name: service_detail - type: config_item - for: "service_name" - configItem: - idField: "service_id" - - - name: virtual_service - type: string - - - name: vs_detail - type: config_item - for: "virtual_service" - configItem: - idField: "vs_id" - - - name: destination_rule - type: string - - - name: dr_detail - type: config_item - for: "destination_rule" - configItem: - idField: "dr_id" - -queries: - services: - configs: - types: ["Istio::Service"] - -mapping: - service_name: "row.name" - service_detail: "row.id" - virtual_service: "row.properties.virtualservice_name" - vs_detail: "row.properties.virtualservice_id" - destination_rule: "row.properties.destination_rule_name" - dr_detail: "row.properties.destination_rule_id" -``` +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {16-17} -Navigate between service, virtual service, and destination rule configurations. - -## Link Text Display - -The link text comes from the `for` property: - -```yaml -columns: - - name: resource_link - type: config_item - for: "resource_name" # Use this column's value as link text - configItem: - idField: "id" - -mapping: - resource_name: "row.name" # Display as link text - resource_link: "row.id" # Link target (not visible) -``` - -The user sees `row.name` as a clickable link. Clicking navigates to the configuration page for `row.id`. - -## Config Item Detail Pages - -Clicking a config_item link opens the configuration detail page for that resource, which includes: -- Full configuration in JSON/YAML -- Property explorer -- Related resources -- Change history -- Cost information (if available) -- Custom properties -- Tags and labels - -## Column Layout - -Typically you'll have: -1. **Display column** (string) - Shows the name/identifier -2. **Link column** (config_item) - Provides the navigation - -```yaml -columns: - # Display what the resource is - - name: pod_name - type: string - primaryKey: true - - # Clickable link to details - - name: pod_details - type: config_item - for: "pod_name" - configItem: - idField: "id" - -mapping: - pod_name: "row.name" - pod_details: "row.id" -``` - -Or combine them: - -```yaml -columns: - - name: pod_detail - type: config_item - for: "pod_name" # Show pod name as link text - configItem: - idField: "id" - -mapping: - pod_name: "row.name" # Display text - pod_detail: "row.id" # Link target -``` - -## Using Variables with Config Links - -You can use variables in config_item expressions: - -```yaml -columns: - - name: cluster_resource - type: config_item - configItem: - idField: "id" - -templating: - - key: cluster - label: "Cluster" - values: ["us-east-1", "us-west-2"] - -mapping: - cluster_resource: "row.id" # Same ID regardless of cluster variable -``` - -The config_item always links by ID; variables don't affect the link target, only which rows are displayed. - -## Best Practices - -1. **Use for navigation** - Make drill-down easy - ```yaml - # ✓ Easy navigation path - - name: pod_name - type: string - - name: pod_detail - type: config_item - ``` - -2. **Provide meaningful text** - Show what the link is about - ```yaml - # ✓ Clear link purpose - for: "pod_name" - - # ✗ Generic link text - for: "link" - ``` - -3. **Use consistent IDs** - ID field must be unique and valid - ```yaml - # ✓ Unique config IDs - idField: "id" - - # ✗ Might not be unique - idField: "name" - ``` - -4. **Add descriptions** - Explain what clicking does - ```yaml - - name: pod_details - type: config_item - description: "View complete pod configuration" - ``` - -5. **Combine with filters** - Use view filters for context - ```yaml - templating: - - key: cluster - values: ["prod", "staging"] - - # User selects cluster, then clicks config_item to drill down - ``` - -## Multiple Config Items - -You can have multiple config_item links in one view: - -```yaml -columns: - - name: pod_detail - type: config_item - for: "pod" - configItem: - idField: "pod_id" - - - name: node_detail - type: config_item - for: "node" - configItem: - idField: "node_id" - -mapping: - pod: "row.pod_name" - pod_detail: "row.pod_id" - node: "row.node_name" - node_detail: "row.node_id" -``` - -Users can navigate to either the pod or node details. - -## Column ID Mapping - -The `idField` property must match your config ID structure: - -```yaml -configItem: - idField: "id" # Simple ID field - # OR - idField: "row.properties.config_id" # Nested ID ``` - -Ensure the mapped value is a valid config ID in the catalog. - -## Filtering for Config Items - -Config items are typically not filtered directly, but you can filter the parent view: - -```yaml -columns: - - name: pod_detail - type: config_item - configItem: - idField: "id" - -# Filter shows/hides rows, which affects what config items are linked -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - status: "running" # Only show running pods - -mapping: - pod_detail: "row.id" -``` - -## Performance Considerations - -- Config_item columns are very efficient -- No performance impact from multiple config_item links -- Links resolve instantly when clicked -- Minimal UI overhead - -## Comparison with URL Column Type - -| Type | Use Case | -|------|----------| -| `config_item` | Navigate to Mission Control config detail page | -| `url` | Navigate to external URLs or custom views | - -Use `config_item` to drill into config details. Use `url` for external links. - -## Real-World Navigation Example - -### Complete Resource Hierarchy - -```yaml -columns: - - name: pod - type: string - primaryKey: true - - - name: pod_detail - type: config_item - for: "pod" - configItem: - idField: "pod_id" - - - name: deployment - type: string - - - name: deployment_detail - type: config_item - for: "deployment" - configItem: - idField: "deployment_id" - - - name: namespace - type: string - - - name: namespace_detail - type: config_item - for: "namespace" - configItem: - idField: "namespace_id" - - - name: cluster - type: string - - - name: cluster_detail - type: config_item - for: "cluster" - configItem: - idField: "cluster_id" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod: "row.name" - pod_detail: "row.id" - deployment: "row.deployment_name" - deployment_detail: "row.deployment_id" - namespace: "row.namespace" - namespace_detail: "row.namespace_id" - cluster: "row.cluster_name" - cluster_detail: "row.cluster_id" -``` - -User can navigate: Pod → Pod Details, Pod → Deployment Details, Pod → Namespace Details, Pod → Cluster Details - -All from a single summary view. - -## Error Handling - -If a config ID is invalid or doesn't exist: -- Link may appear disabled -- Clicking shows an error -- Ensure IDs are valid and exist in your catalog - -Test with sample data before deploying views. diff --git a/mission-control/docs/guide/views/table/datetime.md b/mission-control/docs/guide/views/table/datetime.md index e3f01928..5402f0c5 100644 --- a/mission-control/docs/guide/views/table/datetime.md +++ b/mission-control/docs/guide/views/table/datetime.md @@ -4,405 +4,10 @@ sidebar_custom_props: icon: mdi:calendar-clock --- -The `datetime` column type displays timestamp values formatted as human-readable dates and times. +The `datetime` column type displays timestamps with human-readable formatting. -## Basic Usage +## Example -```yaml -columns: - - name: created_at - type: datetime -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"datetime"` | -| `description` | string | Help text for column | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Timestamp Display - -```yaml -columns: - - name: created_at - type: datetime - -mapping: - created_at: "row.created_at" -``` - -### DateTime from Calculation - -```yaml -columns: - - name: last_updated - type: datetime - -mapping: - last_updated: "row.updated_at" -``` - -### DateTime with Description - -```yaml -columns: - - name: deployment_time - type: datetime - description: "When this resource was deployed" - -mapping: - deployment_time: "row.properties.deployment_timestamp" -``` - -## Common Patterns - -### Resource Lifecycle Timestamps -```yaml -columns: - - name: created_at - type: datetime - - name: updated_at - type: datetime - - name: deleted_at - type: datetime - -mapping: - created_at: "row.created_at" - updated_at: "row.updated_at" - deleted_at: "row.deleted_at" -``` - -### Event Timeline -```yaml -columns: - - name: event_time - type: datetime - - name: acknowledged_at - type: datetime - - name: resolved_at - type: datetime - -mapping: - event_time: "row.event_timestamp" - acknowledged_at: "row.acknowledgment_timestamp" - resolved_at: "row.resolution_timestamp" -``` - -### Calculated Timestamps -```yaml -columns: - - name: last_check - type: datetime - -mapping: - # Last time status was checked (from metrics) - last_check: "row.properties.last_status_check_time" -``` - -## DateTime Formatting - -The platform automatically formats datetime values. Examples: -- `2024-01-15T10:30:00Z` displays as `Jan 15, 2024 10:30 AM` -- Time zone information is preserved -- Relative times may be shown ("2 hours ago") - -## Real-World Examples - -### Pod Event Timeline -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: created_at - type: datetime - description: "Pod creation time" - - - name: ready_since - type: datetime - description: "When pod became ready" +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {30-31} - - name: last_transition - type: datetime - description: "Last status change" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - created_at: "row.created_at" - ready_since: "row.properties.status.conditions[0].lastTransitionTime" - last_transition: "row.updated_at" ``` - -### Deployment History -```yaml -columns: - - name: deployment - type: string - primaryKey: true - - - name: deployed_at - type: datetime - description: "Deployment time" - - - name: image_built_at - type: datetime - description: "Container image build time" - - - name: last_update - type: datetime - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment: "row.name" - deployed_at: "row.created_at" - image_built_at: "row.properties.image_build_time" - last_update: "row.updated_at" -``` - -### Certificate Expiration Tracking -```yaml -columns: - - name: certificate_name - type: string - primaryKey: true - - - name: issued_at - type: datetime - description: "Issue date" - - - name: expires_at - type: datetime - description: "Expiration date" - - - name: last_renewed - type: datetime - -queries: - certs: - configs: - types: ["Security::Certificate"] - -mapping: - certificate_name: "row.name" - issued_at: "row.properties.not_before" - expires_at: "row.properties.not_after" - last_renewed: "row.properties.renewal_timestamp" -``` - -### Change Audit Trail -```yaml -columns: - - name: change_id - type: string - primaryKey: true - hidden: true - - - name: resource - type: string - - - name: changed_at - type: datetime - description: "When change occurred" - - - name: first_seen - type: datetime - - - name: last_seen - type: datetime - -queries: - changes: - changes: - types: ["Kubernetes::Pod"] - limit: 100 - -mapping: - change_id: "row.id" - resource: "row.config_name" - changed_at: "row.created_at" - first_seen: "row.first_seen_at" - last_seen: "row.last_seen_at" -``` - -### System Events Timeline -```yaml -columns: - - name: event_id - type: string - primaryKey: true - hidden: true - - - name: event_type - type: string - - - name: resource - type: string - - - name: occurred_at - type: datetime - - - name: logged_at - type: datetime - -queries: - events: - configs: - types: ["System::Event"] - -mapping: - event_id: "row.id" - event_type: "row.properties.event_type" - resource: "row.properties.affected_resource" - occurred_at: "row.properties.event_time" - logged_at: "row.created_at" -``` - -## DateTime Filtering - -Enable users to filter by date ranges: - -```yaml -columns: - - name: created_at - type: datetime - filter: - type: "date" - -mapping: - created_at: "row.created_at" -``` - -Users can then filter to show: -- Items created before a date -- Items created after a date -- Items created within a date range - -## DateTime Expressions in CEL - -### Creating DateTime Values -```yaml -mapping: - # Use timestamp conversion - event_time: "timestamp('2024-01-15T10:30:00Z')" - - # Current time - now_time: "now" -``` - -### DateTime Calculations -```yaml -mapping: - # Age in days - age_days: "(now - row.created_at) / duration('24h')" - - # Is old (created more than 90 days ago) - is_old: "row.created_at < now - duration('90d')" - - # Days until expiration - days_until_expiry: "(row.expires_at - now) / duration('24h')" -``` - -### DateTime Comparisons -```yaml -mapping: - is_recent: "row.created_at > now - duration('7d')" - is_expired: "row.expires_at < now" - is_coming_due: "row.expires_at > now && row.expires_at < now + duration('30d')" -``` - -## Best Practices - -1. **Use meaningful names** - DateTime columns should indicate time aspect - ```yaml - - name: created_at # ✓ Clear - - name: last_updated # ✓ Clear - - name: timestamp # ✓ Acceptable - - name: time1 # ✗ Unclear - ``` - -2. **Provide descriptions** - Explain what the timestamp represents - ```yaml - - name: created_at - type: datetime - description: "When this resource was first created" - ``` - -3. **Show timezone** - Include timezone info when relevant - ```yaml - - name: created_at - type: datetime - description: "Creation time (UTC)" - ``` - -4. **Order chronologically** - Present timestamps in logical time order - ```yaml - - name: created_at - type: datetime - - name: updated_at - type: datetime - - name: deleted_at - type: datetime - ``` - -5. **Handle null timestamps** - Default gracefully when time is unknown - ```yaml - mapping: - deleted_at: "has(row.deleted_at) ? row.deleted_at : null" - ``` - -## Comparison with Other Time Types - -| Type | Use Case | -|------|----------| -| `datetime` | Specific point in time (when something happened) | -| `duration` | Length of time (how long something took) | - -Use `datetime` for "when" questions. Use `duration` for "how long" questions. - -## Performance Considerations - -- DateTime columns are efficient to store and retrieve -- DateTime filtering can be optimized with proper indexing -- DateTime calculations in CEL are fast -- No significant performance overhead for datetime operations - -## Timezone Handling - -- All datetimes are stored in UTC internally -- Display timezone depends on user's local settings -- When querying, assume UTC times in database -- CEL expressions work with UTC values - -## Auto-Generated Fields - -Many resources automatically provide: -- `created_at` - When resource was created -- `updated_at` - Last modification time -- `deleted_at` - When resource was deleted (if deleted) - -These are available directly from `row.created_at`, `row.updated_at`, etc. - -## Relative Time Display - -The UI may display datetime values as: -- Absolute: "Jan 15, 2024 10:30 AM" -- Relative: "2 hours ago" -- Combined: "Jan 15, 2024 10:30 AM (2 hours ago)" - -The exact display format depends on UI configuration. diff --git a/mission-control/docs/guide/views/table/decimal.md b/mission-control/docs/guide/views/table/decimal.md index 68760e08..e0ee7520 100644 --- a/mission-control/docs/guide/views/table/decimal.md +++ b/mission-control/docs/guide/views/table/decimal.md @@ -4,515 +4,17 @@ sidebar_custom_props: icon: mdi:decimal --- -The `decimal` column type displays precise floating-point numbers with configurable decimal places. Use it for calculated values, percentages, ratios, and other decimal numbers. - -## Basic Usage - -```yaml -columns: - - name: cost_per_hour - type: decimal - precision: 2 -``` +The `decimal` column type displays precise floating-point numbers with configurable decimal places. ## Properties | Property | Type | Description | |----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"decimal"` | -| `description` | string | Help text for column | | `precision` | integer | Number of decimal places | | `unit` | string | Display unit (e.g., "$", "%") | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Cost Display - -```yaml -columns: - - name: monthly_cost - type: decimal - precision: 2 - unit: "$" - -mapping: - monthly_cost: "row.cost_total_30d" -``` -### Percentage Calculation +## Example -```yaml -columns: - - name: error_rate - type: decimal - precision: 2 - unit: "%" +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {76-80} -mapping: - error_rate: "(row.errors / row.total_requests) * 100" ``` - -### Ratio Display - -```yaml -columns: - - name: memory_ratio - type: decimal - precision: 3 - -mapping: - memory_ratio: "row.used_memory / row.total_memory" -``` - -## Common Patterns - -### Financial Calculations -```yaml -columns: - - name: unit_price - type: decimal - precision: 2 - unit: "$" - - - name: total_price - type: decimal - precision: 2 - unit: "$" - -mapping: - unit_price: "row.properties.price" - total_price: "row.properties.price * row.quantity" -``` - -### Performance Metrics -```yaml -columns: - - name: response_time_avg - type: decimal - precision: 2 - unit: "ms" - - - name: throughput - type: decimal - precision: 1 - unit: "req/s" - -mapping: - response_time_avg: "row.total_response_time / row.request_count" - throughput: "row.requests_per_second" -``` - -### Efficiency Metrics -```yaml -columns: - - name: cache_hit_ratio - type: decimal - precision: 3 - - - name: compression_ratio - type: decimal - precision: 2 - -mapping: - cache_hit_ratio: "row.cache_hits / (row.cache_hits + row.cache_misses)" - compression_ratio: "row.original_size / row.compressed_size" -``` - -## Real-World Examples - -### Cost Analysis Dashboard -```yaml -columns: - - name: resource_id - type: string - primaryKey: true - - - name: hourly_rate - type: decimal - precision: 4 - unit: "$" - - - name: daily_cost - type: decimal - precision: 2 - unit: "$" - - - name: monthly_cost - type: decimal - precision: 2 - unit: "$" - - - name: yearly_cost - type: decimal - precision: 2 - unit: "$" - -queries: - resources: - configs: - types: ["AWS::EC2Instance"] - -mapping: - resource_id: "row.id" - hourly_rate: "row.properties.hourly_cost" - daily_cost: "row.properties.hourly_cost * 24" - monthly_cost: "row.cost_total_30d" - yearly_cost: "row.cost_total_30d * 12" -``` - -### API Performance Metrics -```yaml -columns: - - name: endpoint - type: string - primaryKey: true - - - name: avg_response_ms - type: decimal - precision: 2 - unit: "ms" - - - name: p95_response_ms - type: decimal - precision: 2 - unit: "ms" - - - name: p99_response_ms - type: decimal - precision: 2 - unit: "ms" - - - name: error_rate_percent - type: decimal - precision: 3 - unit: "%" - -queries: - metrics: - prometheus: - connection: prod - query: | - { - avg: http_request_duration_seconds, - p95: histogram_quantile(0.95, http_request_duration_seconds), - p99: histogram_quantile(0.99, http_request_duration_seconds), - errors: rate(http_errors_total[5m]) - } - columns: - endpoint: string - avg: decimal - p95: decimal - p99: decimal - errors: decimal - -mapping: - endpoint: "row.endpoint" - avg_response_ms: "row.avg * 1000" - p95_response_ms: "row.p95 * 1000" - p99_response_ms: "row.p99 * 1000" - error_rate_percent: "row.errors * 100" -``` - -### Database Performance Metrics -```yaml -columns: - - name: query_name - type: string - primaryKey: true - - - name: avg_duration_ms - type: decimal - precision: 2 - unit: "ms" - - - name: avg_cpu_percent - type: decimal - precision: 1 - unit: "%" - - - name: avg_memory_mb - type: decimal - precision: 1 - unit: "MB" - -queries: - queries: - configs: - types: ["Database::QueryStatistic"] - -mapping: - query_name: "row.name" - avg_duration_ms: "row.properties.avg_duration_ms" - avg_cpu_percent: "row.properties.avg_cpu_percent" - avg_memory_mb: "row.properties.avg_memory_bytes / 1024 / 1024" -``` - -### Resource Efficiency Report -```yaml -columns: - - name: resource_name - type: string - primaryKey: true - - - name: requested_cpu - type: decimal - precision: 2 - unit: " cores" - - - name: actual_cpu_avg - type: decimal - precision: 2 - unit: " cores" - - - name: utilization_percent - type: decimal - precision: 1 - unit: "%" - - - name: waste_factor - type: decimal - precision: 2 - -mapping: - resource_name: "row.name" - requested_cpu: "row.properties.cpu_request / 1000" - actual_cpu_avg: "row.properties.cpu_avg / 1000" - utilization_percent: "(row.properties.cpu_avg / row.properties.cpu_request) * 100" - waste_factor: "row.properties.cpu_request / row.properties.cpu_avg" -``` - -## Decimal Expressions in CEL - -### Simple Division -```yaml -mapping: - ratio: "row.used / row.total" - percentage: "(row.used / row.total) * 100" -``` - -### Rounding -```yaml -mapping: - # Round to 2 decimal places - price: "round(row.calculated_price, 2)" - - # Round to nearest 0.5 - rating: "round(row.score * 2) / 2" -``` - -### Conditional Decimals -```yaml -mapping: - adjusted_rate: " - row.tier == 'enterprise' ? row.base_rate * 0.9 : - row.tier == 'premium' ? row.base_rate * 0.95 : - row.base_rate - " -``` - -### Range Normalization -```yaml -mapping: - # Normalize to 0-1 range - normalized: "(row.value - row.min) / (row.max - row.min)" - - # Clamp between 0 and 1 - clamped: "min(max(row.value / row.max, 0), 1)" -``` - -## Precision Guidelines - -Choose precision based on your data: - -```yaml -# Currency (cents) -precision: 2 -unit: "$" - -# Percentages (0.01%) -precision: 2 -unit: "%" - -# Time (milliseconds) -precision: 2 -unit: "ms" - -# Ratios (0.001) -precision: 3 - -# Scientific values -precision: 4 or more -``` - -## Real-World Precision Examples - -### Unit Price -```yaml -- name: unit_price - type: decimal - precision: 2 - unit: "$" -# Display: $19.99, $99.99 -``` - -### Efficiency Ratio -```yaml -- name: efficiency - type: decimal - precision: 3 -# Display: 0.950, 0.987, 1.025 -``` - -### Response Time -```yaml -- name: response_time_ms - type: decimal - precision: 2 - unit: "ms" -# Display: 125.43ms, 1250.80ms -``` - -### Error Rate -```yaml -- name: error_rate_percent - type: decimal - precision: 3 - unit: "%" -# Display: 0.123%, 5.456%, 25.000% -``` - -## Filtering - -Enable users to filter by numeric ranges: - -```yaml -columns: - - name: cost_per_month - type: decimal - filter: - type: "range" - -mapping: - cost_per_month: "row.cost_total_30d" -``` - -## Comparison with Other Numeric Types - -| Type | Use Case | -|------|----------| -| `decimal` | Precise floating-point (costs, percentages, ratios) | -| `number` | Integer or decimal counts | -| `gauge` | Percentage 0-100 with visual gauge | -| `bytes` | Storage sizes with auto-formatting | - -Use `decimal` for precise calculations. Use `number` for counts. Use `gauge` for percentages with visualization. - -## Performance Considerations - -- Decimal columns are very efficient -- Decimal calculations in CEL are fast -- Can handle large datasets -- Minimal UI rendering overhead - -## Null/Zero Handling - -```yaml -mapping: - # Default to 0 if unknown - rate: "has(row.rate) ? row.rate : 0" - - # Show as "N/A" if not applicable - ratio: "row.total > 0 ? row.used / row.total : null" - - # Prevent division by zero - percentage: "row.total > 0 ? (row.used / row.total) * 100 : 0" -``` - -## Unit Display - -Units display after the value: -- `19.99 $` (currency) -- `125.43 ms` (milliseconds) -- `0.987` (ratio, no unit) -- `45.50 %` (percentage) - -Configure with the `unit` property in your column definition. - -## Common Decimal Calculations - -### Percentage -```yaml -mapping: - percent: "(row.value / row.total) * 100" -``` - -### Ratio -```yaml -mapping: - ratio: "row.value / row.target" -``` - -### Moving Average -```yaml -mapping: - avg: "(row.sum_1d / row.count_1d)" -``` - -### Growth Rate -```yaml -mapping: - growth: "((row.current - row.previous) / row.previous) * 100" -``` - -### Cost Projection -```yaml -mapping: - monthly_estimate: "row.daily_cost * 30" -``` - -## Best Practices - -1. **Set appropriate precision** - Match your data accuracy - ```yaml - # ✓ Currency needs 2 decimal places - precision: 2 - unit: "$" - - # ✗ Too many decimals for currency - precision: 5 - ``` - -2. **Include units** - Make values understandable - ```yaml - # ✓ Clear what unit represents - unit: "$" - unit: "%" - unit: "ms" - - # ✗ No context - unit: "" - ``` - -3. **Prevent division by zero** - Use conditional logic - ```yaml - mapping: - ratio: "row.denominator > 0 ? row.numerator / row.denominator : 0" - ``` - -4. **Round appropriately** - Use round() for display - ```yaml - mapping: - price: "round(row.calculated, 2)" # Always 2 decimal places - ``` - -5. **Document calculations** - Add descriptions - ```yaml - - name: utilization_percent - type: decimal - precision: 1 - unit: "%" - description: "Actual usage divided by requested resources" - ``` diff --git a/mission-control/docs/guide/views/table/duration.md b/mission-control/docs/guide/views/table/duration.md index 81e64065..d805f2ed 100644 --- a/mission-control/docs/guide/views/table/duration.md +++ b/mission-control/docs/guide/views/table/duration.md @@ -4,419 +4,10 @@ sidebar_custom_props: icon: mdi:timer-outline --- -The `duration` column type displays time spans and durations in a human-readable format (e.g., "2h 30m", "1d"). +The `duration` column type displays time spans in human-readable format (e.g., "2h 30m", "1d"). -## Basic Usage +## Example -```yaml -columns: - - name: uptime - type: duration -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"duration"` | -| `description` | string | Help text for column | -| `unit` | string | Default unit for display (optional) | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Duration Display - -```yaml -columns: - - name: build_time - type: duration - -mapping: - build_time: "row.properties.build_duration" -``` - -### Duration from Timestamp Difference - -```yaml -columns: - - name: pod_age - type: duration - -mapping: - pod_age: "now - row.created_at" -``` - -### Duration with Description - -```yaml -columns: - - name: sla_remaining - type: duration - description: "Time remaining for SLA compliance" - -mapping: - sla_remaining: "row.sla_deadline - now" -``` - -## Common Patterns - -### Resource Lifecycle Durations -```yaml -columns: - - name: uptime - type: duration - description: "Time since creation" - - - name: time_since_update - type: duration - description: "Time since last update" - -mapping: - uptime: "now - row.created_at" - time_since_update: "now - row.updated_at" -``` - -### Process Execution Times -```yaml -columns: - - name: build_time - type: duration - - name: deploy_time - type: duration - - name: total_time - type: duration - -mapping: - build_time: "row.properties.build_end - row.properties.build_start" - deploy_time: "row.properties.deploy_end - row.properties.deploy_start" - total_time: "row.properties.deploy_end - row.properties.build_start" -``` - -### Time to Compliance -```yaml -columns: - - name: sla_time_remaining - type: duration - - name: time_to_expiration - type: duration - -mapping: - sla_time_remaining: "row.sla_deadline - now" - time_to_expiration: "row.expires_at - now" -``` - -## Duration Formatting - -Durations are automatically formatted for readability: -- `3600s` displays as `1h` -- `5400s` displays as `1h 30m` -- `86400s` displays as `1d` -- `2h 30m 45s` displays as written - -## Real-World Examples - -### Pod Uptime Monitoring -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: uptime - type: duration - description: "Time since pod started" - - - name: ready_duration - type: duration - description: "How long pod has been ready" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - uptime: "now - row.created_at" - ready_duration: "now - row.properties.status.conditions[0].lastTransitionTime" -``` - -### CI/CD Pipeline Metrics -```yaml -columns: - - name: build_id - type: string - primaryKey: true - - - name: total_duration - type: duration - description: "Total build time" - - - name: compile_duration - type: duration - description: "Compilation time" - - - name: test_duration - type: duration - description: "Testing time" - - - name: deploy_duration - type: duration - description: "Deployment time" - -queries: - builds: - configs: - types: ["CI::BuildRun"] - -mapping: - build_id: "row.id" - total_duration: "row.properties.end_time - row.properties.start_time" - compile_duration: "row.properties.compile_end - row.properties.compile_start" - test_duration: "row.properties.test_end - row.properties.test_start" - deploy_duration: "row.properties.deploy_end - row.properties.deploy_start" -``` - -### Certificate Expiration Timeline -```yaml -columns: - - name: certificate - type: string - primaryKey: true - - - name: age - type: duration - description: "Certificate age" - - - name: time_until_expiry - type: duration - description: "Time remaining before expiration" - - - name: renewal_window_open - type: duration - description: "Time until renewal window opens" - -queries: - certs: - configs: - types: ["Security::Certificate"] - -mapping: - certificate: "row.name" - age: "now - row.properties.not_before" - time_until_expiry: "row.properties.not_after - now" - renewal_window_open: "(row.properties.not_after - duration('30d')) - now" -``` - -### Backup and Sync Operations -```yaml -columns: - - name: backup_name - type: string - primaryKey: true - - - name: duration_seconds - type: duration - description: "How long backup took" - - - name: age - type: duration - description: "How old the backup is" - - - name: next_backup_in - type: duration - description: "Time until next backup" - -queries: - backups: - configs: - types: ["Backup::Job"] - -mapping: - backup_name: "row.name" - duration_seconds: "row.properties.end_time - row.properties.start_time" - age: "now - row.properties.completed_at" - next_backup_in: "row.properties.next_scheduled - now" -``` - -### SLA Compliance Tracking -```yaml -columns: - - name: incident_id - type: string - primaryKey: true - - - name: time_to_resolution - type: duration - description: "Total time to resolve" - - - name: sla_deadline - type: datetime - - - name: time_to_deadline - type: duration - -queries: - incidents: - configs: - types: ["Incident::Report"] - -mapping: - incident_id: "row.id" - time_to_resolution: "row.properties.resolved_at - row.created_at" - sla_deadline: "row.created_at + duration('4h')" - time_to_deadline: "(row.created_at + duration('4h')) - now" -``` - -## Duration Expressions in CEL - -### Creating Durations -```yaml -mapping: - # Using duration literal - timeout: "duration('5m')" - - # Common durations - hour: "duration('1h')" - day: "duration('24h')" - week: "duration('168h')" - - # Custom calculations - two_hours: "duration('2h')" -``` - -### Duration Calculations -```yaml -mapping: - # Time difference - elapsed: "now - row.start_time" - - # Add duration to time - deadline: "now + duration('30d')" - - # Duration arithmetic - total_time: "(row.end_time - row.start_time) + duration('5m')" -``` - -### Duration Comparisons -```yaml -mapping: - is_old: "(now - row.created_at) > duration('90d')" - is_urgent: "(row.deadline - now) < duration('1h')" - requires_renewal: "(row.expires_at - now) < duration('30d')" -``` - -### Duration to Numeric Value -```yaml -mapping: - # Convert to seconds - seconds: "(now - row.created_at) / duration('1s')" - - # Convert to hours - hours: "(now - row.created_at) / duration('1h')" - - # Convert to days - days: "(now - row.created_at) / duration('24h')" -``` - -## Common Duration Values - -These duration literals are commonly used in CEL: - -``` -1s - 1 second -1m - 1 minute -1h - 1 hour -24h - 1 day -168h - 1 week -720h - 1 month (30 days) -8760h - 1 year (365 days) -``` - -Combine them: -``` -1h30m - 1 hour and 30 minutes -2h45m30s - 2 hours, 45 minutes, 30 seconds -``` - -## Best Practices - -1. **Use meaningful names** - Duration columns should indicate what duration they represent - ```yaml - - name: uptime # ✓ Clear - - name: build_time # ✓ Clear - - name: duration # ? Generic - - name: time1 # ✗ Unclear - ``` - -2. **Provide descriptions** - Explain what the duration measures - ```yaml - - name: uptime - type: duration - description: "Time since pod was created" - ``` - -3. **Handle negative durations** - Document what negative means - ```yaml - - name: time_to_deadline - type: duration - description: "Positive = time remaining, Negative = overdue" - ``` - -4. **Consider filtering** - Enable filtering for common durations - ```yaml - - name: pod_age - type: duration - filter: - type: "duration" - - mapping: - pod_age: "now - row.created_at" - ``` - -5. **Order chronologically** - Present durations in logical order - ```yaml - - name: created_duration # Oldest - - name: modified_duration # More recent - ``` - -## Comparison with Other Time Types - -| Type | Use Case | -|------|----------| -| `duration` | Length of time (how long) | -| `datetime` | Specific point in time (when) | - -Use `duration` for "how long did this take" or "how old is this". Use `datetime` for "when did this happen". - -## Performance Considerations - -- Duration columns are efficient to calculate and display -- Duration calculations in CEL expressions are fast -- No significant performance overhead - -## Display Examples - -How durations appear in the UI: -- `3600s` → `1h` -- `5400s` → `1h 30m` -- `90s` → `1m 30s` -- `86400s` → `1d` -- `604800s` → `7d` -- Negative durations might show as "Past" or display the difference - -## Null Duration Handling - -When duration is unknown or null: - -```yaml -mapping: - # Default to 0 if unknown - duration: "has(row.duration) ? row.duration : duration('0s')" +```yaml title="pipelines.yaml" file=/modules/mission-control/fixtures/views/pipelines.yaml {49-51} - # Show as "Not available" - duration: "has(row.duration) ? row.duration : null" ``` diff --git a/mission-control/docs/guide/views/table/gauge.md b/mission-control/docs/guide/views/table/gauge.md index 80afbe5a..5fc918da 100644 --- a/mission-control/docs/guide/views/table/gauge.md +++ b/mission-control/docs/guide/views/table/gauge.md @@ -4,564 +4,19 @@ sidebar_custom_props: icon: mdi:gauge --- -The `gauge` column type displays numeric values (typically 0-100) as visual progress bars or gauge visualizations with customizable thresholds and colors. +The `gauge` column type displays numeric values as visual gauges with configurable thresholds and colors. -## Basic Usage - -```yaml -columns: - - name: cpu_usage - type: gauge - gauge: - max: "100" -``` - -## Properties +## Gauge Configuration | Property | Type | Description | |----------|------|-------------| -| `name` | string | Column name | -| `type` | string | Set to `"gauge"` | -| `gauge` | object | Gauge configuration | - -## Gauge Configuration - -```yaml -gauge: - # Required: maximum value for the gauge - max: "100" - - # Optional: minimum value (default: 0) - min: "0" - - # Optional: decimal precision - precision: 1 - - # Optional: display unit - unit: "%" - - # Optional: color thresholds - thresholds: - - percent: 50 - color: "yellow" - - percent: 80 - color: "red" - - # Optional: show percentage - showPercent: true - - # Optional: show value - showValue: true -``` - -## Example Usage - -### CPU Usage Percentage - -```yaml -columns: - - name: cpu_percent - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 50 - color: "yellow" - - percent: 80 - color: "red" - -mapping: - cpu_percent: "row.cpu_usage" -``` - -### Memory Usage with Thresholds - -```yaml -columns: - - name: memory_usage - type: gauge - gauge: - max: "100" - precision: 1 - unit: "%" - thresholds: - - percent: 70 - color: "yellow" - - percent: 90 - color: "red" - -mapping: - memory_usage: "(row.memory_used / row.memory_total) * 100" -``` - -### Disk Space Percentage - -```yaml -columns: - - name: disk_usage - type: gauge - gauge: - max: "100" - unit: "%" - showPercent: true - -mapping: - disk_usage: "(row.disk_used / row.disk_total) * 100" -``` - -### Custom Scale Gauge - -```yaml -columns: - - name: connection_pool - type: gauge - gauge: - min: "0" - max: "100" # Max connections - unit: " connections" - showValue: true - -mapping: - connection_pool: "row.active_connections" -``` - -## Common Patterns - -### Resource Utilization -```yaml -columns: - - name: cpu_usage - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 75 - color: "yellow" - - percent: 90 - color: "red" - - - name: memory_usage - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 75 - color: "yellow" - - percent: 90 - color: "red" - -mapping: - cpu_usage: "row.cpu_percent" - memory_usage: "row.memory_percent" -``` - -### Health Score -```yaml -columns: - - name: health_score - type: gauge - gauge: - max: "100" - unit: " points" - thresholds: - - percent: 50 - color: "red" - - percent: 75 - color: "yellow" - -mapping: - health_score: "row.computed_health_score" -``` - -### Capacity Planning -```yaml -columns: - - name: utilization - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 80 - color: "orange" - - percent: 95 - color: "red" - -mapping: - utilization: "(row.used / row.capacity) * 100" -``` - -## Threshold Configuration - -Thresholds define when the gauge color changes: - -```yaml -gauge: - max: "100" - thresholds: - # At 0%, start with green (default) - # At 50%, change to yellow - - percent: 50 - color: "yellow" - # At 80%, change to red - - percent: 80 - color: "red" -``` - -The gauge automatically: -- Shows green (healthy) from 0 to first threshold -- Transitions through colors as value increases -- Shows red (critical) above the last threshold - -## Real-World Examples - -### Node Resource Monitoring -```yaml -columns: - - name: node_name - type: string - primaryKey: true - - - name: cpu_usage - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 70 - color: "yellow" - - percent: 85 - color: "red" - - - name: memory_usage - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 70 - color: "yellow" - - percent: 85 - color: "red" - - - name: disk_usage - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 80 - color: "yellow" - - percent: 90 - color: "red" - -queries: - nodes: - prometheus: - connection: prod - query: | - { - cpu: rate(node_cpu_seconds_total[5m]) * 100, - memory: (node_memory_MemTotal_bytes - node_memory_MemFree_bytes) / node_memory_MemTotal_bytes * 100, - disk: (node_filesystem_size_bytes - node_filesystem_avail_bytes) / node_filesystem_size_bytes * 100 - } - columns: - node: string - cpu: decimal - memory: decimal - disk: decimal - -mapping: - node_name: "row.node" - cpu_usage: "row.cpu" - memory_usage: "row.memory" - disk_usage: "row.disk" -``` +| `max` | string | Maximum value (can be CEL like `row.memory_limit`) | +| `min` | string | Minimum value | +| `precision` | int | Decimal places | +| `thresholds` | array | Color thresholds by percent | -### Database Connection Pool Status -```yaml -columns: - - name: pool_name - type: string - primaryKey: true +## Example - - name: utilization - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 70 - color: "yellow" - - percent: 90 - color: "red" - - - name: connections_used - type: number - - - name: connections_max - type: number - -queries: - pools: - configs: - types: ["Database::ConnectionPool"] - -mapping: - pool_name: "row.name" - utilization: "(row.properties.active / row.properties.max_connections) * 100" - connections_used: "row.properties.active" - connections_max: "row.properties.max_connections" -``` - -### Kubernetes Pod Resource Requests -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: cpu_allocated - type: gauge - gauge: - max: "2" # 2 CPU cores - unit: " cores" - precision: 2 - showValue: true - - - name: memory_allocated - type: gauge - gauge: - max: "8" # 8 GB - unit: " GB" - precision: 1 - showValue: true - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - cpu_allocated: "row.properties.spec.containers[0].resources.requests.cpu / 1000" - memory_allocated: "row.properties.spec.containers[0].resources.requests.memory / 1024 / 1024 / 1024" -``` - -### SLA Compliance Score -```yaml -columns: - - name: service_name - type: string - primaryKey: true - - - name: sla_compliance - type: gauge - gauge: - max: "100" - unit: "%" - precision: 1 - thresholds: - - percent: 95 - color: "red" # Below 95% SLA = warning - - percent: 99 - color: "yellow" # 95-99% = yellow - - - name: uptime_percent - type: gauge - gauge: - max: "100" - unit: "%" - -mapping: - service_name: "row.name" - sla_compliance: "row.properties.sla_compliance_percent" - uptime_percent: "row.properties.uptime_percent" -``` - -### Storage Capacity Planning -```yaml -columns: - - name: storage_system - type: string - primaryKey: true - - - name: capacity_used - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 70 - color: "yellow" - - percent: 85 - color: "red" - - - name: iops_utilization - type: gauge - gauge: - max: "100" - unit: "%" - thresholds: - - percent: 75 - color: "yellow" - - percent: 90 - color: "red" - -queries: - storage: - configs: - types: ["Storage::Volume"] - -mapping: - storage_system: "row.name" - capacity_used: "(row.properties.used_capacity / row.properties.total_capacity) * 100" - iops_utilization: "(row.properties.current_iops / row.properties.max_iops) * 100" -``` - -## Gauge Expressions in CEL - -### Percentage Calculation -```yaml -mapping: - # Simple percentage - usage_percent: "(row.used / row.total) * 100" - - # Capped at 100% - usage_capped: "min(row.used / row.total, 1.0) * 100" - - # With minimum - usage_min: "max(row.used / row.total, 0.0) * 100" -``` - -### Conditional Gauge Values -```yaml -mapping: - # Use different calculation based on condition - utilization: " - row.type == 'cpu' ? (row.used / 4) * 100 : - row.type == 'memory' ? (row.used / 16) * 100 : - (row.used / row.max) * 100 - " -``` - -## Best Practices - -1. **Set appropriate max values** - Match your scale - ```yaml - # CPU percentage - gauge: - max: "100" - - # Memory in GB - gauge: - max: "16" - - # Connections - gauge: - max: "1000" - ``` - -2. **Use meaningful thresholds** - Match your SLOs - ```yaml - # ✓ Clear thresholds for your use case - thresholds: - - percent: 70 - color: "yellow" - - percent: 85 - color: "red" - - # ✗ Unclear thresholds - thresholds: - - percent: 50 - color: "yellow" - ``` - -3. **Include units** - Make values understandable - ```yaml - gauge: - unit: "%" # ✓ Clear - unit: " GB" # ✓ Clear - unit: "" # ✗ No context - ``` - -4. **Add descriptions** - Explain what's being measured - ```yaml - - name: cpu_usage - type: gauge - description: "CPU utilization (0-100%)" - ``` - -5. **Pair with numeric columns** - Show the actual value too - ```yaml - - name: cpu_gauge - type: gauge - - name: cpu_cores - type: number - unit: " cores" # Show the actual value - ``` - -## Color Themes - -Standard color progression: -- **Green** - Healthy (0-50%) -- **Yellow** - Warning (50-80%) -- **Red** - Critical (80-100%) - -Customize based on your thresholds and needs. - -## Display Options - -Gauges can show: -- **Bar/Progress bar** - Horizontal gauge visualization -- **Circular gauge** - Speedometer-style visualization -- **Value and unit** - Numeric display with unit -- **Percentage** - Show as percentage - -Configuration options: -```yaml -gauge: - showPercent: true # Show % value - showValue: true # Show numeric value - # Display style depends on UI implementation -``` - -## Performance Considerations - -- Gauge calculations are very efficient -- Threshold evaluation is fast -- Can handle large datasets -- Minimal UI rendering overhead - -## Comparison with Other Numeric Types - -| Type | Use Case | -|------|----------| -| `gauge` | Percentage or 0-max range with visual representation | -| `decimal` | Precise numeric values without visualization | -| `number` | Integer or decimal counts | - -Use `gauge` for percentages and ratios. Use `number` for counts. Use `decimal` for precise calculations. - -## Gauge Formula Examples - -### CPU to Percentage -```yaml -mapping: - cpu_percent: "(row.cpu_nanocores / 1000 / 1000) / row.cpu_cores / 100" -``` - -### Memory Percentage -```yaml -mapping: - memory_percent: "(row.memory_bytes / (1024 * 1024 * 1024)) / row.memory_gb * 100" -``` +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {25-38} -### Normalized Score -```yaml -mapping: - score: "min(max(row.raw_score, 0), 100)" ``` diff --git a/mission-control/docs/guide/views/table/health.md b/mission-control/docs/guide/views/table/health.md index 4449deb7..f4a60503 100644 --- a/mission-control/docs/guide/views/table/health.md +++ b/mission-control/docs/guide/views/table/health.md @@ -4,407 +4,12 @@ sidebar_custom_props: icon: health --- -The `health` column type displays health status with color-coded badges showing three states: healthy (green), warning (yellow), and critical (red). +The `health` column type displays health status with color-coded indicators. Supports three states: `healthy` (green), `warning` (yellow), and `unhealthy`/`critical` (red). -## Basic Usage +## Example -```yaml -columns: - - name: health_status - type: health -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"health"` | -| `description` | string | Help text for column | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Health States - -The health column supports three states: - -| State | Color | Meaning | -|-------|-------|---------| -| `healthy` | Green | Operating normally, no issues | -| `warning` | Yellow | Minor issues or degradation | -| `critical` | Red | Major issues, needs attention | - -## Example Usage - -### Direct Health Property - -```yaml -columns: - - name: health - type: health - -mapping: - health: "row.health" -``` - -### Health from Status - -```yaml -columns: - - name: pod_health - type: health - -mapping: - pod_health: "row.properties.status" -``` - -### Health from Condition - -```yaml -columns: - - name: cluster_health - type: health - -mapping: - cluster_health: "row.status == 'ready' ? 'healthy' : 'critical'" -``` - -## Common Patterns - -### Simple Health Status -```yaml -mapping: - health: "row.health" -``` - -### Health from Replica Mismatch -```yaml -mapping: - health: "row.replicas == row.ready_replicas ? 'healthy' : row.ready_replicas > 0 ? 'warning' : 'critical'" -``` - -### Health from Multiple Conditions -```yaml -mapping: - health: " - row.cpu_usage > 90 || row.memory_usage > 90 ? 'critical' : - row.cpu_usage > 75 || row.memory_usage > 75 ? 'warning' : - 'healthy' - " -``` - -### Health from Property -```yaml -mapping: - health: "row.properties.health_check_status" -``` - -## Real-World Examples - -### Kubernetes Pod Health -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: health - type: health - description: "Pod health status" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - health: "row.health" -``` - -### Deployment Replica Status -```yaml -columns: - - name: deployment - type: string - primaryKey: true - - - name: replica_health - type: health - description: "Replica status" - - - name: desired_replicas - type: number - - - name: ready_replicas - type: number - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment: "row.name" - replica_health: "row.properties.spec.replicas == row.properties.status.readyReplicas ? 'healthy' : row.properties.status.readyReplicas > 0 ? 'warning' : 'critical'" - desired_replicas: "row.properties.spec.replicas" - ready_replicas: "row.properties.status.readyReplicas" -``` - -### Database Connection Pool Health -```yaml -columns: - - name: pool_name - type: string - primaryKey: true - - - name: health - type: health - description: "Connection pool health" - - - name: active_connections - type: number - - - name: max_connections - type: number - -queries: - pools: - configs: - types: ["Database::ConnectionPool"] - -mapping: - pool_name: "row.name" - health: "row.active_connections >= row.max_connections * 0.9 ? 'critical' : row.active_connections >= row.max_connections * 0.75 ? 'warning' : 'healthy'" - active_connections: "row.properties.active" - max_connections: "row.properties.max_connections" -``` +```yaml title="ingress.yaml" file=/modules/mission-control/fixtures/views/ingress.yaml {41-47} -### Service Health from Multiple Metrics -```yaml -columns: - - name: service_name - type: string - primaryKey: true - - - name: health - type: health - description: "Overall service health" - - - name: error_rate - type: gauge - - - name: response_time - type: number - unit: "ms" - -queries: - services: - configs: - types: ["Service::Instance"] - -mapping: - service_name: "row.name" - health: " - row.properties.error_rate > 5 || row.properties.response_time > 1000 ? 'critical' : - row.properties.error_rate > 1 || row.properties.response_time > 500 ? 'warning' : - 'healthy' - " - error_rate: "row.properties.error_rate" - response_time: "row.properties.response_time" -``` - -### Infrastructure Node Health -```yaml -columns: - - name: node_name - type: string - primaryKey: true - - - name: health - type: health - description: "Node health" - - - name: cpu_usage - type: gauge - gauge: - max: "100" - - - name: memory_usage - type: gauge - gauge: - max: "100" - - - name: disk_usage - type: gauge - gauge: - max: "100" - -queries: - nodes: - configs: - types: ["Kubernetes::Node"] - -mapping: - node_name: "row.name" - health: " - row.cpu > 90 || row.memory > 90 || row.disk > 90 ? 'critical' : - row.cpu > 75 || row.memory > 75 || row.disk > 75 ? 'warning' : - 'healthy' - " - cpu_usage: "row.properties.cpu_percent" - memory_usage: "row.properties.memory_percent" - disk_usage: "row.properties.disk_percent" -``` - -## Health Filtering - -Enable users to filter by health status: - -```yaml -columns: - - name: health - type: health - filter: - type: "multiselect" - -mapping: - health: "row.health" -``` - -Users can then filter to show: -- All items -- Only healthy items -- Only warning items -- Only critical items -- Any combination of states - -## Health Expressions in CEL - -### Threshold-Based Health -```yaml -mapping: - # Simple threshold - health: "row.cpu_usage > 80 ? 'critical' : 'healthy'" - - # Range-based - health: "row.cpu_usage > 90 ? 'critical' : row.cpu_usage > 75 ? 'warning' : 'healthy'" - - # Multiple conditions - health: " - (row.cpu_usage > 90 || row.memory_usage > 90) ? 'critical' : - (row.cpu_usage > 75 || row.memory_usage > 75) ? 'warning' : - 'healthy' - " ``` -### State-Based Health -```yaml -mapping: - # Health from status field - health: "row.status == 'active' ? 'healthy' : row.status == 'degraded' ? 'warning' : 'critical'" - - # Health from readiness - health: "row.is_ready ? 'healthy' : 'critical'" -``` - -### Time-Based Health -```yaml -mapping: - # Old items are critical - health: " - (now - row.last_check) > duration('1h') ? 'critical' : - (now - row.last_check) > duration('30m') ? 'warning' : - 'healthy' - " -``` - -## Best Practices - -1. **Use consistent thresholds** - Define thresholds once and reuse across views - ```yaml - # Define at the top level - # CPU: < 75% = healthy, 75-90% = warning, > 90% = critical - # Memory: similar thresholds - ``` - -2. **Document thresholds** - Use descriptions to explain what makes a resource healthy - ```yaml - - name: health - type: health - description: "CPU < 75% = healthy, < 90% = warning, >= 90% = critical" - ``` - -3. **Consider context** - Health meaning may vary by resource type - ```yaml - # For critical services, stricter thresholds - # For development resources, more lenient thresholds - ``` - -4. **Combine with details** - Show health alongside relevant metrics - ```yaml - - name: health - type: health - - name: cpu_usage - type: gauge # Show the actual value too - ``` - -5. **Avoid overcomplication** - Keep health logic understandable - ```yaml - # ✓ Clear and maintainable - health: "row.status == 'healthy' ? 'healthy' : 'critical'" - - # ✗ Complex and hard to understand - health: "size([x for x in row.conditions if x.status == 'ok']) == size(row.conditions) ? 'healthy' : size([x for x in row.conditions if x.status == 'ok']) > 0 ? 'warning' : 'critical'" - ``` - -## Comparison with Other Status Types - -| Type | Use Case | -|------|----------| -| `health` | Three-state health (healthy/warning/critical) | -| `status` | General status badges (any custom status) | -| `boolean` | Binary true/false states | - -Use `health` for operational health. Use `status` for custom statuses like "pending", "failed", "queued", etc. - -## Performance Considerations - -- Health columns are efficient to calculate and display -- Health filtering is fast even with large datasets -- No significant performance overhead for health expressions - -## Visual Representation - -Health states typically display as: -- **Green checkmark** ✓ for healthy -- **Yellow triangle** ⚠ for warning -- **Red X** ✗ for critical - -The exact icons and colors depend on the UI theme. - -## Combining Multiple Health Signals - -To combine multiple health indicators: - -```yaml -columns: - - name: overall_health - type: health - - name: cpu_health - type: health - - name: memory_health - type: health - - name: disk_health - type: health - -mapping: - overall_health: " - (row.cpu_health == 'critical' || row.memory_health == 'critical' || row.disk_health == 'critical') ? 'critical' : - (row.cpu_health == 'warning' || row.memory_health == 'warning' || row.disk_health == 'warning') ? 'warning' : - 'healthy' - " - cpu_health: "row.cpu > 90 ? 'critical' : row.cpu > 75 ? 'warning' : 'healthy'" - memory_health: "row.memory > 90 ? 'critical' : row.memory > 75 ? 'warning' : 'healthy'" - disk_health: "row.disk > 90 ? 'critical' : row.disk > 75 ? 'warning' : 'healthy'" -``` +Use `card.useForAccent: true` to color the card based on health. diff --git a/mission-control/docs/guide/views/table/index.mdx b/mission-control/docs/guide/views/table/index.mdx index 9525550c..cea0f0ba 100644 --- a/mission-control/docs/guide/views/table/index.mdx +++ b/mission-control/docs/guide/views/table/index.mdx @@ -1,10 +1,59 @@ --- sidebar_position: 3 -title: Table +title: Table Columns sidebar_custom_props: icon: view-details --- +Tables define the structure and display of view data. Each column has a type that controls how values are rendered and filtered. + +## Column Definition + +Columns are defined in `spec.columns`: + +```yaml +columns: + - name: pod_name # Column identifier (used in mapping) + type: string # Column type + primaryKey: true # At least one column must be a primary key + description: "Pod name" +``` + +## Example + +This example demonstrates multiple column types including gauge, status, health, datetime, and card positioning: + +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {7-65} + +``` + +## Common Properties + +All column types support these properties: + +| Property | Type | Description | +|----------|------|-------------| +| `name` | string | Column identifier (required) | +| `type` | string | Column type (required) | +| `primaryKey` | bool | Include in composite primary key | +| `description` | string | Help text for the column | +| `hidden` | bool | Hide from table display | +| `filter` | object | Enable filtering (`type: multiselect`) | +| `icon` | string | Icon for the column (supports CEL like `row.health`) | +| `card` | object | Card layout position (`position`, `useForAccent`) | + +## Card Positioning + +Columns can be positioned in card layouts using `card.position`: + +- `title` - Card title area +- `subtitle` - Subtitle area +- `deck` - Header area after subtitle +- `body` - Main content area +- `footer` - Footer area +- `headerRight` - Right side of header + +## Column Types import DocCardList from '@theme/DocCardList'; diff --git a/mission-control/docs/guide/views/table/millicore.md b/mission-control/docs/guide/views/table/millicore.md index 31760a29..77e40310 100644 --- a/mission-control/docs/guide/views/table/millicore.md +++ b/mission-control/docs/guide/views/table/millicore.md @@ -4,415 +4,18 @@ sidebar_custom_props: icon: mdi:cpu-64-bit --- -The `millicore` column type displays CPU resources in millicores (m) with automatic formatting. 1000 millicores = 1 CPU core. - -## Basic Usage - -```yaml -columns: - - name: cpu_request - type: millicore -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"millicore"` | -| `description` | string | Help text for column | -| `precision` | integer | Decimal places for display | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### CPU Request Display - -```yaml -columns: - - name: cpu_request - type: millicore - -mapping: - cpu_request: "row.properties.cpu_request_m" -``` - -### CPU Limit Display - -```yaml -columns: - - name: cpu_limit - type: millicore - precision: 1 - -mapping: - cpu_limit: "row.properties.cpu_limit_m" -``` +The `millicore` column type displays CPU resources in millicores (1000m = 1 CPU core). ## Conversion -Millicores are the standard unit for Kubernetes CPU requests/limits: - | Value | Display | Meaning | |-------|---------|---------| -| 100 | 100m | 0.1 CPU core (10% of a core) | -| 500 | 500m | 0.5 CPU core (50% of a core) | -| 1000 | 1000m or 1 | 1 full CPU core | -| 2000 | 2000m or 2 | 2 CPU cores | -| 2500 | 2500m or 2.5 | 2.5 CPU cores | - -## Common Patterns - -### Pod Resource Limits -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: cpu_request - type: millicore - - - name: cpu_limit - type: millicore - -mapping: - pod_name: "row.name" - cpu_request: "row.properties.spec.containers[0].resources.requests.cpu_m" - cpu_limit: "row.properties.spec.containers[0].resources.limits.cpu_m" -``` - -### Node CPU Capacity -```yaml -columns: - - name: node_name - type: string - primaryKey: true - - - name: allocatable_cpu - type: millicore - - - name: requested_cpu - type: millicore - - - name: available_cpu - type: millicore - -mapping: - node_name: "row.name" - allocatable_cpu: "row.properties.status.allocatable.cpu_m" - requested_cpu: "row.properties.status.requested.cpu_m" - available_cpu: "row.properties.status.allocatable.cpu_m - row.properties.status.requested.cpu_m" -``` - -## Real-World Examples - -### Pod CPU Requests and Limits -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: container - type: string - - - name: cpu_request - type: millicore - description: "Requested CPU (minimum guaranteed)" - - - name: cpu_limit - type: millicore - description: "CPU limit (maximum allowed)" - - - name: cpu_usage - type: millicore - description: "Current actual usage" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - container: "row.properties.spec.containers[0].name" - cpu_request: "row.properties.spec.containers[0].resources.requests.cpu * 1000" - cpu_limit: "row.properties.spec.containers[0].resources.limits.cpu * 1000" - cpu_usage: "row.properties.metrics.cpu_m" -``` - -### Node Resource Allocation -```yaml -columns: - - name: node_name - type: string - primaryKey: true - - - name: total_capacity - type: millicore - description: "Total CPU capacity" - - - name: allocatable - type: millicore - description: "CPU available for pods" - - - name: requested - type: millicore - description: "Sum of all pod requests" - - - name: available - type: millicore - description: "Remaining unallocated CPU" - -queries: - nodes: - configs: - types: ["Kubernetes::Node"] - -mapping: - node_name: "row.name" - total_capacity: "row.properties.status.capacity.cpu * 1000" - allocatable: "row.properties.status.allocatable.cpu * 1000" - requested: "row.properties.status.requested.cpu * 1000" - available: "(row.properties.status.allocatable.cpu - row.properties.status.requested.cpu) * 1000" -``` - -### Deployment CPU Planning -```yaml -columns: - - name: deployment_name - type: string - primaryKey: true - - - name: replicas - type: number - - - name: cpu_per_replica - type: millicore - - - name: total_cpu_requested - type: millicore - - - name: total_cpu_limit - type: millicore - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment_name: "row.name" - replicas: "row.properties.spec.replicas" - cpu_per_replica: "row.properties.spec.template.spec.containers[0].resources.requests.cpu * 1000" - total_cpu_requested: "row.properties.spec.replicas * row.properties.spec.template.spec.containers[0].resources.requests.cpu * 1000" - total_cpu_limit: "row.properties.spec.replicas * row.properties.spec.template.spec.containers[0].resources.limits.cpu * 1000" -``` +| 100 | 100m | 10% of a core | +| 500 | 500m | 50% of a core | +| 1000 | 1000m | 1 full CPU core | -### Resource Request Validation -```yaml -columns: - - name: pod_name - type: string - primaryKey: true +## Example - - name: cpu_request - type: millicore - - - name: is_request_reasonable - type: health - description: "Request is between 10m and 2000m" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - cpu_request: "row.properties.spec.containers[0].resources.requests.cpu * 1000" - is_request_reasonable: " - has(row.properties.spec.containers[0].resources.requests) && - row.cpu_request >= 10 && - row.cpu_request <= 2000 - ? 'healthy' : 'warning' - " -``` - -## Millicore Expressions in CEL - -### Convert from CPU Cores to Millicores -```yaml -mapping: - # From cores to millicores - cpu_m: "row.cpu_cores * 1000" - - # From string "0.5" to 500m - cpu_m: "float(row.cpu_string) * 1000" -``` - -### Calculate Total CPU -```yaml -mapping: - total_cpu_m: "row.replicas * row.cpu_per_replica_m" -``` - -### CPU Allocation Percentage -```yaml -mapping: - allocation_percent: "(row.requested_m / row.allocatable_m) * 100" -``` - -### CPU Headroom -```yaml -mapping: - available_m: "row.allocatable_m - row.requested_m" -``` - -## Comparison with Cores - -Millicore is Kubernetes' standard unit: - -```yaml -# ✓ Use millicores (Kubernetes standard) -cpu_request: "row.resources.requests.cpu * 1000" # Convert to millicore - -# ✗ Don't use cores for Kubernetes -cpu_request: "row.resources.requests.cpu" # Would be fractional - -# ✓ Display with millicore type -type: millicore -``` - -## Real-World Millicore Values - -Common CPU requests in Kubernetes: - -| Value | Typical Use Case | -|-------|-----------------| -| 10-50m | Sidecar containers, minimal overhead | -| 50-100m | Small services, non-critical apps | -| 100-250m | Standard services, small microservices | -| 250-500m | Medium services, moderate workloads | -| 500m-1 | Larger services, significant computation | -| 1-2 | CPU-intensive workloads | -| 2+ | High-performance applications | - -## Best Practices - -1. **Use millicore for Kubernetes CPU** - It's the standard unit - ```yaml - # ✓ Kubernetes standard - type: millicore - - # ✗ Avoid raw core values - type: decimal - ``` - -2. **Provide meaningful defaults** - Common requests - ```yaml - # ✓ Standard requests - - 100m (10% of a core) - - 250m (25% of a core) - - 500m (50% of a core) - - 1000m (1 full core) - ``` - -3. **Set request and limit together** - Show both - ```yaml - - name: cpu_request - type: millicore - - name: cpu_limit - type: millicore - ``` - -4. **Validate reasonable ranges** - Use health checks - ```yaml - - name: cpu_validity - type: health - description: "Request is reasonable" - ``` - -5. **Monitor node capacity** - Show what's available - ```yaml - - name: available_cpu - type: millicore - description: "Unallocated CPU on node" - ``` - -## Filtering - -Enable filtering by CPU ranges: - -```yaml -columns: - - name: cpu_request - type: millicore - filter: - type: "range" - -mapping: - cpu_request: "row.cpu_request_m" -``` - -Users can filter to find: -- Pods with excessive CPU requests -- Pods with too little CPU -- Nodes with low CPU availability - -## Performance Considerations - -- Millicore columns are very efficient -- Millicore calculations are fast -- Can handle large pod counts -- No significant UI overhead - -## Comparison with Other Resource Types - -| Type | Use Case | -|------|----------| -| `millicore` | CPU resources in millicores (Kubernetes standard) | -| `bytes` | Memory in bytes | -| `number` | Other numeric values | -| `decimal` | Floating-point calculations | - -Use `millicore` specifically for CPU. Use `bytes` for memory. Use `number` for counts. - -## Null/Zero Handling - -```yaml -mapping: - # Default to 0 if not specified - cpu_request: "has(row.cpu_request_m) ? row.cpu_request_m : 0" - - # Show "unlimited" if no limit - cpu_limit: "has(row.cpu_limit_m) ? row.cpu_limit_m : null" -``` - -## Common Millicore Calculations - -### Total CPU for Deployment -```yaml -mapping: - total_cpu: "row.spec.replicas * row.spec.containers[0].resources.requests.cpu * 1000" -``` - -### CPU Headroom on Node -```yaml -mapping: - available_cpu: "(row.allocatable.cpu - row.requested.cpu) * 1000" -``` - -### CPU Over-subscription Ratio -```yaml -mapping: - ratio: "row.requested.cpu / row.allocatable.cpu" -``` +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {46-48} -### CPU Burst Headroom -```yaml -mapping: - burst_available: "(row.allocatable.cpu - row.requested_limit.cpu) * 1000" ``` diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/number.md index 7ab163b9..c87c07a9 100644 --- a/mission-control/docs/guide/views/table/number.md +++ b/mission-control/docs/guide/views/table/number.md @@ -4,327 +4,17 @@ sidebar_custom_props: icon: mdi:numeric --- -The `number` column type displays numeric values in a standard number format. This includes integers and decimal values. - -## Basic Usage - -```yaml -columns: - - name: pod_count - type: number -``` +The `number` column type displays numeric values (integers and decimals). ## Properties | Property | Type | Description | |----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"number"` | -| `description` | string | Help text for column | -| `unit` | string | Display unit (e.g., "pods", "requests/sec") | | `precision` | integer | Decimal places to display | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Count Display - -```yaml -columns: - - name: replica_count - type: number - -mapping: - replica_count: "row.properties.replicas" -``` - -### Number with Precision - -```yaml -columns: - - name: cpu_cores - type: number - precision: 2 - -mapping: - cpu_cores: "row.properties.cpu_limit / 1000" -``` - -### Number with Unit - -```yaml -columns: - - name: request_rate - type: number - unit: "requests/sec" - -mapping: - request_rate: "row.properties.requests_per_second" -``` - -### Number from Calculation - -```yaml -columns: - - name: uptime_days - type: number - precision: 1 - -mapping: - uptime_days: "(now - row.created_at) / duration('24h')" -``` - -## Common Patterns - -### Pod/Replica Counts -```yaml -columns: - - name: desired_replicas - type: number - - name: ready_replicas - type: number - -mapping: - desired_replicas: "row.properties.spec.replicas" - ready_replicas: "row.properties.status.readyReplicas" -``` - -### Resource Quotas -```yaml -columns: - - name: cpu_allocated - type: number - unit: "cores" - - name: memory_allocated - type: number - unit: "GB" - -mapping: - cpu_allocated: "row.properties.cpu_limit / 1000" - memory_allocated: "row.properties.memory_limit / 1024 / 1024 / 1024" -``` - -### Calculated Metrics -```yaml -columns: - - name: average_response_time - type: number - unit: "ms" - precision: 2 - -mapping: - average_response_time: "row.total_response_time / row.request_count" -``` - -## Number Formatting - -### Whole Numbers -```yaml -columns: - - name: pod_count - type: number - precision: 0 - -mapping: - pod_count: "row.properties.pod_count" -``` - -### Decimal Values -```yaml -columns: - - name: cpu_usage - type: number - precision: 3 - unit: "cores" - -mapping: - cpu_usage: "row.properties.cpu_usage_cores" -``` - -## Filtering - -Enable users to filter by numeric ranges or exact values: - -```yaml -columns: - - name: replica_count - type: number - filter: - type: "number" # Enables numeric filtering - -mapping: - replica_count: "row.properties.replicas" -``` - -## Real-World Examples - -### Kubernetes Deployment Status -```yaml -columns: - - name: deployment - type: string - primaryKey: true - - - name: desired_replicas - type: number - - - name: ready_replicas - type: number - - - name: available_replicas - type: number - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment: "row.name" - desired_replicas: "row.properties.spec.replicas" - ready_replicas: "row.properties.status.readyReplicas" - available_replicas: "row.properties.status.availableReplicas" -``` - -### Database Connection Pool -```yaml -columns: - - name: pool_name - type: string - primaryKey: true - - - name: total_connections - type: number - - - name: active_connections - type: number - - - name: idle_connections - type: number - -queries: - pools: - configs: - types: ["Database::ConnectionPool"] - -mapping: - pool_name: "row.name" - total_connections: "row.properties.max_connections" - active_connections: "row.properties.active" - idle_connections: "row.properties.idle" -``` - -### API Request Metrics -```yaml -columns: - - name: endpoint - type: string - primaryKey: true - - - name: total_requests - type: number - unit: "requests" - - - name: error_rate_percent - type: number - unit: "%" - precision: 2 - - - name: avg_latency_ms - type: number - unit: "ms" - precision: 1 - -queries: - metrics: - prometheus: - connection: prod - query: | - { - requests: increase(http_requests_total[1h]), - errors: increase(http_errors_total[1h]), - latency: histogram_quantile(0.95, http_request_duration_seconds) - } - columns: - endpoint: string - requests: number - errors: number - latency: decimal - -mapping: - endpoint: "row.endpoint" - total_requests: "row.requests" - error_rate_percent: "(row.errors / row.requests) * 100" - avg_latency_ms: "row.latency * 1000" -``` - -## Comparison with Other Numeric Types - -| Type | Use Case | -|------|----------| -| `number` | General numeric values (counts, ratios, metrics) | -| `decimal` | Precise floating-point values (costs, percentages) | -| `gauge` | Percentage or 0-100 values with visual gauge | -| `bytes` | Binary storage sizes (auto-formatted as KB, MB, GB) | -| `millicore` | CPU resources in millicores | - -## Best Practices - -1. **Use appropriate precision** - Don't display unnecessary decimal places - ```yaml - - name: replica_count - type: number - precision: 0 # No decimals needed for counts - ``` - -2. **Add meaningful units** - Help users understand what they're viewing - ```yaml - - name: memory_mb - type: number - unit: "MB" - ``` - -3. **Validate ranges** - Consider using `gauge` for percentage-like values - ```yaml - - name: health_score # 0-100 - type: gauge # Better than number - ``` - -4. **Round appropriately** - Avoid very large or very small numbers - ```yaml - mapping: - # ✓ Round to reasonable precision - cpu_cores: "round(row.cpu_millis / 1000, 2)" - - # ✗ Too many decimals - cpu_cores: "row.cpu_millis / 1000" - ``` - -5. **Use negative values carefully** - Number can display negatives but document them - ```yaml - columns: - - name: balance_change - type: number - description: "Positive = increase, Negative = decrease" - ``` - -## Performance Considerations - -- Numeric columns are very efficient -- Numeric filtering can be optimized with database indexes -- Avoid complex calculations for large datasets -- Consider pre-calculating values in queries when possible - -## Null and Zero Handling +| `unit` | string | Display unit (e.g., "pods", "req/s") | -Numbers default to 0 if null. Use CEL expressions to handle special cases: +## Example -```yaml -mapping: - # ✓ Handle null values - count: "has(row.count) ? row.count : 0" +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {115-119} - # Display different text for zero - status_text: "row.count == 0 ? 'No items' : string(row.count) + ' items'" ``` diff --git a/mission-control/docs/guide/views/table/status.md b/mission-control/docs/guide/views/table/status.md index 59f93656..77eeee80 100644 --- a/mission-control/docs/guide/views/table/status.md +++ b/mission-control/docs/guide/views/table/status.md @@ -4,421 +4,10 @@ sidebar_custom_props: icon: mdi:list-status --- -The `status` column type displays custom status badges for any status values. Unlike `health` which is limited to three states, `status` supports any custom status string. +The `status` column type displays status values with appropriate styling. Common values include `Running`, `Pending`, `Failed`, `Succeeded`, etc. -## Basic Usage +## Example -```yaml -columns: - - name: pod_status - type: status -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"status"` | -| `description` | string | Help text for column | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Direct Status Property - -```yaml -columns: - - name: status - type: status - -mapping: - status: "row.status" -``` - -### Status from Custom Field - -```yaml -columns: - - name: deployment_status - type: status - -mapping: - deployment_status: "row.properties.deployment_state" -``` - -### Status from Condition - -```yaml -columns: - - name: build_status - type: status - -mapping: - build_status: "row.properties.result == 0 ? 'success' : 'failed'" -``` - -## Common Patterns - -### Kubernetes Pod States -```yaml -mapping: - status: "row.status" # pending, running, succeeded, failed, unknown -``` - -### Build/Deployment States -```yaml -mapping: - status: "row.properties.state" # created, running, succeeded, failed, cancelled -``` - -### Replica States -```yaml -mapping: - status: "row.desired == row.ready ? 'ready' : row.ready > 0 ? 'updating' : 'not-ready'" -``` - -### Custom Status Values -```yaml -mapping: - status: "row.properties.status" # Can be any string -``` - -## Real-World Examples - -### Pod Status Display -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: status - type: status - description: "Current pod state" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - status: "row.status" # pending, running, succeeded, failed, unknown -``` - -### Build Pipeline Status -```yaml -columns: - - name: build_id - type: string - primaryKey: true - - - name: status - type: status - description: "Build state" - - - name: stage - type: status - description: "Current stage" - -queries: - builds: - configs: - types: ["CI::Build"] - -mapping: - build_id: "row.id" - status: "row.properties.state" # created, queued, running, succeeded, failed - stage: "row.properties.current_stage" # build, test, deploy -``` - -### Deployment Rollout Status -```yaml -columns: - - name: deployment - type: string - primaryKey: true - - - name: status - type: status - description: "Rollout status" - - - name: desired_replicas - type: number - - - name: ready_replicas - type: number - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment: "row.name" - status: "row.desired == row.ready ? 'ready' : row.ready > 0 ? 'updating' : 'pending'" - desired_replicas: "row.properties.spec.replicas" - ready_replicas: "row.properties.status.readyReplicas" -``` - -### Database Migration Status -```yaml -columns: - - name: migration_id - type: string - primaryKey: true - - - name: database - type: string - - - name: status - type: status - description: "Migration state" - -queries: - migrations: - configs: - types: ["Database::Migration"] - -mapping: - migration_id: "row.id" - database: "row.properties.database_name" - status: "row.properties.state" # pending, running, succeeded, failed, rolled_back -``` - -### Job Execution Status -```yaml -columns: - - name: job_id - type: string - primaryKey: true +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {20-24} - - name: job_name - type: string - - - name: status - type: status - description: "Job execution status" - - - name: attempt - type: number - -queries: - jobs: - configs: - types: ["Job::Run"] - -mapping: - job_id: "row.id" - job_name: "row.name" - status: "row.properties.execution_status" # pending, running, succeeded, failed, skipped - attempt: "row.properties.attempt_number" -``` - -## Complex Status Logic - -### Multi-Step Status Determination -```yaml -columns: - - name: resource - type: string - primaryKey: true - - - name: status - type: status - -mapping: - status: " - row.properties.state == 'error' ? 'error' : - row.properties.state == 'pending' ? 'pending' : - !row.properties.is_configured ? 'not-configured' : - !row.properties.is_healthy ? 'degraded' : - 'ready' - " -``` - -### Status from Resource Type -```yaml -mapping: - status: " - row.type == 'Kubernetes::Pod' ? row.status : - row.type == 'Kubernetes::Deployment' ? (row.desired == row.ready ? 'ready' : 'updating') : - row.type == 'Kubernetes::Node' ? (row.is_ready ? 'ready' : 'not-ready') : - 'unknown' - " -``` - -## Status Filtering - -Enable users to filter by status values: - -```yaml -columns: - - name: status - type: status - filter: - type: "multiselect" - -mapping: - status: "row.status" ``` - -Users can then filter to show: -- All statuses -- Only specific statuses (e.g., only "running" and "pending") -- Combinations of statuses - -## Status Values by Resource Type - -### Kubernetes Pod Status -- `pending` - Waiting for resources -- `running` - Pod is executing -- `succeeded` - Completed successfully -- `failed` - Execution failed -- `unknown` - Status unknown - -### Kubernetes Deployment Status -- `progressing` - Rolling out new version -- `available` - Deployment is available -- `replicas-failure` - Replica creation failed - -### CI/CD Pipeline Status -- `created` - Job created -- `queued` - Waiting to run -- `running` - Currently executing -- `succeeded` - Completed successfully -- `failed` - Failed to complete -- `cancelled` - Manually cancelled -- `skipped` - Skipped (conditional) - -### Database/Data Status -- `pending` - Waiting to start -- `running` - Currently executing -- `succeeded` - Completed -- `failed` - Failed -- `cancelled` - Cancelled -- `rolled_back` - Rolled back - -## Status Display - -Status values display as badges with: -- **Status text** - The status value itself -- **Color coding** - Varies by platform, typically: - - Green: success, succeeded, running, ready - - Yellow: warning, pending, updating, degraded - - Red: failed, error, critical - - Gray: unknown, cancelled, skipped - -## Best Practices - -1. **Use consistent naming** - Keep status values consistent across resources - ```yaml - # ✓ Consistent - succeeded/failed/pending - - # ✗ Inconsistent - success/fail/wait - ``` - -2. **Document possible values** - List all possible status values in descriptions - ```yaml - - name: status - type: status - description: "Can be: pending, running, succeeded, failed, unknown" - ``` - -3. **Keep values lowercase** - Use lowercase status values for consistency - ```yaml - # ✓ Good - status: "row.properties.state.toLowerCase()" - - # ✗ Inconsistent case - status: "row.properties.state" - ``` - -4. **Combine with details** - Show status alongside relevant information - ```yaml - - name: status - type: status - - name: reason - type: string # Why it has this status - - name: since - type: datetime # When it changed - ``` - -5. **Filter for investigation** - Enable filtering for troubleshooting - ```yaml - - name: status - type: status - filter: - type: "multiselect" - ``` - -## Comparison with Other Status Types - -| Type | Use Case | -|------|----------| -| `status` | Custom multi-value statuses (pending, running, failed, etc.) | -| `health` | Three-state operational health (healthy/warning/critical) | -| `boolean` | Binary true/false states | - -Use `status` for workflow states, execution states, or anything with 4+ possible values. Use `health` for operational health. Use `boolean` for simple on/off states. - -## Performance Considerations - -- Status columns are very efficient to display and filter -- Status filtering is optimized for common status values -- No performance overhead for status expressions - -## Status vs Health - -**Health** answers "Is this healthy?" (healthy/warning/critical) -**Status** answers "What is the current state?" (pending/running/failed/succeeded) - -Example: -- A pod with status `running` might have health `critical` (not enough resources) -- A pod with status `pending` might have health `warning` (taking a while to start) -- A pod with status `succeeded` has health `healthy` (completed successfully) - -You can use both together for complete information. - -## Practical Example: Multi-Status View - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: pod_status - type: status - description: "Kubernetes pod state" - - - name: health - type: health - description: "Resource health" - - - name: reason - type: string - description: "Status reason" - - - name: since - type: datetime - description: "When status changed" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - pod_status: "row.status" # pending, running, succeeded, failed - health: "row.health" # healthy, warning, critical - reason: "row.properties.status.reason" - since: "row.properties.status.lastTransitionTime" -``` - -This provides complete visibility into both the current state and the health of the resource. diff --git a/mission-control/docs/guide/views/table/string.md b/mission-control/docs/guide/views/table/string.md index 84c9e898..a628fcbb 100644 --- a/mission-control/docs/guide/views/table/string.md +++ b/mission-control/docs/guide/views/table/string.md @@ -4,311 +4,10 @@ sidebar_custom_props: icon: mdi:format-text --- -The `string` column type displays text values as a simple text field in the table. +The `string` column type displays text values. -## Basic Usage +## Example -```yaml -columns: - - name: pod_name - type: string - primaryKey: true -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"string"` | -| `description` | string | Help text for column | -| `primaryKey` | boolean | Is this part of the unique identifier? | -| `hidden` | boolean | Hide column from UI | -| `unit` | string | Display unit suffix (e.g., "ms") | -| `filter` | object | Enable filtering on this column | -| `card` | object | Configure card layout position | - -## Example Usage - -### Simple Text Display - -```yaml -columns: - - name: name - type: string - primaryKey: true - -queries: - resources: - configs: - types: ["Kubernetes::Pod"] - -mapping: - name: "row.name" -``` - -### String with Description - -```yaml -columns: - - name: region - type: string - description: "AWS region" +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {18-19} -mapping: - region: "row.properties.region" ``` - -### String with Filtering - -Enable users to filter by string values: - -```yaml -columns: - - name: environment - type: string - filter: - type: "text" - -mapping: - environment: "row.properties.environment" -``` - -### String with Unit Display - -```yaml -columns: - - name: version - type: string - unit: "v" # Displays as "v1.25" - -mapping: - version: "row.properties.kubernetes_version" -``` - -### Composite Strings from Expressions - -Use CEL expressions to create formatted strings: - -```yaml -columns: - - name: display_name - type: string - primaryKey: true - -mapping: - display_name: "'Pod: ' + row.name + ' (' + row.namespace + ')'" -``` - -## Common Patterns - -### Display Config Item Type -```yaml -mapping: - type: "row.type" -``` - -### Namespace Display -```yaml -mapping: - namespace: "row.namespace" -``` - -### Custom Property -```yaml -mapping: - image: "row.properties.container_image" -``` - -### Formatted Status Message -```yaml -mapping: - message: "row.health == 'healthy' ? 'OK' : 'Check required'" -``` - -## Filtering - -When you add filter configuration, users can: -- Search for text values -- Filter by exact match -- Filter by partial match (if supported) - -```yaml -columns: - - name: pod_name - type: string - filter: - type: "text" - - - name: label - type: string - filter: - type: "multiselect" # Users can select multiple values -``` - -## String Mapping Examples - -### Simple Direct Mapping -```yaml -mapping: - name: "row.name" -``` - -### Concatenation -```yaml -mapping: - full_location: "row.region + '/' + row.zone" -``` - -### Conditional Values -```yaml -mapping: - status_text: "row.status == 'running' ? 'Active' : 'Inactive'" -``` - -### Extracted from Properties -```yaml -mapping: - owner: "row.properties.owner_email" -``` - -### Optional String with Default -```yaml -mapping: - description: "has(row.properties.description) ? row.properties.description : 'No description'" -``` - -## Real-World Examples - -### Pod Details View -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: namespace - type: string - - - name: node - type: string - - - name: image - type: string - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - namespace: "row.namespace" - node: "row.properties.node_name" - image: "row.properties.container_image" -``` - -### AWS Resource Labels -```yaml -columns: - - name: instance_id - type: string - primaryKey: true - - - name: instance_type - type: string - - - name: subnet_id - type: string - - - name: availability_zone - type: string - -queries: - instances: - configs: - types: ["AWS::EC2Instance"] - -mapping: - instance_id: "row.name" - instance_type: "row.properties.instance_type" - subnet_id: "row.properties.subnet_id" - availability_zone: "row.properties.availability_zone" -``` - -### Deployment Configuration -```yaml -columns: - - name: deployment_name - type: string - primaryKey: true - - - name: replicas_config - type: string - description: "Configured replicas" - - - name: image_registry - type: string - description: "Container image registry" - -queries: - deployments: - configs: - types: ["Kubernetes::Deployment"] - -mapping: - deployment_name: "row.name" - replicas_config: "string(row.properties.spec.replicas)" - image_registry: "row.properties.spec.containers[0].image" -``` - -## Best Practices - -1. **Use primaryKey for identifiers** - Make the primary identifier string a primaryKey - ```yaml - - name: id - type: string - primaryKey: true - ``` - -2. **Provide descriptions for clarity** - Help users understand what each string represents - ```yaml - - name: region - type: string - description: "AWS region identifier" - ``` - -3. **Consistent formatting** - Use CEL expressions for consistent formatting - ```yaml - mapping: - created_date: "row.created_at.format('2006-01-02')" - ``` - -4. **Hide internal IDs** - Mark non-user-friendly identifiers as hidden - ```yaml - - name: config_id - type: string - hidden: true - primaryKey: true - ``` - -5. **Use units for clarity** - Add units when values have implicit meaning - ```yaml - - name: version - type: string - unit: "v" - ``` - -## Performance Considerations - -- String columns are very fast - use freely -- String filtering can be slower with large datasets -- Consider limiting results with `limit` in queries -- Use `hidden: true` for primaryKey fields not needed in UI - -## String Length - -By default, strings are not truncated. Long strings will wrap or scroll in the table. Consider: -- Using descriptions instead of long content -- Storing long content in a separate detail view -- Truncating in mapping: `row.name.substring(0, 50)` diff --git a/mission-control/docs/guide/views/table/url.md b/mission-control/docs/guide/views/table/url.md index fe425f34..954e59b1 100644 --- a/mission-control/docs/guide/views/table/url.md +++ b/mission-control/docs/guide/views/table/url.md @@ -4,515 +4,28 @@ sidebar_custom_props: icon: mdi:link --- -The `url` column type displays clickable links. Links can point to external URLs, other views, or configuration items. URLs can be parameterized with row data for dynamic linking. - -## Basic Usage - -```yaml -columns: - - name: dashboard_link - type: url - url: - href: "https://example.com" -``` - -## Properties - -| Property | Type | Description | -|----------|------|-------------| -| `name` | string | Column name (used in mapping) | -| `type` | string | Set to `"url"` | -| `description` | string | Help text for column | -| `url` | object | URL configuration | -| `for` | string | Column to use as link text | +The `url` column type displays clickable links to external URLs, other views, or config items. ## URL Configuration ```yaml url: - # External URL - href: "https://example.com/resource" + # External URL (supports row values) + href: "https://grafana.example.com/d/panel?pod=$(row.name)" - # OR internal view link + # OR link to another view view: namespace: "default" - name: "view-name" + name: "pod-details" filter: - param: "value" + pod_id: "row.id" # OR link to config item config: "row.id" ``` -## Example Usage - -### External URL Link - -```yaml -columns: - - name: documentation - type: url - url: - href: "https://docs.example.com" - -mapping: - documentation: "row.name" # Link text -``` - -### Dynamic External URL - -```yaml -columns: - - name: grafana_link - type: url - for: "metric_name" # Use this column as link text - url: - href: "https://grafana.example.com/d/panel?pod=$(row.name)" - -mapping: - metric_name: "row.name" -``` - -### Link to Another View - -```yaml -columns: - - name: details_link - type: url - url: - view: - namespace: "default" - name: "pod-details" - filter: - pod_id: "row.id" - -mapping: - details_link: "row.name" # Link text = pod name -``` - -### Link to Config Item - -```yaml -columns: - - name: config_link - type: url - for: "resource_name" # Show resource name as link text - url: - config: "row.id" # Link to config by ID - -mapping: - resource_name: "row.name" -``` - -## Common Patterns - -### External Service Links -```yaml -columns: - - name: service_url - type: url - for: "service_name" - url: - href: "https://$(row.domain)/service/$(row.service_id)" - -mapping: - service_name: "row.name" -``` - -### Monitoring Dashboard Links -```yaml -columns: - - name: metrics_dashboard - type: url - for: "pod_name" - url: - href: "https://prometheus.example.com/graph?expr=pod_metrics%7Bpod%3D%22$(row.name)%22%7D" - -mapping: - pod_name: "row.name" -``` - -### Log Aggregation Links -```yaml -columns: - - name: logs_link - type: url - for: "pod_name" - url: - href: "https://logs.example.com/search?q=pod:$(row.name)" - -mapping: - pod_name: "row.name" -``` - -### View Navigation -```yaml -columns: - - name: pod_details - type: url - url: - view: - namespace: "default" - name: "pod-details" - filter: - pod_id: "row.id" - cluster: "$(var.cluster)" # Use variables too - -mapping: - pod_details: "row.name" -``` - -## Real-World Examples - -### Kubernetes Pod Dashboard Links -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: logs_link - type: url - for: "pod_name" - description: "View pod logs" - url: - href: "https://logs.example.com/search?pod=$(row.name)&namespace=$(row.namespace)" - - - name: metrics_link - type: url - for: "pod_name" - description: "View metrics" - url: - href: "https://metrics.example.com/dashboard?pod=$(row.name)" - - - name: pod_config - type: url - for: "pod_name" - description: "View config details" - url: - config: "row.id" - -queries: - pods: - configs: - types: ["Kubernetes::Pod"] - -mapping: - pod_name: "row.name" - logs_link: "row.name" - metrics_link: "row.name" - pod_config: "row.name" -``` - -### AWS Resource Links -```yaml -columns: - - name: instance_id - type: string - primaryKey: true - - - name: aws_console_link - type: url - for: "instance_id" - description: "Open in AWS Console" - url: - href: "https://console.aws.amazon.com/ec2/v2/home#Instances:instanceId=$(row.instance_id)" - - - name: cloudwatch_metrics - type: url - for: "instance_id" - description: "CloudWatch Metrics" - url: - href: "https://console.aws.amazon.com/cloudwatch/home#metricsV2:graph=~();query=$(row.instance_id)" - -queries: - instances: - configs: - types: ["AWS::EC2Instance"] - -mapping: - instance_id: "row.name" - aws_console_link: "row.name" - cloudwatch_metrics: "row.name" -``` - -### Application Links -```yaml -columns: - - name: app_name - type: string - primaryKey: true - - - name: production_url - type: url - for: "app_name" - description: "Open production app" - url: - href: "https://$(row.production_domain)/$(row.app_id)" - - - name: staging_url - type: url - for: "app_name" - description: "Open staging app" - url: - href: "https://staging-$(row.production_domain)/$(row.app_id)" - - - name: git_repository - type: url - for: "app_name" - description: "View source code" - url: - href: "$(row.git_repo_url)" +## Example -queries: - apps: - configs: - types: ["Application::Service"] +```yaml title="deployments.yaml" file=/modules/mission-control/fixtures/views/deployments.yaml {37-39} -mapping: - app_name: "row.name" - production_url: "row.name" - staging_url: "row.name" - git_repository: "row.name" ``` - -### Incident Response Links -```yaml -columns: - - name: incident_id - type: string - primaryKey: true - - - name: related_configs - type: url - for: "incident_id" - description: "View affected resources" - url: - view: - namespace: "default" - name: "incident-resources" - filter: - incident_id: "row.id" - - - name: incident_timeline - type: url - for: "incident_id" - description: "View timeline" - url: - view: - namespace: "default" - name: "incident-timeline" - filter: - incident_id: "row.id" - - - name: external_issue_tracker - type: url - for: "incident_id" - description: "View in Jira" - url: - href: "https://jira.example.com/browse/INC-$(row.id)" - -queries: - incidents: - configs: - types: ["Incident::Report"] - -mapping: - incident_id: "row.id" - related_configs: "row.id" - incident_timeline: "row.id" - external_issue_tracker: "row.id" -``` - -## URL Syntax - -### Static URLs -```yaml -url: - href: "https://example.com/resource" -``` - -### Dynamic URLs with Row Data -```yaml -url: - href: "https://example.com/search?q=$(row.name)&id=$(row.id)" -``` - -### URLs with Variables -```yaml -url: - href: "https://example.com/cluster/$(var.cluster)/pod/$(row.name)" -``` - -### Internal View Links -```yaml -url: - view: - namespace: "default" - name: "view-name" - filter: - param: "value" -``` - -## Link Text - -The link text (what users see and click) comes from: - -1. **`for` property** - Use specified column as text - ```yaml - - name: link_column - type: url - for: "name_column" # Use name_column as link text - url: { ... } - ``` - -2. **Mapping value** - Use mapped value as text - ```yaml - mapping: - link: "row.name" # Show name as link text - ``` - -3. **Default** - Shows the URL itself if not specified - -## Internal View Links - -Link to other views with optional filters: - -```yaml -url: - view: - namespace: "default" # View namespace - name: "pod-details" # View name - filter: # Optional parameters - pod_id: "row.id" - cluster: "us-east-1" -``` - -Users clicking the link navigate to the specified view with filters applied. - -## Configuration Item Links - -Link directly to configuration item detail pages: - -```yaml -url: - config: "row.id" # Links to config detail page -``` - -## Real URL Parameters Example - -```yaml -columns: - - name: pod_name - type: string - primaryKey: true - - - name: logs - type: url - for: "pod_name" - url: - # This creates clickable pod names linking to logs - href: "https://logs.company.com/pods?name=$(row.name)&ns=$(row.namespace)" - -mapping: - pod_name: "row.name" -``` - -When rendered: -- Users see the pod name as a blue link -- Clicking takes them to logs.company.com with pod name and namespace in query params - -## Best Practices - -1. **Use meaningful link text** - Show what the link is about - ```yaml - # ✓ Clear what the link does - for: "pod_name" - - # ✗ Generic link text - for: "link" - ``` - -2. **Add descriptions** - Explain link purpose - ```yaml - - name: logs_link - type: url - description: "View pod logs in Datadog" - ``` - -3. **Use HTTPS** - Always use secure URLs - ```yaml - # ✓ Secure - href: "https://example.com" - - # ✗ Insecure - href: "http://example.com" - ``` - -4. **Parameterize URLs** - Make links dynamic - ```yaml - # ✓ Dynamic for each row - href: "https://example.com?pod=$(row.name)" - - # ✗ Static, same for all rows - href: "https://example.com?pod=my-pod" - ``` - -5. **Test links** - Verify they work before deploying - - Check URL formatting - - Verify query parameters - - Test with sample data - -## Escaping Special Characters - -In URLs, some characters need escaping: - -```yaml -# Space: %20 -href: "https://example.com?q=$(row.name)%20extra" - -# ? -href: "https://example.com?param1=value¶m2=value" - -# # -href: "https://example.com#section" -``` - -## URL Encoding Example - -```yaml -# Properly encoded URL with spaces and special chars -url: - href: "https://logs.example.com/search?query=$(urlEncode(row.name))&time=1h" -``` - -## Performance Considerations - -- URL columns are very efficient -- Link rendering has minimal overhead -- No performance impact on views with many links - -## Comparison with Other Link Types - -| Type | Use Case | -|------|----------| -| `url` | External links or custom URLs | -| `config_item` | Links to configuration detail page | - -Use `url` for external sites (logs, monitoring, etc.). Use `config_item` to link to Mission Control config pages. - -## Security Considerations - -- Always validate URL sources -- Use HTTPS for sensitive data -- Avoid exposing sensitive parameters in URLs -- Consider URL encoding for user-supplied data - -## Open Link Behavior - -By default, links: -- Open in a new browser tab/window -- Preserve the parent view -- Allow back navigation - -This can usually be configured at the platform level. From 430c017d7cf833d9f7e009cef5ad459590b77f75 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Wed, 3 Dec 2025 22:55:42 +0545 Subject: [PATCH 4/8] chore: updates --- mission-control-chart | 2 +- .../views/queries/view-table-selector.md | 9 ------ .../docs/guide/views/table/boolean.md | 13 -------- .../docs/guide/views/table/duration.md | 2 +- mission-control/docs/guide/views/table/url.md | 31 ------------------- modules/canary-checker | 2 +- modules/config-db | 2 +- modules/duty | 2 +- modules/mission-control | 2 +- modules/mission-control-chart | 2 +- modules/mission-control-registry | 2 +- 11 files changed, 8 insertions(+), 61 deletions(-) delete mode 100644 mission-control/docs/guide/views/table/boolean.md delete mode 100644 mission-control/docs/guide/views/table/url.md diff --git a/mission-control-chart b/mission-control-chart index 3710fad5..f57f3876 160000 --- a/mission-control-chart +++ b/mission-control-chart @@ -1 +1 @@ -Subproject commit 3710fad5bb8408aaf37129f0272d7aa4da1f3c77 +Subproject commit f57f387623c5137d4be3d33af655a1437f63f7d4 diff --git a/mission-control/docs/guide/views/queries/view-table-selector.md b/mission-control/docs/guide/views/queries/view-table-selector.md index 4ee21eac..e2b8d4a5 100644 --- a/mission-control/docs/guide/views/queries/view-table-selector.md +++ b/mission-control/docs/guide/views/queries/view-table-selector.md @@ -343,14 +343,6 @@ spec: type: status - name: health type: health - - name: details_link - type: url - url: - view: - namespace: default - name: resource-details - filter: - resource_id: 'row.resource_id' queries: data: @@ -365,7 +357,6 @@ spec: name: 'row.name' status: 'row.status' health: 'row.health' - details_link: 'row.name' ``` ### Composite Metrics View diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/boolean.md deleted file mode 100644 index 2cfb6c5c..00000000 --- a/mission-control/docs/guide/views/table/boolean.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Boolean -sidebar_custom_props: - icon: mdi:checkbox-marked-outline ---- - -The `boolean` column type displays true/false values as checkboxes or text labels. - -## Example - -```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {11-31} - -``` diff --git a/mission-control/docs/guide/views/table/duration.md b/mission-control/docs/guide/views/table/duration.md index d805f2ed..f1982063 100644 --- a/mission-control/docs/guide/views/table/duration.md +++ b/mission-control/docs/guide/views/table/duration.md @@ -4,7 +4,7 @@ sidebar_custom_props: icon: mdi:timer-outline --- -The `duration` column type displays time spans in human-readable format (e.g., "2h 30m", "1d"). +The `duration` column type displays time spans in human-readable format (e.g., "2h 30m", "1d"). The value is expected in nanoseconds. ## Example diff --git a/mission-control/docs/guide/views/table/url.md b/mission-control/docs/guide/views/table/url.md deleted file mode 100644 index 954e59b1..00000000 --- a/mission-control/docs/guide/views/table/url.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: URL -sidebar_custom_props: - icon: mdi:link ---- - -The `url` column type displays clickable links to external URLs, other views, or config items. - -## URL Configuration - -```yaml -url: - # External URL (supports row values) - href: "https://grafana.example.com/d/panel?pod=$(row.name)" - - # OR link to another view - view: - namespace: "default" - name: "pod-details" - filter: - pod_id: "row.id" - - # OR link to config item - config: "row.id" -``` - -## Example - -```yaml title="deployments.yaml" file=/modules/mission-control/fixtures/views/deployments.yaml {37-39} - -``` diff --git a/modules/canary-checker b/modules/canary-checker index 1df9e0d7..ed38050d 160000 --- a/modules/canary-checker +++ b/modules/canary-checker @@ -1 +1 @@ -Subproject commit 1df9e0d7e9eac5e8ecf89535d08029ec05351544 +Subproject commit ed38050dc7e235b75879366248554587b3470425 diff --git a/modules/config-db b/modules/config-db index 218a9c93..b831a7b5 160000 --- a/modules/config-db +++ b/modules/config-db @@ -1 +1 @@ -Subproject commit 218a9c93278ab274329912ecda3037db39d95f23 +Subproject commit b831a7b5fbe36b3925da6cf43216632cd9e0bee6 diff --git a/modules/duty b/modules/duty index bb543d7d..436114ba 160000 --- a/modules/duty +++ b/modules/duty @@ -1 +1 @@ -Subproject commit bb543d7d69591e14e58f4ad8505658524448e4d2 +Subproject commit 436114ba6e4710286a28e3819e3f5d84d0f038cf diff --git a/modules/mission-control b/modules/mission-control index 6bbd14cf..594221f4 160000 --- a/modules/mission-control +++ b/modules/mission-control @@ -1 +1 @@ -Subproject commit 6bbd14cfb180c52b8d6087000c75fb132551dd4e +Subproject commit 594221f4cc0d66a7d0a047137992c70ea234ce29 diff --git a/modules/mission-control-chart b/modules/mission-control-chart index 0a7c6f0d..f57f3876 160000 --- a/modules/mission-control-chart +++ b/modules/mission-control-chart @@ -1 +1 @@ -Subproject commit 0a7c6f0d20711126e61a2812f5a77806988d75bd +Subproject commit f57f387623c5137d4be3d33af655a1437f63f7d4 diff --git a/modules/mission-control-registry b/modules/mission-control-registry index d2833707..7cb49b3a 160000 --- a/modules/mission-control-registry +++ b/modules/mission-control-registry @@ -1 +1 @@ -Subproject commit d28337071d1fcad5f22401f66dc170e513dfc0d2 +Subproject commit 7cb49b3aa464410b76323b924b716f9c07f4360c From 2132fbdcd7b0bbbd08cf93a6452f13001cc8c0d9 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Thu, 4 Dec 2025 10:53:30 +0545 Subject: [PATCH 5/8] updated docs --- mission-control-chart | 2 +- mission-control/docs/guide/views/index.md | 19 + .../docs/guide/views/panels/bargauge.md | 34 +- .../docs/guide/views/panels/duration.md | 2 +- .../docs/guide/views/panels/gauge.md | 3 +- .../docs/guide/views/panels/index.mdx | 1 + .../docs/guide/views/panels/number.md | 4 +- .../docs/guide/views/panels/piechart.md | 4 +- .../docs/guide/views/panels/table.md | 4 +- .../docs/guide/views/panels/text.md | 19 + .../docs/guide/views/queries/sql.md | 33 + .../views/queries/view-table-selector.md | 581 +----------------- .../docs/guide/views/table/boolean.md | 15 + .../docs/guide/views/table/config-item.md | 4 +- .../docs/guide/views/table/index.mdx | 5 +- .../docs/guide/views/table/labels.md | 19 + .../docs/guide/views/table/millicore.md | 12 +- .../docs/guide/views/table/number.md | 2 +- .../docs/reference/views/_view.mdx | 231 ++++++- modules/canary-checker | 2 +- modules/config-db | 2 +- modules/duty | 2 +- modules/mission-control | 2 +- modules/mission-control-chart | 2 +- modules/mission-control-registry | 2 +- 25 files changed, 393 insertions(+), 613 deletions(-) create mode 100644 mission-control/docs/guide/views/panels/text.md create mode 100644 mission-control/docs/guide/views/queries/sql.md create mode 100644 mission-control/docs/guide/views/table/boolean.md create mode 100644 mission-control/docs/guide/views/table/labels.md diff --git a/mission-control-chart b/mission-control-chart index f57f3876..c53bd62b 160000 --- a/mission-control-chart +++ b/mission-control-chart @@ -1 +1 @@ -Subproject commit f57f387623c5137d4be3d33af655a1437f63f7d4 +Subproject commit c53bd62b539b63059121bd096b8262ec3773cfbb diff --git a/mission-control/docs/guide/views/index.md b/mission-control/docs/guide/views/index.md index be51452a..7fcfc3e9 100644 --- a/mission-control/docs/guide/views/index.md +++ b/mission-control/docs/guide/views/index.md @@ -20,6 +20,7 @@ Views serve as a powerful data aggregation and visualization layer in Mission Co - **Support templating** with variables that users can adjust to dynamically filter and update the view - **Cache results** intelligently to balance data freshness with performance - **Transform data** using expressions to map raw query results to meaningful display columns +- **Embed views** inside config item pages or assemble multiple views on one page with sections ## Key Features @@ -30,6 +31,8 @@ Views can query data from multiple sources: - **Config Items**: Infrastructure components and configurations via the `configs` selector - **Changes**: Configuration change tracking and audit data via the `changes` selector - **Metrics**: Time-series data from Prometheus using PromQL queries +- **SQL**: Direct SQL queries via stored connections (PostgreSQL, MySQL, SQL Server) +- **Other Views**: Reuse cached tables from existing views with `viewTableSelector` ### Output Types @@ -84,6 +87,22 @@ panels: This SQL-first approach gives you unlimited flexibility to slice, filter, and aggregate your data. +### Compose Pages with Sections + +Use `spec.sections` to render multiple views together. Mission Control aggregates their variables and shows a single filter bar for all sections. + +```yaml title="workload-overview.yaml" file=/modules/mission-control/fixtures/views/workload-overview.yaml {6-24} + +``` + +### Attach Views to Config Tabs + +`display.plugins` lets you place a view as a tab on matching config items. Variables can be templated from the config to scope the view automatically. + +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {66-76} + +``` + ## API Reference diff --git a/mission-control/docs/guide/views/panels/bargauge.md b/mission-control/docs/guide/views/panels/bargauge.md index 3bf475eb..d6988c27 100644 --- a/mission-control/docs/guide/views/panels/bargauge.md +++ b/mission-control/docs/guide/views/panels/bargauge.md @@ -8,31 +8,31 @@ The `bargauge` panel displays multiple values as horizontal bars with configurab ## Properties -| Property | Type | Description | -|----------|------|-------------| -| `min` | string | Minimum value (can be a number or CEL expression) | -| `max` | string | Maximum value (can be a number or CEL expression) | -| `precision` | int | Decimal places to display | -| `unit` | string | Unit label (e.g., "%", "bytes") | -| `group` | string | Field to group bars by | -| `format` | string | Display format: `percentage` or `multiplier` | -| `thresholds` | array | Color thresholds based on percentage | +| Property | Type | Description | +| ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `min` | string | Minimum value (can be a number or CEL expression) | +| `max` | string | Maximum value (can be a number or CEL expression) | +| `precision` | int | Decimal places to display | +| `unit` | string | Unit label (e.g., "%", "bytes") | +| `group` | string | Name of a group. When multiple bargauges have the same group, they are placed together. This is useful when each bar needs different properties. | +| `format` | string | Display format: `percentage` or `multiplier` | +| `thresholds` | array | Color thresholds based on percentage | ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `value` | number | The numeric value for each bar (required) | -| `name` | string | Label for each bar (required, or any other column will be used as label) | +| Column | Type | Description | +| ---------------------------------- | ------ | ------------------------------------- | +| `value` | number | Numeric value for each bar (required) | +| `name` or first non-`value` column | string | Bar label (required) | ## Thresholds Thresholds define colors at percentage breakpoints: -| Property | Type | Description | -|----------|------|-------------| -| `percent` | int | Percentage at which this threshold applies | -| `color` | string | Color name or hex code (e.g., "#10b981") | +| Property | Type | Description | +| --------- | ------ | ------------------------------------------ | +| `percent` | int | Percentage at which this threshold applies | +| `color` | string | Color name or hex code (e.g., "#10b981") | ## Example diff --git a/mission-control/docs/guide/views/panels/duration.md b/mission-control/docs/guide/views/panels/duration.md index 03180ff0..995467c5 100644 --- a/mission-control/docs/guide/views/panels/duration.md +++ b/mission-control/docs/guide/views/panels/duration.md @@ -11,7 +11,7 @@ The `duration` panel displays time duration values in a human-readable format (e | Column | Type | Description | |--------|------|-------------| | `value` | number | Duration in **nanoseconds** (required) | -| `label` | string | Label for the panel (optional, defaults to panel name) | +| `label` | string | Optional per-row label (defaults to the panel name) | ## Example diff --git a/mission-control/docs/guide/views/panels/gauge.md b/mission-control/docs/guide/views/panels/gauge.md index e00b9964..48ff2d7e 100644 --- a/mission-control/docs/guide/views/panels/gauge.md +++ b/mission-control/docs/guide/views/panels/gauge.md @@ -20,7 +20,8 @@ The `gauge` panel displays a single numeric value as a visual gauge with configu | Column | Type | Description | |--------|------|-------------| -| `value` | number | The numeric value to display on the gauge (required) | +| `value` | number | Numeric value to display (required) | +| `label` | string | Optional label; the panel title is used when omitted | ## Thresholds diff --git a/mission-control/docs/guide/views/panels/index.mdx b/mission-control/docs/guide/views/panels/index.mdx index 977075ee..04316d4f 100644 --- a/mission-control/docs/guide/views/panels/index.mdx +++ b/mission-control/docs/guide/views/panels/index.mdx @@ -29,6 +29,7 @@ All panel types support these properties: | `description` | string | Optional description | | `type` | string | Panel type (required) | | `query` | string | SQL query against view data (required) | +| `gauge`, `number`, `piechart`, `bargauge`, `timeseries` | object | Type-specific options | ## Panel Types diff --git a/mission-control/docs/guide/views/panels/number.md b/mission-control/docs/guide/views/panels/number.md index f9bceedb..73b21400 100644 --- a/mission-control/docs/guide/views/panels/number.md +++ b/mission-control/docs/guide/views/panels/number.md @@ -17,8 +17,8 @@ The `number` panel displays a single numeric value with optional unit formatting | Column | Type | Description | |--------|------|-------------| -| `value` or `count` | number | The numeric value to display (required) | -| `label` | string | Label for the panel (optional, defaults to panel name) | +| `value` or `count` | number | Numeric value to display (required) | +| `label` | string | Optional per-row label (defaults to the panel name) | ## Example diff --git a/mission-control/docs/guide/views/panels/piechart.md b/mission-control/docs/guide/views/panels/piechart.md index 0706aa12..668f315d 100644 --- a/mission-control/docs/guide/views/panels/piechart.md +++ b/mission-control/docs/guide/views/panels/piechart.md @@ -17,8 +17,8 @@ The `piechart` panel displays data distribution as a pie chart with customizable | Column | Type | Description | |--------|------|-------------| -| `count` | number | The size of each pie slice (required) | -| Any other column | string | Used as the label for each slice (e.g., `health`, `status`) | +| `count` | number | Size of each slice (required) | +| First non-`count` column | string | Slice label (e.g., `health`, `status`) | ## Colors diff --git a/mission-control/docs/guide/views/panels/table.md b/mission-control/docs/guide/views/panels/table.md index b0ee1bd1..c17b7f31 100644 --- a/mission-control/docs/guide/views/panels/table.md +++ b/mission-control/docs/guide/views/panels/table.md @@ -10,8 +10,8 @@ The `table` panel displays query results as a simple key-value list. It has no a | Column | Type | Description | |--------|------|-------------| -| `value` | any | The value displayed on the right side (required) | -| Any other column | string | Used as the label on the left side | +| `value` | string/number | Value displayed on the right (required) | +| First non-`value` column | string | Label displayed on the left (required) | ## Example diff --git a/mission-control/docs/guide/views/panels/text.md b/mission-control/docs/guide/views/panels/text.md new file mode 100644 index 00000000..1ecb2f35 --- /dev/null +++ b/mission-control/docs/guide/views/panels/text.md @@ -0,0 +1,19 @@ +--- +title: Text +sidebar_custom_props: + icon: mdi:text +--- + +The `text` panel renders free-form text rows. Use it for short notes, callouts, or contextual guidance above the table. + +## Expected Columns + +| Column | Type | Description | +|--------|------|-------------| +| `value` | string | Text to display (required) | + +## Example + +```yaml title="text.yaml" file=/modules/mission-control/fixtures/views/panels/text.yaml + +``` diff --git a/mission-control/docs/guide/views/queries/sql.md b/mission-control/docs/guide/views/queries/sql.md new file mode 100644 index 00000000..50a24fb6 --- /dev/null +++ b/mission-control/docs/guide/views/queries/sql.md @@ -0,0 +1,33 @@ +--- +title: SQL Queries +sidebar_custom_props: + icon: mdi:database +--- + +Use `sql` to run queries against external databases (PostgreSQL, MySQL, or SQL Server) and feed the results into a view. SQL queries share the same templating and mapping capabilities as other data sources. + +## Configuration + +| Field | Description | +| ------------- | ------------------------------------------------------------- | +| `connection` | Name or URL of a stored SQL connection (recommended) | +| `type` | Connection type when not using `connection` (`postgres`, `mysql`, `sqlserver`) | +| `url` | Database DSN/URL (supports env var references) | +| `username` | Database username (supports env var references) | +| `password` | Database password (supports env var references) | +| `query` | SQL statement to execute | + +Mission Control hydrates the connection details before executing the query, so secrets can stay in stored connections or environment variables. + +## Example + +```yaml title="sql-incidents.yaml" file=/modules/mission-control/fixtures/views/sql-incidents.yaml {7-28} + +``` + +## Tips + +- Prefer `connection` to reuse managed credentials instead of embedding URLs and passwords. +- Declare query `columns` and `mapping` to control types when the upstream query could return empty results. +- Use templating to parameterize queries (`$(var.cluster)`) just like other view data sources. +- Keep SQL focused on selection/aggregation; use `merge` to combine SQL results with other data sources. diff --git a/mission-control/docs/guide/views/queries/view-table-selector.md b/mission-control/docs/guide/views/queries/view-table-selector.md index e2b8d4a5..51bbaea2 100644 --- a/mission-control/docs/guide/views/queries/view-table-selector.md +++ b/mission-control/docs/guide/views/queries/view-table-selector.md @@ -4,579 +4,36 @@ sidebar_custom_props: icon: view-details --- -View table selector queries fetch data from other views that have already been cached. This allows you to reuse view data and build composite views without re-querying underlying data sources. +View table selectors reuse cached data from other views instead of hitting the original data sources again. They are ideal for composing dashboards, drilldowns, or summaries on top of existing views. ## Overview -Instead of fetching data directly from configs, metrics, or changes, view table selectors query previously cached view results. This is useful for: - -- Building views on top of other views (composition) -- Reusing expensive query results -- Creating drill-down dashboards -- Reducing database load - -**Example**: - -```yaml -queries: - pod_data: - viewTableSelector: - name: pod-inventory - namespace: default -``` +- Query the materialized Postgres tables generated for other views +- Avoid re-running expensive source queries +- Compose multiple views together or build drill-downs +- Keep formatting and column types consistent with the source view ## Query Properties -| Property | Type | Description | -| ----------- | ------- | ------------------------------------------ | -| `name` | string | Name of the view to query | -| `namespace` | string | Namespace of the view (default: `default`) | -| `filter` | object | Optional: filter rows by column values | -| `limit` | integer | Maximum rows to return | - -## Query Examples - -### Query Another View - -```yaml -queries: - pods: - viewTableSelector: - name: pod-inventory - namespace: default -``` - -Returns all rows from the cached `pod-inventory` view. - -### Filter Results - -```yaml -queries: - prod_pods: - viewTableSelector: - name: pod-inventory - namespace: default - filter: - environment: 'production' - health: 'critical' -``` - -Return rows where environment=production AND health=critical. - -### Limit Results - -```yaml -queries: - top_pods: - viewTableSelector: - name: pod-inventory - namespace: default - limit: 50 -``` - -Return the first 50 rows from the view. - -### Combine Filters and Limits - -```yaml -queries: - recent_changes: - viewTableSelector: - name: change-summary - namespace: monitoring - filter: - severity: 'warning' - resource_type: 'Kubernetes::Deployment' - limit: 100 -``` - -## Using Variables with View Table Selectors - -Make view queries dynamic with templating variables: - -```yaml -templating: - - key: environment - label: 'Environment' - values: ['dev', 'staging', 'prod'] - default: 'prod' - -queries: - data: - viewTableSelector: - name: resource-inventory - filter: - environment: '$(var.environment)' -``` - -## Performance Benefits - -View table selectors are more efficient than re-querying sources: - -| Operation | Time | Data Transfer | -| ----------------------- | ----------- | ------------------ | -| Config query (uncached) | 1-5 seconds | Large | -| Config query (cached) | "< 100ms" | Large | -| View table selector | "< 100ms" | Only filtered rows | - -## Use Cases - -### Drill-Down Dashboards - -Create a hierarchy of views where higher-level views query lower-level views: - -```yaml -# Level 1: Simple pod inventory (queries configs) -kind: View -metadata: - name: pod-inventory -# queries configs directly - ---- -# Level 2: Pod metrics (queries pod-inventory + prometheus) -kind: View -metadata: - name: pod-metrics -queries: - pods: - viewTableSelector: - name: pod-inventory # Query cached pods - - metrics: - prometheus: - query: 'container_memory_usage_bytes' - ---- -# Level 3: Pod troubleshooting (queries pod-metrics) -kind: View -metadata: - name: pod-troubleshoot -queries: - data: - viewTableSelector: - name: pod-metrics # Query cached metrics -``` - -### Filter by Context Variables - -```yaml -# Resource inventory view with namespace filter -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: namespace-resources -spec: - templating: - - key: namespace - label: 'Namespace' - values: ['default', 'kube-system'] - - queries: - data: - viewTableSelector: - name: all-resources - filter: - namespace: '$(var.namespace)' -``` - -### Combine Multiple Views - -When building a view that needs data from multiple other views, use both viewTableSelector queries and merge: - -```yaml -queries: - configs: - viewTableSelector: - name: config-summary - filter: - status: 'critical' - - changes: - viewTableSelector: - name: recent-changes - filter: - severity: 'warning' - -merge: | - SELECT - c.id, - c.name, - c.status, - COUNT(ch.id) as change_count - FROM configs c - LEFT JOIN changes ch ON c.id = ch.config_id - GROUP BY c.id, c.name, c.status -``` - -## Column Mapping - -Columns from view table selectors work like any other query: - -```yaml -columns: - - name: name - type: string - primaryKey: true - - name: status - type: status - -queries: - data: - viewTableSelector: - name: resource-inventory - -mapping: - name: 'row.name' - status: 'row.status' -``` - -## Real-World Examples - -### High-Level Resource Status Dashboard - -First, create the base view that queries configs: - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: resource-inventory -spec: - columns: - - name: id - type: string - primaryKey: true - hidden: true - - name: name - type: string - - name: type - type: string - - name: status - type: status - - name: health - type: health - - queries: - resources: - configs: - types: ['Kubernetes::Pod', 'Kubernetes::Node'] - - mapping: - id: 'row.id' - name: 'row.name' - type: 'row.type' - status: 'row.status' - health: 'row.health' -``` - -Then create a summary view using viewTableSelector: - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: resource-summary -spec: - display: - title: 'Resource Summary' - card: - columns: 2 - - columns: - - name: type - type: string - primaryKey: true - - name: total_count - type: number - - name: healthy_count - type: number - - name: critical_count - type: number - - queries: - resources: - viewTableSelector: - name: resource-inventory - - merge: | - SELECT - type, - COUNT(*) as total_count, - SUM(CASE WHEN health = 'healthy' THEN 1 ELSE 0 END) as healthy_count, - SUM(CASE WHEN health = 'critical' THEN 1 ELSE 0 END) as critical_count - FROM resources - GROUP BY type - - mapping: - type: 'row.type' - total_count: 'row.total_count' - healthy_count: 'row.healthy_count' - critical_count: 'row.critical_count' -``` - -### Production Resource Drill-Down +| Property | Type | Description | +| --------------- | ------ | --------------------------------------------------------------------------- | +| `name` | string | Name of the view to query | +| `namespace` | string | Namespace of the view (default: `default`) | +| `labelSelector` | string | Optional label selector to match multiple views (for composition by label) | -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: prod-resources -spec: - display: - title: 'Production Resources' - sidebar: true +The selector returns **all rows** from the matched view tables. Shape or filter the data in your `merge` SQL or panel queries. - templating: - - key: resource_type - label: 'Resource Type' - values: ['Pod', 'Deployment', 'Node'] - default: 'Pod' +## Example: Summarize an Existing View - columns: - - name: resource_id - type: string - primaryKey: true - hidden: true - - name: name - type: string - - name: status - type: status - - name: health - type: health +Aggregate the cached `deployments` view to show healthy vs unhealthy releases per namespace: - queries: - data: - viewTableSelector: - name: resource-inventory - filter: - type: '$(var.resource_type)' - status: 'production' +```yaml title="deployments-summary.yaml" file=/modules/mission-control/fixtures/views/deployments-summary.yaml {10-37} - mapping: - resource_id: 'row.id' - name: 'row.name' - status: 'row.status' - health: 'row.health' ``` -### Composite Metrics View - -Base view with Prometheus metrics: - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: node-metrics -spec: - columns: - - name: node - type: string - primaryKey: true - - name: cpu_percent - type: gauge - - queries: - metrics: - prometheus: - connection: prod - query: 'rate(node_cpu_seconds_total[5m]) * 100' - - mapping: - node: 'row.node' - cpu_percent: 'row.value' -``` - -Composite view that adds more context: - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: nodes-with-metrics -spec: - columns: - - name: node_name - type: string - primaryKey: true - - name: node_type - type: string - - name: status - type: status - - name: cpu_usage - type: gauge - - queries: - nodes: - viewTableSelector: - name: node-inventory - - metrics: - viewTableSelector: - name: node-metrics - - merge: | - SELECT - n.name as node_name, - n.type as node_type, - n.status, - m.cpu_percent as cpu_usage - FROM nodes n - LEFT JOIN metrics m ON n.name = m.node - - mapping: - node_name: 'row.node_name' - node_type: 'row.node_type' - status: 'row.status' - cpu_usage: 'row.cpu_usage' -``` - -### Change Impact Analysis - -Query cached changes using viewTableSelector: - -```yaml -apiVersion: mission-control.flanksource.com/v1 -kind: View -metadata: - name: change-impact -spec: - display: - title: 'Change Impact Analysis' - - templating: - - key: severity - label: 'Minimum Severity' - values: ['info', 'warning', 'critical'] - default: 'warning' - - columns: - - name: change_id - type: string - primaryKey: true - hidden: true - - name: resource - type: string - - name: change_type - type: string - - name: impact - type: health - - queries: - changes: - viewTableSelector: - name: recent-changes - filter: - severity: '$(var.severity)' - - mapping: - change_id: 'row.id' - resource: 'row.resource_name' - change_type: 'row.change_type' - impact: 'row.severity' -``` - -## Performance Tips - -### Use Base Views for Heavy Queries - -Let specialized views handle expensive queries, then compose them: - -```yaml -# ✓ Good: Heavy query in base view -# pod-inventory (queries all configs once) - -# ✓ Good: Light queries on top -# pod-metrics (just adds a column from viewTableSelector) -# pod-summary (just aggregates viewTableSelector results) - -# ✗ Bad: Heavy query in composite view -# every-pod-view (duplicates the config query) -``` - -### Filter Early - -Use the `filter` property to reduce data: - -```yaml -# ✓ Filter in viewTableSelector -queries: - data: - viewTableSelector: - name: all-resources - filter: - status: 'critical' # Reduce data from start - -# ✗ Filter in merge query -# queries all rows, then filters -merge: | - SELECT * FROM data - WHERE status = 'critical' # Filters after loading all -``` - -### Cache Configuration - -Ensure base views have appropriate cache settings: - -```yaml -# Base view should cache longer -cache: - maxAge: 15m - -# Composite view can cache shorter -cache: - maxAge: 5m # Depends on base, but can be fresh more often -``` - -### Variable Dependency - -Use view templating variables for dependent filtering: - -```yaml -# ✓ Good: Variables filter viewTableSelector -templating: - - key: environment - values: ['prod', 'staging'] - -queries: - data: - viewTableSelector: - name: resources - filter: - environment: '$(var.environment)' -# ✗ Avoid: Multiple views don't coordinate variables -``` - -## Troubleshooting - -### View Not Found - -Check: - -1. Is the view name correct? (case-sensitive) -2. Is the namespace correct? -3. Has the base view cached data yet? (Run it manually) - -### No Results - -Check: - -1. Does the base view have data? -2. Are filter values correct? -3. Try removing filters temporarily -4. Check column names match exactly - -### Stale Data - -If you see old data: - -1. Verify base view cache timing -2. Check if base view is being refreshed -3. Consider reducing cache TTL on composite view - -## Limitations +## Tips -- Cannot filter on columns that don't exist in the source view -- Filter values must match exactly (case-sensitive) -- Can only query cached view results -- Column types are inherited from source view +- Ensure the source view has cached data; the selector reads the Postgres table created for that view. +- Column types are inherited from the source view, so filters and formatting stay consistent. +- Use `labelSelector` when you want to stitch together multiple related views without hard-coding names. +- Apply filtering and limits in `merge` SQL or panel queries to keep selectors simple. diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/boolean.md new file mode 100644 index 00000000..b671ee9e --- /dev/null +++ b/mission-control/docs/guide/views/table/boolean.md @@ -0,0 +1,15 @@ +--- +title: Boolean +sidebar_custom_props: + icon: mdi:check-circle-outline +--- + +The `boolean` column type renders `true`/`false` values as friendly yes/no text in tables and cards. Use it for readiness, feature flags, or any binary state. + +## Example + +```yaml title="boolean-example.yaml" file=/modules/mission-control/fixtures/views/boolean-example.yaml {7-27} + +``` + +If you enable `filter.type: multiselect` on a boolean column, Mission Control builds the options from the cached table so users can quickly include or exclude rows by state without triggering a view refresh. diff --git a/mission-control/docs/guide/views/table/config-item.md b/mission-control/docs/guide/views/table/config-item.md index f63e7fcc..808b6483 100644 --- a/mission-control/docs/guide/views/table/config-item.md +++ b/mission-control/docs/guide/views/table/config-item.md @@ -4,7 +4,9 @@ sidebar_custom_props: icon: config --- -The `config_item` column type displays clickable links to configuration item detail pages. +The `config_item` column type displays clickable links to configuration item detail pages with a proper icon. + +This column requires an `id` field in row. ## Example diff --git a/mission-control/docs/guide/views/table/index.mdx b/mission-control/docs/guide/views/table/index.mdx index cea0f0ba..95078bce 100644 --- a/mission-control/docs/guide/views/table/index.mdx +++ b/mission-control/docs/guide/views/table/index.mdx @@ -38,8 +38,11 @@ All column types support these properties: | `primaryKey` | bool | Include in composite primary key | | `description` | string | Help text for the column | | `hidden` | bool | Hide from table display | -| `filter` | object | Enable filtering (`type: multiselect`) | +| `filter` | object | Enable filtering (`type: multiselect`), labels columns support include/exclude per key | | `icon` | string | Icon for the column (supports CEL like `row.health`) | +| `url` | object | Link to configs, views, or custom URLs (see URL column type) | +| `unit` | string | Unit label for gauges, numbers, and durations | +| `configItem` | object | Options for `config_item` columns (e.g., custom `idField`) | | `card` | object | Card layout position (`position`, `useForAccent`) | ## Card Positioning diff --git a/mission-control/docs/guide/views/table/labels.md b/mission-control/docs/guide/views/table/labels.md new file mode 100644 index 00000000..2b6e7eff --- /dev/null +++ b/mission-control/docs/guide/views/table/labels.md @@ -0,0 +1,19 @@ +--- +title: Labels +sidebar_custom_props: + icon: mdi:label +--- + +The `labels` column type renders key/value labels and supports include/exclude filtering by tag. + +## Example + +```yaml title="labels.yaml" file=/modules/mission-control/fixtures/views/labels.yaml {17-20} + +``` + +## Behavior + +- Values must be a JSON object (e.g., `{team: "platform", env: "prod"}`). +- Enable `filter.type: multiselect` to allow users to include or exclude specific label values. +- UI filters encode selections per label key, so users can combine multiple label filters without losing context. diff --git a/mission-control/docs/guide/views/table/millicore.md b/mission-control/docs/guide/views/table/millicore.md index 77e40310..d90cb95e 100644 --- a/mission-control/docs/guide/views/table/millicore.md +++ b/mission-control/docs/guide/views/table/millicore.md @@ -8,14 +8,14 @@ The `millicore` column type displays CPU resources in millicores (1000m = 1 CPU ## Conversion -| Value | Display | Meaning | -|-------|---------|---------| -| 100 | 100m | 10% of a core | -| 500 | 500m | 50% of a core | -| 1000 | 1000m | 1 full CPU core | +| Value | Display | Meaning | +| ----- | ------- | --------------- | +| 100 | 100m | 10% of a core | +| 500 | 500m | 50% of a core | +| 1000 | 1000m | 1 full CPU core | ## Example -```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {46-48} +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {45-48} ``` diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/number.md index c87c07a9..c2008f16 100644 --- a/mission-control/docs/guide/views/table/number.md +++ b/mission-control/docs/guide/views/table/number.md @@ -15,6 +15,6 @@ The `number` column type displays numeric values (integers and decimals). ## Example -```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {115-119} +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/notification-send-history.yaml {115-119} ``` diff --git a/mission-control/docs/reference/views/_view.mdx b/mission-control/docs/reference/views/_view.mdx index bdd9c091..55509d87 100644 --- a/mission-control/docs/reference/views/_view.mdx +++ b/mission-control/docs/reference/views/_view.mdx @@ -1,4 +1,9 @@ :::note Validation Requirements -- **At least one query**: Views must define at least one named query +- **At least one query**: Views must define at least one named query (unless the view only renders `sections`) - **Output definition**: Views must have either `panels` or `columns` (or both) - **Merge requirement**: When using multiple queries with table output (columns only), you must provide a `merge` SQL query ::: @@ -83,10 +108,20 @@ Query definition for data sources. description: "Query configuration changes and audit data", scheme: "[ResourceSelector](/docs/reference/resource-selector)" }, + { + field: "sql", + description: "Run a SQL query against a configured connection (PostgreSQL, MySQL, SQL Server)", + scheme: "[SQL query](/mission-control/guide/views/queries/sql)" + }, { field: "prometheus", description: "Query time-series data from Prometheus", scheme: "[Prometheus Query](#prometheus-query)" + }, + { + field: "viewTableSelector", + description: "Read cached rows from another view table", + scheme: "[View Table Selector](#view-table-selector)" } ]}/> @@ -143,7 +178,7 @@ Column definition for view tables with data types and visualization properties. field: "type", required: true, description: "Data type that determines formatting and visualization", - scheme: "`string`, `number`, `boolean`, `datetime`, `duration`, `health`, `status`, `gauge`, `bytes`, `decimal`, `millicore`, `url`" + scheme: "`string`, `number`, `boolean`, `datetime`, `duration`, `health`, `status`, `gauge`, `bytes`, `decimal`, `millicore`, `url`, `badge`, `config_item`, `labels`" }, { field: "primaryKey", @@ -160,6 +195,31 @@ Column definition for view tables with data types and visualization properties. description: "Whether to hide the column from the UI _(default: false)_", scheme: "bool" }, + { + field: "filter", + description: "Enable column filtering in the UI. Options are populated from the cached table per request fingerprint _(type: multiselect; labels columns support key/value include-exclude filters)_", + scheme: "object" + }, + { + field: "icon", + description: "CEL expression that selects an icon per row (for tables and cards)", + scheme: "string" + }, + { + field: "url", + description: "Link to configs, other views, or custom URLs using CEL/Go templates", + scheme: "[ColumnURL](#column-urls)" + }, + { + field: "unit", + description: "Unit string appended to values (e.g., %, bytes, millicore)", + scheme: "string" + }, + { + field: "configItem", + description: "Options for `config_item` columns (choose which field to treat as the config ID)", + scheme: "ConfigItemColumnType" + }, { field: "for", description: "Reference to another column this column provides data for _(helper columns)_. Only applicable for type=url.", @@ -169,6 +229,11 @@ Column definition for view tables with data types and visualization properties. field: "gauge", description: "Configuration for gauge visualization _(required when type=gauge)_", scheme: "[GaugeConfig](#gauge-configuration)" + }, + { + field: "card", + description: "Card layout configuration for this column (position and accent highlighting)", + scheme: "CardConfig" } ]}/> @@ -196,7 +261,7 @@ Panel definition for interactive visualizations. field: "type", required: true, description: "Type of panel visualization", - scheme: "`piechart`, `table`, `number`, `gauge`" + scheme: "`piechart`, `table`, `text`, `number`, `duration`, `gauge`, `bargauge`, `timeseries`" }, { field: "query", @@ -218,6 +283,16 @@ Panel definition for interactive visualizations. field: "number", description: "Configuration for number panels", scheme: "[Panel Number Configuration](#panel-number-configuration)" + }, + { + field: "bargauge", + description: "Configuration for bar gauge panels", + scheme: "[Bar Gauge Configuration](#bar-gauge-configuration)" + }, + { + field: "timeseries", + description: "Configuration for timeseries panels", + scheme: "[Timeseries Configuration](#timeseries-configuration)" } ]}/> @@ -245,19 +320,17 @@ Configuration for gauge visualizations with thresholds and color coding. +#### Bar Gauge Configuration + +Configuration for bar gauge panels. + + + +#### Timeseries Configuration + +Configuration for timeseries panels (API-level; UI rendering in progress). + + + +### View Card Layout + +`display.card` controls the default card layout for tables with card positioning. Cards become the default view when `default: true` and at least one column defines `card.position` (or legacy `cardPosition`). Use `columns[].card.useForAccent` to color the card accent based on a column's value (status/health heuristics in the UI): + + + +### Config Tabs + +Use `display.plugins` to attach a view as a tab on config detail pages. The `configTab` selector chooses matching configs, and `variables` templating pulls values from the config into the view request. + +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {66-76} + +``` + +### Column Filters + +Enable `columns[].filter.type: multiselect` to expose server-side filters without re-running the view. Mission Control gathers distinct values from the cached Postgres table (scoped to the current `request_fingerprint`), builds dropdown options, and applies PostgREST filters. Labels columns support include/exclude tokens so you can target specific keys. + +```yaml title="ingress.yaml" file=/modules/mission-control/fixtures/views/ingress.yaml {8-48} + +``` + +### Column URLs + +`columns[].url` can link to Mission Control objects or external destinations: + +- `config`: CEL expression resolving to a config ID or search query (redirects to catalog page) +- `view`: Link to another view with optional query params built from CEL expressions +- `template`: Go template that renders a custom URL + +```yaml title="deployments.yaml" file=/modules/mission-control/fixtures/views/deployments.yaml {37-40,72-73} + +``` + +### Row Attributes and Grants + +Mission Control appends hidden, reserved columns to every view table: + +- `__row__attributes` (`row_attributes` type) stores per-column metadata generated during mapping: evaluated icons, URLs, gauge min/max overrides, and config item details (`id`, `type`, `class`, `health`, `status`). The UI uses these attributes to render icons, clickable links, and card accents. +- `__grants` (`grants` type) stores scope IDs computed for config queries so row-level security policies can filter PostgREST responses. + +You do not need to declare these columns, but they appear in the materialized Postgres table and PostgREST output. + +### View Table Selector + +Reference cached data from another view instead of re-querying sources. The selector matches views by `name`, `namespace`, or `labelSelector`, then treats their materialized tables as a query source. + +```yaml title="deployments-summary.yaml" file=/modules/mission-control/fixtures/views/deployments-summary.yaml {10-37} + +``` + +### Sections + +Render multiple views on one page. Section-only views can omit panels and columns; each section points at another view and is rendered with shared variable controls. + +```yaml title="workload-overview.yaml" file=/modules/mission-control/fixtures/views/workload-overview.yaml {6-24} +``` diff --git a/modules/canary-checker b/modules/canary-checker index ed38050d..806a8ba3 160000 --- a/modules/canary-checker +++ b/modules/canary-checker @@ -1 +1 @@ -Subproject commit ed38050dc7e235b75879366248554587b3470425 +Subproject commit 806a8ba3ca9357cc8ba1c09d97bf4ac6e92584de diff --git a/modules/config-db b/modules/config-db index b831a7b5..4d7b9237 160000 --- a/modules/config-db +++ b/modules/config-db @@ -1 +1 @@ -Subproject commit b831a7b5fbe36b3925da6cf43216632cd9e0bee6 +Subproject commit 4d7b9237164e0931e31286927fa7c0e48ee8fc23 diff --git a/modules/duty b/modules/duty index 436114ba..38310f70 160000 --- a/modules/duty +++ b/modules/duty @@ -1 +1 @@ -Subproject commit 436114ba6e4710286a28e3819e3f5d84d0f038cf +Subproject commit 38310f7004af13dc628d61fd430f89fbc345cc64 diff --git a/modules/mission-control b/modules/mission-control index 594221f4..fa1448e7 160000 --- a/modules/mission-control +++ b/modules/mission-control @@ -1 +1 @@ -Subproject commit 594221f4cc0d66a7d0a047137992c70ea234ce29 +Subproject commit fa1448e7bb20ff5cb5797b4b3a0b8d9d9d9bae49 diff --git a/modules/mission-control-chart b/modules/mission-control-chart index f57f3876..c53bd62b 160000 --- a/modules/mission-control-chart +++ b/modules/mission-control-chart @@ -1 +1 @@ -Subproject commit f57f387623c5137d4be3d33af655a1437f63f7d4 +Subproject commit c53bd62b539b63059121bd096b8262ec3773cfbb diff --git a/modules/mission-control-registry b/modules/mission-control-registry index 7cb49b3a..145d4761 160000 --- a/modules/mission-control-registry +++ b/modules/mission-control-registry @@ -1 +1 @@ -Subproject commit 7cb49b3aa464410b76323b924b716f9c07f4360c +Subproject commit 145d476118a30aca6dd62e04783139d5edbcb07b From 6a0dc9c28693fe6aec3ad39f530d6133e3d884a1 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Thu, 4 Dec 2025 11:34:19 +0545 Subject: [PATCH 6/8] chore: lint fixes --- .../blog/state-based-alerting/index.md | 146 +++++++++--------- .../guide/config-db/concepts/relationships.md | 24 +-- .../guide/config-db/concepts/retention.md | 22 +-- .../guide/config-db/concepts/transform.md | 32 ++-- .../docs/guide/config-db/scrapers/azure.md | 30 ++-- mission-control/docs/guide/playbooks/_api.md | 32 ++-- .../docs/guide/playbooks/actions/index.md | 42 ++--- .../guide/views/concepts/cache-control.md | 43 ++++-- .../docs/guide/views/panels/duration.md | 6 +- .../docs/guide/views/panels/gauge.md | 28 ++-- .../docs/guide/views/panels/number.md | 16 +- .../docs/guide/views/panels/piechart.md | 12 +- .../docs/guide/views/panels/table.md | 8 +- .../docs/guide/views/panels/text.md | 4 +- .../docs/guide/views/queries/configs.md | 20 +-- .../docs/guide/views/queries/prometheus.md | 8 +- .../docs/guide/views/queries/sql.md | 16 +- .../views/queries/view-table-selector.md | 10 +- .../docs/guide/views/table/bytes.md | 8 +- .../docs/guide/views/table/decimal.md | 8 +- .../docs/guide/views/table/gauge.md | 12 +- .../docs/guide/views/table/number.md | 8 +- .../docs/integrations/flux/catalog.md | 1 - .../docs/reference/canary-checker/check.md | 42 ++--- .../docs/reference/config-db/properties.md | 44 +++--- .../docs/reference/config-db/scrape-result.md | 34 ++-- .../docs/reference/playbooks/events.md | 8 +- .../docs/reference/playbooks/index.md | 58 +++---- .../docs/reference/resource-selector.md | 2 - prompts/blog.md | 23 ++- prompts/style.md | 9 +- scripts/README.md | 2 +- 32 files changed, 387 insertions(+), 371 deletions(-) diff --git a/mission-control/blog/state-based-alerting/index.md b/mission-control/blog/state-based-alerting/index.md index 57aca153..417a3028 100644 --- a/mission-control/blog/state-based-alerting/index.md +++ b/mission-control/blog/state-based-alerting/index.md @@ -1,37 +1,34 @@ --- draft: true --- -# State-Based Alerting: Understanding Why Kubernetes Deployments Fail +# State-Based Alerting: Understanding Why Kubernetes Deployments Fail ## Application vs Infrastructure -Application and infrastucture normally have very different failure scenarios, Application errors are normally due to bugs (that produce exceptions) or performance related problems. When there are problems it becomes immiedatly obvious - page fails to load or starts timing out. Infrastructure health is more often related to configuration errors, drift, permissions and unhealthy dependencies problems can lay latent and be influenced by drift and dependences. +Application and infrastucture normally have very different failure scenarios, Application errors are normally due to bugs (that produce exceptions) or performance related problems. When there are problems it becomes immiedatly obvious - page fails to load or starts timing out. Infrastructure health is more often related to configuration errors, drift, permissions and unhealthy dependencies problems can lay latent and be influenced by drift and dependences. -Common application health methodologies include **USE** (**u**tilization, **s**aturation,**e**rrors) and **RED** (**r**quests, **e**rrors, **d**uration) that primarily use metrics (and log/trace derived metrics) that define thresholds for known health states. It is fairly straightforard to define healthy, unhealthy and warning states. These methodoligies struggle with unknown states i.e. we are not receiving any traffic so we don't if there are any errors. Synthetic testing helps to surface problems by creating artificial transactions +Common application health methodologies include **USE** (**u**tilization, **s**aturation,**e**rrors) and **RED** (**r**quests, **e**rrors, **d**uration) that primarily use metrics (and log/trace derived metrics) that define thresholds for known health states. It is fairly straightforard to define healthy, unhealthy and warning states. These methodoligies struggle with unknown states i.e. we are not receiving any traffic so we don't if there are any errors. Synthetic testing helps to surface problems by creating artificial transactions ## Metric (Thresholds and Anomalies) - ## State Based ## Synthetic Testing - Infrastructure errors tend be more state oreinted ## Alerting Types and Examples There are various types of alerting methods, and choosing the right one can be challenging. -| Alerting Type | Example(s) | Use Cases | -| :---- | :---- | :---- | -| **Metrics (Threshold)** | \- CPU \> 90% for 5 minutes.
\- Available disk space \< 10GB. | Best for USE (**u**tilization, **s**aturation,**e**rrors) and known errors. | -| **Anomaly Detection** | \- Website traffic drops 50% compared to the same time last week.
\- Login attempts spike far beyond the normal range. | Useful for detecting unusual patterns and behavior that deviate from historical norms. Suitable for security monitoring and business metrics. | -| **Log-Based** | \- More than 10 "HTTP 500" errors in web server logs within 1 minute.
\- Any log containing `OutOfMemoryError`. | Ideal for error detection, security events, and application-specific issues that are captured in logs. Good for detailed troubleshooting context. | -| **State Based** | \- Kubernetes Node condition `Ready` \= False for 10 minutes.
\- Pod status is `CrashLoopBackOff`.
\- Deployment condition `Progressing = False` with reason: `ProgressDeadlineExceeded`. | Suitable for infrastructure and platform monitoring where resources have defined states. Good for Kubernetes and cloud resource health monitoring. | -| **Synthetic** | \- Simulated user login journey fails from an external testing location.
\- Critical API endpoint response time exceeds 2 seconds from an external check.
\- Website homepage fails to load correctly from an external probe. | Best for end-to-end monitoring and user experience validation. Ideal for critical business flows and external service dependency checks. | - +| Alerting Type | Example(s) | Use Cases | +| :---------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Metrics (Threshold)** | \- CPU \> 90% for 5 minutes.
\- Available disk space \< 10GB. | Best for USE (**u**tilization, **s**aturation,**e**rrors) and known errors. | +| **Anomaly Detection** | \- Website traffic drops 50% compared to the same time last week.
\- Login attempts spike far beyond the normal range. | Useful for detecting unusual patterns and behavior that deviate from historical norms. Suitable for security monitoring and business metrics. | +| **Log-Based** | \- More than 10 "HTTP 500" errors in web server logs within 1 minute.
\- Any log containing `OutOfMemoryError`. | Ideal for error detection, security events, and application-specific issues that are captured in logs. Good for detailed troubleshooting context. | +| **State Based** | \- Kubernetes Node condition `Ready` \= False for 10 minutes.
\- Pod status is `CrashLoopBackOff`.
\- Deployment condition `Progressing = False` with reason: `ProgressDeadlineExceeded`. | Suitable for infrastructure and platform monitoring where resources have defined states. Good for Kubernetes and cloud resource health monitoring. | +| **Synthetic** | \- Simulated user login journey fails from an external testing location.
\- Critical API endpoint response time exceeds 2 seconds from an external check.
\- Website homepage fails to load correctly from an external probe. | Best for end-to-end monitoring and user experience validation. Ideal for critical business flows and external service dependency checks. | This article compares Metric vs State Based alerts needed by platform teams managing infrastructure and deployments. @@ -51,7 +48,7 @@ labels: severity: warning annotations: summary: Kubernetes pod crash looping (instance {{ $labels.instance }}) - description: "Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping" + description: 'Pod {{ $labels.namespace }}/{{ $labels.pod }} is crash looping' ``` And would produce an alert similar to this: @@ -60,22 +57,19 @@ And would produce an alert similar to this: There are some drawbacks with this approach: -* **Limited Details** - The alert tells you **_what_** happened, but not **_why_**. -* **Limited Context** - You know the name of the pod and namespace, but not much else. If you want to restrict alerts to only pods labelled `env: production`, `kube-state-metrics` needs to be updated to whitelist the label. -* **Cardinality Challenges** - Whitelisting is required, as without it, you risk a cardinality explosion. Ingesting large amounts of metrics can be expensive and inefficient. -* **Configuration Overhead** - Each failure scenario requires configuration, first with the extraction of metrics and then by creating and fine-tuning alerts. +- **Limited Details** - The alert tells you **_what_** happened, but not **_why_**. +- **Limited Context** - You know the name of the pod and namespace, but not much else. If you want to restrict alerts to only pods labelled `env: production`, `kube-state-metrics` needs to be updated to whitelist the label. +- **Cardinality Challenges** - Whitelisting is required, as without it, you risk a cardinality explosion. Ingesting large amounts of metrics can be expensive and inefficient. +- **Configuration Overhead** - Each failure scenario requires configuration, first with the extraction of metrics and then by creating and fine-tuning alerts. These challenges are due to how TSDBs handle textual vs numerical data - the details and context you need is all in the text. - ## State-Based Alerting - The first step to "configuration-less" alerts is some standardization on what it means for something to be unhealthy. This is still an unsolved problem outside of Pod Probes. Kubernetes has taken some early steps with Conditions - which is an interface for reporting the state of a resource as either `unhealthy` or `healthy`. If you run the following command to get the YAML definition of a Pod: - apiVersion: v1 kind: Pod @@ -198,8 +192,6 @@ If you run the following command to get the YAML definition of a Pod:  startTime: "2025-03-26T10:17:16Z" - - While standards exist for exposing metrics, there's no equivalent standard for exposing the thresholds or conditions that trigger alerts. This leads to fragmentation and complexity in monitoring setups. [is-healthy](https://github.com/flanksource/is-healthy) is a tool designed to assess and report the health status of Kubernetes and other cloud resources (such as AWS) without the limitations of metric-based approaches. @@ -213,28 +205,27 @@ ready: false health: unhealthy status: ImagePullBackOff message: Back-off pulling image "nginx:invalid" -lastUpdated: "2025-03-26T10:17:18Z" +lastUpdated: '2025-03-26T10:17:18Z' ``` - This example output shows: -* **ready**: Whether the resource is reconciling or provisioning. Note: `ready` indicates if the resource's desired state matches its actual state, which is different from its health. A pod in a failure state can be `ready` if its state is stable (not changing). -* **health**: One of `healthy`, `unhealthy`, `warning`, `unknown`. This indicates the overall health assessment. -* **status**: A text description of the state of the resource, for example, `Running` or `ImagePullBackOff`. -* **message**: A reason providing more detail for the current status. -* **lastUpdated**: The timestamp when the resource was lastUpdated or reconciled. + +- **ready**: Whether the resource is reconciling or provisioning. Note: `ready` indicates if the resource's desired state matches its actual state, which is different from its health. A pod in a failure state can be `ready` if its state is stable (not changing). +- **health**: One of `healthy`, `unhealthy`, `warning`, `unknown`. This indicates the overall health assessment. +- **status**: A text description of the state of the resource, for example, `Running` or `ImagePullBackOff`. +- **message**: A reason providing more detail for the current status. +- **lastUpdated**: The timestamp when the resource was lastUpdated or reconciled. This is example isn't really thay useful, as it needs to be run continously, [canary-checker](https://canarychecker.io/) is a kubernetes health-check platform with support for 30+ check types, The [`kubernetes`](https://canarychecker.io/reference/kubernetes) check uses the `is-healthy` library: ```yaml title=kubernetes.yaml file=./canary.yaml + ``` This can be run locally: - - ## Step-by-Step Guide to State-Based Alerting for Deployments ### Understanding Deployment States @@ -298,8 +289,6 @@ And then checking on the status: updatedReplicas: 1 - - ### Setting Up State-Based Alerting with Mission Control Mission Control can monitor these states and alert when they indicate problems. Let's create a check to monitor deployment rollout status. @@ -315,38 +304,40 @@ spec: interval: 30 kubernetes: - name: check-deployment-rollout - description: "Monitor deployment rollout state" + description: 'Monitor deployment rollout state' resource: apiVersion: apps/v1 kind: Deployment name: nginx-deployment namespace: default results: - - name: Available - selector: $.status.conditions[?(@.type=="Available")].status - condition: Equal - error: "False" - - name: Progressing - selector: $.status.conditions[?(@.type=="Progressing")].status - condition: Equal - error: "False" - - name: ProgressingReason - selector: $.status.conditions[?(@.type=="Progressing")].reason - condition: Equal - error: "ProgressDeadlineExceeded" - - name: ErrorMessage - selector: $.status.conditions[?(@.type=="Progressing")].message - display: true + - name: Available + selector: $.status.conditions[?(@.type=="Available")].status + condition: Equal + error: 'False' + - name: Progressing + selector: $.status.conditions[?(@.type=="Progressing")].status + condition: Equal + error: 'False' + - name: ProgressingReason + selector: $.status.conditions[?(@.type=="Progressing")].reason + condition: Equal + error: 'ProgressDeadlineExceeded' + - name: ErrorMessage + selector: $.status.conditions[?(@.type=="Progressing")].message + display: true ``` + This Canary check: + 1. Runs every 30 seconds (`interval: 30`). 2. Targets the `Deployment` named `nginx-deployment` in the `default` namespace. 3. Defines results based on JSONPath selectors applied to the Deployment's status: - - Checks if the `Available` condition status is `False`. - - Checks if the `Progressing` condition status is `False`. - - Checks if the `Progressing` condition reason is `ProgressDeadlineExceeded`. - - Captures the `Progressing` condition message for display (`display: true`). - An alert is triggered if any condition marked with `error:` is met. + - Checks if the `Available` condition status is `False`. + - Checks if the `Progressing` condition status is `False`. + - Checks if the `Progressing` condition reason is `ProgressDeadlineExceeded`. + - Captures the `Progressing` condition message for display (`display: true`). + An alert is triggered if any condition marked with `error:` is met. Use `kubectl` to apply the Canary resource definition to your cluster: @@ -384,16 +375,17 @@ spec: app: failing-app spec: containers: - - name: container - image: nginx:latest - resources: - limits: - memory: "10Mi" # Intentionally too small - requests: - memory: "10Mi" - ports: - - containerPort: 80 + - name: container + image: nginx:latest + resources: + limits: + memory: '10Mi' # Intentionally too small + requests: + memory: '10Mi' + ports: + - containerPort: 80 ``` + This Deployment requests 3 replicas but sets a very low memory limit (`10Mi`), which is likely to cause Pods to be terminated with Out Of Memory (OOM) errors. Use `kubectl` to apply the failing Deployment definition to your cluster: @@ -413,18 +405,17 @@ Now, compare how different monitoring approaches handle this failure. With Prometheus, a common alert rule for deployment issues checks for generation mismatches: ```yaml title=KubernetesDeploymentGenerationMismatch - - alert: KubernetesDeploymentGenerationMismatch - expr: kube_deployment_status_observed_generation != kube_deployment_metadata_generation - for: 10m - labels: - severity: critical - annotations: - summary: Kubernetes Deployment generation mismatch (instance {{ $labels.instance }}) - description: "Deployment {{ $labels.namespace }}/{{ $labels.deployment }} has failed but has not been rolled back.\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" +- alert: KubernetesDeploymentGenerationMismatch + expr: kube_deployment_status_observed_generation != kube_deployment_metadata_generation + for: 10m + labels: + severity: critical + annotations: + summary: Kubernetes Deployment generation mismatch (instance {{ $labels.instance }}) + description: "Deployment {{ $labels.namespace }}/{{ $labels.deployment }} has failed but has not been rolled back.\n VALUE = {{ $value }}\n LABELS = {{ $labels }}" ``` -This alert fires when there is a mismatch between the observed and expected generation numbers of a Kubernetes Deployment. The generation number increments whenever the Deployment spec changes. A mismatch indicates that the latest configuration change has not been successfully rolled out by the controller. While useful, it doesn't explain *why* the rollout failed. See [KubernetesDeploymentGenerationMismatch](https://samber.github.io/awesome-prometheus-alerts/rules#rule-kubernetes-1-24) for more details on this type of alert. - +This alert fires when there is a mismatch between the observed and expected generation numbers of a Kubernetes Deployment. The generation number increments whenever the Deployment spec changes. A mismatch indicates that the latest configuration change has not been successfully rolled out by the controller. While useful, it doesn't explain _why_ the rollout failed. See [KubernetesDeploymentGenerationMismatch](https://samber.github.io/awesome-prometheus-alerts/rules#rule-kubernetes-1-24) for more details on this type of alert. #### Mission Control State-Based Alert @@ -456,7 +447,9 @@ The output might resemble the following: } ] ``` + This output shows two conditions: + 1. `Available` is `False` because the deployment does not have the minimum required replicas ready (`MinimumReplicasUnavailable`). 2. `Progressing` is `False` because the rollout timed out (`ProgressDeadlineExceeded`). The message provides specific details about the failure, potentially including reasons like OOM killing if the system surfaces that information here. @@ -467,11 +460,13 @@ Mission Control captures this state and provides an alert with the error message ### When State-Based Alerting Works Best (and When It Doesn't) State-based alerting excels when: + - Resources self-report meaningful status - Problems have descriptive error messages - You need context for troubleshooting It's less effective when: + - Resources don't update status fields - You need to alert on trends over time - Complex conditions require correlation between multiple resources @@ -487,6 +482,7 @@ State changes can trigger multiple alerts. To avoid this: ### Combining with Metric-Based Monitoring The best approach is often a combination: + - Use state-based alerts for detailed diagnostics - Use metric-based alerts for performance issues and trends - Create correlation between the two for complete visibility @@ -498,6 +494,8 @@ State-based alerting transforms monitoring from "something is wrong" to "this is The ability to extract human-readable error messages directly from Kubernetes resources provides context that metrics alone cannot. As systems become more complex, this context becomes critical for effective incident management. For Kubernetes operators, combining state-based alerting with traditional metrics creates a complete view of your system's health and gives you the power to resolve issues faster. + ``` - [KubernetesDeploymentGenerationMismatch](https://samber.github.io/awesome-prometheus-alerts/rules#rule-kubernetes-1-24) +``` diff --git a/mission-control/docs/guide/config-db/concepts/relationships.md b/mission-control/docs/guide/config-db/concepts/relationships.md index 2c9805ef..c1519a24 100644 --- a/mission-control/docs/guide/config-db/concepts/relationships.md +++ b/mission-control/docs/guide/config-db/concepts/relationships.md @@ -53,31 +53,31 @@ You can see changes on the incoming relationships (and their parents) by choosin ## Relationship -| Field | Description | Scheme | Required | -| -------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | -------- | +| Field | Description | Scheme | Required | +| -------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------- | -------- | | `filter` | Which config items to form relationships with | CEL with [`ScrapeResult`](/docs/reference/config-db/scrape-result) | `true` | -| `id` | The ID or Alias (External ID) of the config to link to | [Lookup](#lookup) | | -| `name` | | [Lookup](#lookup) | | -| `type` | Config Type | [Lookup](#lookup) | | +| `id` | The ID or Alias (External ID) of the config to link to | [Lookup](#lookup) | | +| `name` | | [Lookup](#lookup) | | +| `type` | Config Type | [Lookup](#lookup) | | | `agent` | agent of the config to link to | [Lookup](#lookup) that returns an [Agent](/docs/reference/types#agent) | | -| `labels` | Labels of the config to link to | `map[string]`[Lookup](#lookup) | | +| `labels` | Labels of the config to link to | `map[string]`[Lookup](#lookup) | | ### Lookup RelationshipLookup offers different ways to specify a lookup value -| Field | Description | Scheme | Variables | -| ------- | --------------------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------- | +| Field | Description | Scheme | Variables | +| ------- | --------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | | `expr` | An expression that returns a value to be used | CEL with [`ScrapeResult`](/docs/reference/config-db/scrape-result) | [`ScrapeResult`](/docs/reference/config-db/scrape-result) | -| `value` | A static value to use in the lookup | `string` | | -| `label` | Get the value to use from an existing label | `label name` | | +| `value` | A static value to use in the lookup | `string` | | +| `label` | Get the value to use from an existing label | `label name` | | ## Dynamic Linking Sometimes the logic for when to a form a relationship is complex, a CEL expression can be used to return a list of selectors dynamically. -| Field | Description | Scheme | Variables | -| ------ | -------------------------------------------------------------------------------------- | ------------------------------------- | ---------------------------------------------------- | +| Field | Description | Scheme | Variables | +| ------ | ------------------------------------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------- | | `expr` | An expression that returns a list of [ResourceSelectors](/docs/reference/resource-selector) | CEL | [`ScrapeResult`](/docs/reference/config-db/scrape-result) | ```yaml title=link-pvc-to-pod.yaml diff --git a/mission-control/docs/guide/config-db/concepts/retention.md b/mission-control/docs/guide/config-db/concepts/retention.md index d123396e..a06ae8be 100644 --- a/mission-control/docs/guide/config-db/concepts/retention.md +++ b/mission-control/docs/guide/config-db/concepts/retention.md @@ -9,17 +9,17 @@ After scraping we can choose to retain results on the basis of name, age, count The retention rules are applied for each unique catalog item. If `changes` is specified with type `X` and count `20`, last 20 changes of `X` type would be kept for each catalog item -| Field | Description | Scheme | -| -------------- | ------------------------------------------------------------------ | ------------------------------------- | -| `types` | Specify retention rules for config items | [`[]ConfigItem`](#config-items) | -| `changes` | Specify retention rules for changes | [`[]Change`](#changes) | +| Field | Description | Scheme | +| -------------- | ------------------------------------------------------------------ | ------------------------------------------ | +| `types` | Specify retention rules for config items | [`[]ConfigItem`](#config-items) | +| `changes` | Specify retention rules for changes | [`[]Change`](#changes) | | `staleItemAge` | Config items that were last scraped after this age will be deleted | [Duration](/docs/reference/types#duration) | ## Config Items -| Field | Description | Scheme | -| ------------ | ----------------------------------------------------------------- | ------------------------------------- | -| `name` | Specify retention rules for changes | `string` | +| Field | Description | Scheme | +| ------------ | ----------------------------------------------------------------- | ------------------------------------------ | +| `name` | Specify retention rules for changes | `string` | | `createdAge` | Age after a config item is created it will be deleted | [Duration](/docs/reference/types#duration) | | `updatedAge` | Age after a config item last updated, that it will be deleted | [Duration](/docs/reference/types#duration) | | `deletedAge` | Age after a config item is soft deleted, will it be hard deleted. | [Duration](/docs/reference/types#duration) | @@ -63,11 +63,11 @@ spec: Changes can quickly accumulate and grow large over time. While it's important to retain some changes, others can be discarded after a period. -| Field | Description | Scheme | Required | -| ------- | ------------------------------------------------------- | ------------------------------------- | -------- | -| `name` | Name of the change type | `string` | `true` | +| Field | Description | Scheme | Required | +| ------- | ------------------------------------------------------- | ------------------------------------------ | -------- | +| `name` | Name of the change type | `string` | `true` | | `age` | Maximum age of the change type to retain (`12h`, `30d`) | [Duration](/docs/reference/types#duration) | | -| `count` | Maximum count to retain the change type | `int` | | +| `count` | Maximum count to retain the change type | `int` | | ```yaml title="kubernetes-scraper.yaml" apiVersion: configs.flanksource.com/v1 diff --git a/mission-control/docs/guide/config-db/concepts/transform.md b/mission-control/docs/guide/config-db/concepts/transform.md index 2fe62c27..299cf370 100644 --- a/mission-control/docs/guide/config-db/concepts/transform.md +++ b/mission-control/docs/guide/config-db/concepts/transform.md @@ -11,14 +11,14 @@ Transformations allow you to modify scraped config items before they are saved, - Masking sensitive data - Excluding duplicate changes or changes with a high rate -| Field | Description | Scheme | -| --------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------ | -| `transform.exclude` | Remove fields from a scraped `config` | [[]Exclude](#field-exclusions) | -| `transform.mask` | Replace sensitive fields with a hash to enable change detection on secrets | [[]Mask](#masking) | +| Field | Description | Scheme | +| --------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| `transform.exclude` | Remove fields from a scraped `config` | [[]Exclude](#field-exclusions) | +| `transform.mask` | Replace sensitive fields with a hash to enable change detection on secrets | [[]Mask](#masking) | | `transform.changes.exclude` | Ignore changes | [[]CEL](#exclusions) with [Change Context](/docs/reference/config-db/changes) | -| `transform.changes.mapping` | Categorize changes | [Mapping](#mapping) | +| `transform.changes.mapping` | Categorize changes | [Mapping](#mapping) | | `transform.expr` | | [CEL](/docs/reference/scripting/cel) | -| `transform.relationship` | Create relationships between items | [Relationships](./relationships) | +| `transform.relationship` | Create relationships between items | [Relationships](./relationships) | ## Config Items @@ -76,11 +76,11 @@ spec: - fixtures/data/single-config.json ``` -| Field | Description | Scheme | -| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------- | +| Field | Description | Scheme | +| ---------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | `selector` | Filter which config items to apply masks on | `CEL` with [ScrapeResult](/docs/reference/config-db/scrape-result) context | -| `jsonpath` | Values to mask | `JSONPath` | -| `value` | The replacement value of matched elements | `md5` or any static string e.g. `***` | +| `jsonpath` | Values to mask | `JSONPath` | +| `value` | The replacement value of matched elements | `md5` or any static string e.g. `***` | :::info Masks are applied in the order they are specified in the configuration file. @@ -138,19 +138,19 @@ spec: //highlight-end ``` -| Field | Description | Scheme | -| --------- | ------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------- | +| Field | Description | Scheme | +| --------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | | `filter` | Selects changes to apply the mapping | CEL with [Change Context](/docs/reference/config-db/changes) | -| `action` | What action to take on the change, if `delete` then the corresponding config item is marked as deleted | `delete` or `ignore` | -| `type` | New change type | `string` | +| `action` | What action to take on the change, if `delete` then the corresponding config item is marked as deleted | `delete` or `ignore` | +| `type` | New change type | `string` | | `summary` | New summary of the change | Go Template with [Change Context](/docs/reference/config-db/changes) | ## Scripting Scripting modifies the scraped configuration using CEL before saving it to the database. This process is beneficial for data normalization, default value population, and sensitive field masking. -| Field | Description | Scheme | Context | -| ------ | ----------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| Field | Description | Scheme | Context | +| ------ | ----------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | | `expr` | Transform a config item | CEL that returns [[]ScrapeResult](/docs/reference/config-db/scrape-result) | `config` `JSON`
`result` [Scrape Result](/docs/reference/config-db/scrape-result) | ```yaml title="file-scraper.yaml" diff --git a/mission-control/docs/guide/config-db/scrapers/azure.md b/mission-control/docs/guide/config-db/scrapers/azure.md index 404351a5..bbf2ca6d 100644 --- a/mission-control/docs/guide/config-db/scrapers/azure.md +++ b/mission-control/docs/guide/config-db/scrapers/azure.md @@ -17,27 +17,27 @@ The Azure scrapers scrapes your azure account to fetch all the resources & save ## Scraper -| Field | Description | Scheme | Required | -| ----------- | ---------------------------------------------------------------------------- | -------------------------------------------------- | -------- | -| `logLevel` | Specify the level of logging. | `string` | | -| `schedule` | Specify the interval to scrape in cron format. Defaults to every 60 minutes. | `string` | | +| Field | Description | Scheme | Required | +| ----------- | ---------------------------------------------------------------------------- | ------------------------------------------------------- | -------- | +| `logLevel` | Specify the level of logging. | `string` | | +| `schedule` | Specify the interval to scrape in cron format. Defaults to every 60 minutes. | `string` | | | `retention` | Settings for retaining changes, analysis and scraped items | [`Retention`](/docs/guide/config-db/concepts/retention) | | -| `azure` | Azure scrape config | [`[]Azure`](#azure) | | +| `azure` | Azure scrape config | [`[]Azure`](#azure) | | ### Azure -| Field | Description | Scheme | Required | -| ---------------- | -------------------------------------------------------------------------- | ----------------------------------------------------- | -------- | -| `connection` | Specify the connection that provides the clientID, clientSecret & tenantID | `string` | | -| `subscriptionID` | Azure subscription ID | `string` | | -| `organisation` | Azure organisation ID | `string` | | -| `tenantID` | Azure tenant ID | `string` | | -| `clientID` | Microsoft Entra ID app client id | _EnvVar_ | | -| `clientSecret` | Microsoft Entra ID app client secret | _EnvVar_ | | -| `exclusions` | Specifies the Azure projects to scrape | [`Exclusion`](#exclusion) | | +| Field | Description | Scheme | Required | +| ---------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------- | -------- | +| `connection` | Specify the connection that provides the clientID, clientSecret & tenantID | `string` | | +| `subscriptionID` | Azure subscription ID | `string` | | +| `organisation` | Azure organisation ID | `string` | | +| `tenantID` | Azure tenant ID | `string` | | +| `clientID` | Microsoft Entra ID app client id | _EnvVar_ | | +| `clientSecret` | Microsoft Entra ID app client secret | _EnvVar_ | | +| `exclusions` | Specifies the Azure projects to scrape | [`Exclusion`](#exclusion) | | | `properties` | Custom templatable properties for the scraped config items. | [`[]ConfigProperty`](/docs/reference/config-db/properties) | | | `transform` | Field to transform result | [`Transform`](/docs/guide/config-db/concepts/transform) | | -| `tags` | Set custom tags on the scraped config items | `map[string]string` | | +| `tags` | Set custom tags on the scraped config items | `map[string]string` | | :::note Either the `connection` name or the credentials (`clientID`, `clientSecret` & `tenantID`) are required diff --git a/mission-control/docs/guide/playbooks/_api.md b/mission-control/docs/guide/playbooks/_api.md index 6708403e..3322089f 100644 --- a/mission-control/docs/guide/playbooks/_api.md +++ b/mission-control/docs/guide/playbooks/_api.md @@ -55,10 +55,10 @@ POST `/playbook/list?check_id={check_id}` ### Query Parameters -| Parameter | Description | Type | -| -------------- | ------------------------ | -------- | -| `config_id` | ID of the config item | `string` | -| `check_id` | ID of the Check | `string` | +| Parameter | Description | Type | +| ----------- | --------------------- | -------- | +| `config_id` | ID of the config item | `string` | +| `check_id` | ID of the Check | `string` | > Provide only 1 parameter @@ -123,18 +123,18 @@ GET /playbook/run/{id} ### Response -| Field | Type | Description | -| -------------- | ------------------- | ----------------------------------------------------- | -| `id` | `string` | The ID of the run. | -| `playbook_id` | `string` | The ID of the playbook. | -| `status` | `string` | The status of the run. | -| `created_at` | `string` | The time the run is scheduled to start (_in RFC3339_) | -| `start_time` | `string` | The time the run started (_in RFC3339_) | -| `end_time` | `string` | The time the run ended (_in RFC3339_) | -| `created_by` | `string` | The ID of the user that created the run. | -| `config_id` | `string` | The ID of the config item that ran the playbook. | -| `parameters` | `map[string]string` | The parameters to pass to the playbook. | -| `agent_id` | `string` | The ID of the agent that ran the playbook. | +| Field | Type | Description | +| ------------- | ------------------- | ----------------------------------------------------- | +| `id` | `string` | The ID of the run. | +| `playbook_id` | `string` | The ID of the playbook. | +| `status` | `string` | The status of the run. | +| `created_at` | `string` | The time the run is scheduled to start (_in RFC3339_) | +| `start_time` | `string` | The time the run started (_in RFC3339_) | +| `end_time` | `string` | The time the run ended (_in RFC3339_) | +| `created_by` | `string` | The ID of the user that created the run. | +| `config_id` | `string` | The ID of the config item that ran the playbook. | +| `parameters` | `map[string]string` | The parameters to pass to the playbook. | +| `agent_id` | `string` | The ID of the agent that ran the playbook. | ## Accessing Artifacts diff --git a/mission-control/docs/guide/playbooks/actions/index.md b/mission-control/docs/guide/playbooks/actions/index.md index f9dbef1a..4cfdaa36 100644 --- a/mission-control/docs/guide/playbooks/actions/index.md +++ b/mission-control/docs/guide/playbooks/actions/index.md @@ -7,21 +7,21 @@ sidebar_position: 3 Actions are the fundamental tasks executed by a playbook. A playbook can comprise multiple actions, which are executed sequentially. If any action encounters an error and fails, the execution of the playbook is halted. -| Field | Description | Scheme | Required | -| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------- | -------- | -| `name` | Name of action. | `string` | `true` | +| Field | Description | Scheme | Required | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -------- | +| `name` | Name of action. | `string` | `true` | | `runsOn` | Specify the [runners](/docs/guide/playbooks/concepts/runners) that can run this action. One will be chosen on random. When empty, the playbook will run on the main instance itself | `[]string` | | -| `templatesOn` | Specify where the templating of the action spec should occur | `host` or `agent` | | -| `delay` | A delay before running the action e.g. `8h` | `Duration` or [`Expression`](../concepts/expression) | | -| `filter` | Whether to run the step or not | [`Expression`](../concepts/expression) | | -| `timeout` | Timeout on this action. | `Duration` | | -| `azureDevopsPipeline` | | [AzureDevops](./azure_devops_pipeline) | | -| `exec` | Specify exec of action. | [Exec](./exec) | | -| `gitops` | Specify gitops of action. | [Gitops](./gitops) | | -| `http` | Specify http of action. | [Http](./http) | | -| `sql` | Specify sql of action. | [Sql`](./sql) | | -| `pod` | Specify pod of action. | [Pod](./pod) | | -| `notification` | Specify notification of action. | [Notification](./notification) | | +| `templatesOn` | Specify where the templating of the action spec should occur | `host` or `agent` | | +| `delay` | A delay before running the action e.g. `8h` | `Duration` or [`Expression`](../concepts/expression) | | +| `filter` | Whether to run the step or not | [`Expression`](../concepts/expression) | | +| `timeout` | Timeout on this action. | `Duration` | | +| `azureDevopsPipeline` | | [AzureDevops](./azure_devops_pipeline) | | +| `exec` | Specify exec of action. | [Exec](./exec) | | +| `gitops` | Specify gitops of action. | [Gitops](./gitops) | | +| `http` | Specify http of action. | [Http](./http) | | +| `sql` | Specify sql of action. | [Sql`](./sql) | | +| `pod` | Specify pod of action. | [Pod](./pod) | | +| `notification` | Specify notification of action. | [Notification](./notification) | | :::note Specify one or more actions; but at least one. @@ -77,10 +77,10 @@ getAction('action_name').result.stdout.JSON().count < 5 Templates receive a context variable that contain details about the config or component it is running for. In addition, it also contains the optional `params` variable which contains the parameters passed to the playbook. -| Field | Description | Schema | -| ------------- | ---------------------------------------- | --------------------------------------------- | -| `.config` | Config passed to the playbook | [`ConfigItem`](/docs/reference/config-db) | -| `.check` | Canary Check passed to the playbook | [`Check`](/docs/reference/canary-checker/check) | -| `.params` | User provided parameters to the playbook | `map[string]string` | -| `.user.name` | Name of the user who invoked the action | `string` | -| `.user.email` | Email of the user who invoked the action | `string` | +| Field | Description | Schema | +| ------------- | ---------------------------------------- | ----------------------------------------------- | +| `.config` | Config passed to the playbook | [`ConfigItem`](/docs/reference/config-db) | +| `.check` | Canary Check passed to the playbook | [`Check`](/docs/reference/canary-checker/check) | +| `.params` | User provided parameters to the playbook | `map[string]string` | +| `.user.name` | Name of the user who invoked the action | `string` | +| `.user.email` | Email of the user who invoked the action | `string` | diff --git a/mission-control/docs/guide/views/concepts/cache-control.md b/mission-control/docs/guide/views/concepts/cache-control.md index 6438f7a7..0f0499c6 100644 --- a/mission-control/docs/guide/views/concepts/cache-control.md +++ b/mission-control/docs/guide/views/concepts/cache-control.md @@ -41,6 +41,7 @@ spec: ## Cache Parameters ### maxAge + The maximum age of cached data before it's considered stale and needs refresh. - **Default**: `15m` @@ -50,12 +51,14 @@ The maximum age of cached data before it's considered stale and needs refresh. - Longer duration: Less frequent refreshes, potentially stale data, lower load **Example**: + ```yaml cache: - maxAge: 5m # Refresh at least every 5 minutes + maxAge: 5m # Refresh at least every 5 minutes ``` ### minAge + The minimum age cached data must reach before a user can request a manual refresh. This prevents over-refreshing from rapid user clicks. - **Default**: `10s` @@ -65,12 +68,14 @@ The minimum age cached data must reach before a user can request a manual refres - Helps prevent accidental load spikes from aggressive clicking **Example**: + ```yaml cache: - minAge: 30s # Users can only refresh every 30 seconds + minAge: 30s # Users can only refresh every 30 seconds ``` ### refreshTimeout + How long to wait for a refresh operation to complete. If the refresh takes longer, stale data is returned instead of waiting. - **Default**: `5s` @@ -80,9 +85,10 @@ How long to wait for a refresh operation to complete. If the refresh takes longe - Longer timeout: Fresher data, but slower responses if refresh is slow **Example**: + ```yaml cache: - refreshTimeout: 2s # Return stale data if refresh takes > 2 seconds + refreshTimeout: 2s # Return stale data if refresh takes > 2 seconds ``` ## Per-Variable Caching @@ -90,6 +96,7 @@ cache: Each unique combination of template variables creates a separate cache entry. This allows different filters to maintain independent cache lifespans. **Example**: A view with a "cluster" variable will maintain separate cached data for: + - cluster=us-east-1 - cluster=us-west-2 - cluster=eu-central-1 @@ -99,6 +106,7 @@ Each cluster's data is cached independently, allowing users to switch between cl ## Cache Behavior Examples ### Example 1: Fresh Data Request + ``` User requests view ↓ @@ -110,6 +118,7 @@ Response time: ~10ms ``` ### Example 2: Stale Data with Quick Refresh + ``` User requests view ↓ @@ -125,6 +134,7 @@ Response time: ~1.5s ``` ### Example 3: Stale Data with Slow Refresh + ``` User requests view ↓ @@ -144,6 +154,7 @@ Refresh continues in background, updates cache ``` ### Example 4: Manual Refresh Throttling + ``` User clicks refresh button ↓ @@ -157,6 +168,7 @@ User must wait 8 more seconds before refresh is allowed ## Recommended Settings ### High-Frequency Monitoring (Every Minute) + Use shorter cache times for real-time dashboards: ```yaml @@ -167,6 +179,7 @@ cache: ``` ### Typical Dashboard (Every 5-15 Minutes) + Standard balance of freshness and performance: ```yaml @@ -177,6 +190,7 @@ cache: ``` ### Low-Frequency Reference Data (Hourly) + For relatively static data: ```yaml @@ -187,6 +201,7 @@ cache: ``` ### Real-Time Critical (Seconds) + For mission-critical live data: ```yaml @@ -200,14 +215,14 @@ cache: Cache settings directly affect system performance: -| Setting | ↓ Latency | ↓ Load | ↓ Freshness | -|---------|-----------|--------|------------| -| Shorter maxAge | ✗ | ✗ | ✓ | -| Longer maxAge | ✓ | ✓ | ✗ | -| Shorter refreshTimeout | ✓ | ✗ | ✗ | -| Longer refreshTimeout | ✗ | ✓ | ✓ | -| Higher minAge | ✓ | ✓ | ✗ | -| Lower minAge | ✗ | ✗ | ✓ | +| Setting | ↓ Latency | ↓ Load | ↓ Freshness | +| ---------------------- | --------- | ------ | ----------- | +| Shorter maxAge | ✗ | ✗ | ✓ | +| Longer maxAge | ✓ | ✓ | ✗ | +| Shorter refreshTimeout | ✓ | ✗ | ✗ | +| Longer refreshTimeout | ✗ | ✓ | ✓ | +| Higher minAge | ✓ | ✓ | ✗ | +| Lower minAge | ✗ | ✗ | ✓ | ## Default Configuration @@ -215,8 +230,8 @@ If you don't specify cache settings, Mission Control uses these defaults: ```yaml cache: - maxAge: 15m # Refresh at least every 15 minutes - minAge: 10s # Throttle user refreshes to every 10 seconds + maxAge: 15m # Refresh at least every 15 minutes + minAge: 10s # Throttle user refreshes to every 10 seconds refreshTimeout: 5s # Return stale data if refresh takes > 5 seconds ``` @@ -234,11 +249,13 @@ Mission Control uses **singleflight deduplication** to prevent multiple concurre ## Cache Storage View cache data is stored in: + - **Primary storage**: PostgreSQL database (persistent) - **Format**: `view__` table per view - **Tracking**: Request fingerprint (SHA256 hash of variable map) identifies unique variable combinations This allows: + - Data to survive service restarts - PostgREST API access to view data - Historical tracking of different variable combinations diff --git a/mission-control/docs/guide/views/panels/duration.md b/mission-control/docs/guide/views/panels/duration.md index 995467c5..1d6b1010 100644 --- a/mission-control/docs/guide/views/panels/duration.md +++ b/mission-control/docs/guide/views/panels/duration.md @@ -8,9 +8,9 @@ The `duration` panel displays time duration values in a human-readable format (e ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `value` | number | Duration in **nanoseconds** (required) | +| Column | Type | Description | +| ------- | ------ | --------------------------------------------------- | +| `value` | number | Duration in **nanoseconds** (required) | | `label` | string | Optional per-row label (defaults to the panel name) | ## Example diff --git a/mission-control/docs/guide/views/panels/gauge.md b/mission-control/docs/guide/views/panels/gauge.md index 48ff2d7e..44ca2723 100644 --- a/mission-control/docs/guide/views/panels/gauge.md +++ b/mission-control/docs/guide/views/panels/gauge.md @@ -8,29 +8,29 @@ The `gauge` panel displays a single numeric value as a visual gauge with configu ## Properties -| Property | Type | Description | -|----------|------|-------------| -| `min` | string | Minimum value (can be a number or CEL expression) | -| `max` | string | Maximum value (can be a number or CEL expression) | -| `precision` | int | Decimal places to display | -| `unit` | string | Unit label (e.g., "%", "pods") | -| `thresholds` | array | Color thresholds based on percentage | +| Property | Type | Description | +| ------------ | ------ | ------------------------------------------------- | +| `min` | string | Minimum value (can be a number or CEL expression) | +| `max` | string | Maximum value (can be a number or CEL expression) | +| `precision` | int | Decimal places to display | +| `unit` | string | Unit label (e.g., "%", "pods") | +| `thresholds` | array | Color thresholds based on percentage | ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `value` | number | Numeric value to display (required) | +| Column | Type | Description | +| ------- | ------ | ---------------------------------------------------- | +| `value` | number | Numeric value to display (required) | | `label` | string | Optional label; the panel title is used when omitted | ## Thresholds Thresholds define colors at percentage breakpoints (0-100%): -| Property | Type | Description | -|----------|------|-------------| -| `percent` | int | Percentage at which this threshold applies | -| `color` | string | Color name or hex code (e.g., "green", "#10b981") | +| Property | Type | Description | +| --------- | ------ | ------------------------------------------------- | +| `percent` | int | Percentage at which this threshold applies | +| `color` | string | Color name or hex code (e.g., "green", "#10b981") | ## Example diff --git a/mission-control/docs/guide/views/panels/number.md b/mission-control/docs/guide/views/panels/number.md index 73b21400..ed086780 100644 --- a/mission-control/docs/guide/views/panels/number.md +++ b/mission-control/docs/guide/views/panels/number.md @@ -8,17 +8,17 @@ The `number` panel displays a single numeric value with optional unit formatting ## Properties -| Property | Type | Description | -|----------|------|-------------| -| `unit` | string | Unit label (e.g., "bytes", "seconds", "pods") | -| `precision` | int | Decimal places to display | +| Property | Type | Description | +| ----------- | ------ | --------------------------------------------- | +| `unit` | string | Unit label (e.g., "bytes", "seconds", "pods") | +| `precision` | int | Decimal places to display | ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `value` or `count` | number | Numeric value to display (required) | -| `label` | string | Optional per-row label (defaults to the panel name) | +| Column | Type | Description | +| ------------------ | ------ | --------------------------------------------------- | +| `value` or `count` | number | Numeric value to display (required) | +| `label` | string | Optional per-row label (defaults to the panel name) | ## Example diff --git a/mission-control/docs/guide/views/panels/piechart.md b/mission-control/docs/guide/views/panels/piechart.md index 668f315d..055f2260 100644 --- a/mission-control/docs/guide/views/panels/piechart.md +++ b/mission-control/docs/guide/views/panels/piechart.md @@ -8,16 +8,16 @@ The `piechart` panel displays data distribution as a pie chart with customizable ## Properties -| Property | Type | Description | -|----------|------|-------------| +| Property | Type | Description | +| ------------ | ---- | --------------------------------------------- | | `showLabels` | bool | Whether to display value labels on pie slices | -| `colors` | map | Custom color mapping by label name | +| `colors` | map | Custom color mapping by label name | ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `count` | number | Size of each slice (required) | +| Column | Type | Description | +| ------------------------ | ------ | -------------------------------------- | +| `count` | number | Size of each slice (required) | | First non-`count` column | string | Slice label (e.g., `health`, `status`) | ## Colors diff --git a/mission-control/docs/guide/views/panels/table.md b/mission-control/docs/guide/views/panels/table.md index c17b7f31..ea6491fc 100644 --- a/mission-control/docs/guide/views/panels/table.md +++ b/mission-control/docs/guide/views/panels/table.md @@ -8,10 +8,10 @@ The `table` panel displays query results as a simple key-value list. It has no a ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| -| `value` | string/number | Value displayed on the right (required) | -| First non-`value` column | string | Label displayed on the left (required) | +| Column | Type | Description | +| ------------------------ | ------------- | --------------------------------------- | +| `value` | string/number | Value displayed on the right (required) | +| First non-`value` column | string | Label displayed on the left (required) | ## Example diff --git a/mission-control/docs/guide/views/panels/text.md b/mission-control/docs/guide/views/panels/text.md index 1ecb2f35..c91c7716 100644 --- a/mission-control/docs/guide/views/panels/text.md +++ b/mission-control/docs/guide/views/panels/text.md @@ -8,8 +8,8 @@ The `text` panel renders free-form text rows. Use it for short notes, callouts, ## Expected Columns -| Column | Type | Description | -|--------|------|-------------| +| Column | Type | Description | +| ------- | ------ | -------------------------- | | `value` | string | Text to display (required) | ## Example diff --git a/mission-control/docs/guide/views/queries/configs.md b/mission-control/docs/guide/views/queries/configs.md index 36f0e640..93c84ba8 100644 --- a/mission-control/docs/guide/views/queries/configs.md +++ b/mission-control/docs/guide/views/queries/configs.md @@ -8,16 +8,16 @@ Config queries fetch configuration items from the Flanksource catalog. ## Query Properties -| Property | Type | Description | -|----------|------|-------------| -| `types` | array | Config types to query (e.g., `["Kubernetes::Pod"]`) | -| `search` | string | Free text search (supports `@order=` for sorting) | -| `status` | string | Filter by status | -| `health` | string | Filter by health status | -| `tagSelector` | string | Filter by tags (e.g., `environment=prod,team=platform`) | -| `labelSelector` | string | Filter by Kubernetes-style labels | -| `agent` | string | Filter by agent ID (use `all` for all agents) | -| `limit` | integer | Maximum results to return | +| Property | Type | Description | +| --------------- | ------- | ------------------------------------------------------- | +| `types` | array | Config types to query (e.g., `["Kubernetes::Pod"]`) | +| `search` | string | Free text search (supports `@order=` for sorting) | +| `status` | string | Filter by status | +| `health` | string | Filter by health status | +| `tagSelector` | string | Filter by tags (e.g., `environment=prod,team=platform`) | +| `labelSelector` | string | Filter by Kubernetes-style labels | +| `agent` | string | Filter by agent ID (use `all` for all agents) | +| `limit` | integer | Maximum results to return | ## Example diff --git a/mission-control/docs/guide/views/queries/prometheus.md b/mission-control/docs/guide/views/queries/prometheus.md index fe02b972..a7efaf81 100644 --- a/mission-control/docs/guide/views/queries/prometheus.md +++ b/mission-control/docs/guide/views/queries/prometheus.md @@ -8,11 +8,11 @@ Prometheus queries fetch metrics directly from Prometheus using PromQL. ## Query Properties -| Property | Type | Description | -|----------|------|-------------| +| Property | Type | Description | +| ------------ | ------ | -------------------------------------------------------------------- | | `connection` | string | Prometheus connection reference (e.g., `connection://mc/prometheus`) | -| `query` | string | PromQL query expression | -| `columns` | object | Define column types for results (recommended) | +| `query` | string | PromQL query expression | +| `columns` | object | Define column types for results (recommended) | ## Example diff --git a/mission-control/docs/guide/views/queries/sql.md b/mission-control/docs/guide/views/queries/sql.md index 50a24fb6..ba5a740d 100644 --- a/mission-control/docs/guide/views/queries/sql.md +++ b/mission-control/docs/guide/views/queries/sql.md @@ -8,14 +8,14 @@ Use `sql` to run queries against external databases (PostgreSQL, MySQL, or SQL S ## Configuration -| Field | Description | -| ------------- | ------------------------------------------------------------- | -| `connection` | Name or URL of a stored SQL connection (recommended) | -| `type` | Connection type when not using `connection` (`postgres`, `mysql`, `sqlserver`) | -| `url` | Database DSN/URL (supports env var references) | -| `username` | Database username (supports env var references) | -| `password` | Database password (supports env var references) | -| `query` | SQL statement to execute | +| Field | Description | +| ------------ | ------------------------------------------------------------------------------ | +| `connection` | Name or URL of a stored SQL connection (recommended) | +| `type` | Connection type when not using `connection` (`postgres`, `mysql`, `sqlserver`) | +| `url` | Database DSN/URL (supports env var references) | +| `username` | Database username (supports env var references) | +| `password` | Database password (supports env var references) | +| `query` | SQL statement to execute | Mission Control hydrates the connection details before executing the query, so secrets can stay in stored connections or environment variables. diff --git a/mission-control/docs/guide/views/queries/view-table-selector.md b/mission-control/docs/guide/views/queries/view-table-selector.md index 51bbaea2..a743240c 100644 --- a/mission-control/docs/guide/views/queries/view-table-selector.md +++ b/mission-control/docs/guide/views/queries/view-table-selector.md @@ -15,11 +15,11 @@ View table selectors reuse cached data from other views instead of hitting the o ## Query Properties -| Property | Type | Description | -| --------------- | ------ | --------------------------------------------------------------------------- | -| `name` | string | Name of the view to query | -| `namespace` | string | Namespace of the view (default: `default`) | -| `labelSelector` | string | Optional label selector to match multiple views (for composition by label) | +| Property | Type | Description | +| --------------- | ------ | -------------------------------------------------------------------------- | +| `name` | string | Name of the view to query | +| `namespace` | string | Namespace of the view (default: `default`) | +| `labelSelector` | string | Optional label selector to match multiple views (for composition by label) | The selector returns **all rows** from the matched view tables. Shape or filter the data in your `merge` SQL or panel queries. diff --git a/mission-control/docs/guide/views/table/bytes.md b/mission-control/docs/guide/views/table/bytes.md index 38e54c53..bcc25467 100644 --- a/mission-control/docs/guide/views/table/bytes.md +++ b/mission-control/docs/guide/views/table/bytes.md @@ -9,10 +9,10 @@ The `bytes` column type displays byte sizes with automatic formatting (B, KB, MB ## Auto-Formatting | Input Value | Display | -|------------|---------| -| 512 | 512 B | -| 1048576 | 1 MB | -| 1073741824 | 1 GB | +| ----------- | ------- | +| 512 | 512 B | +| 1048576 | 1 MB | +| 1073741824 | 1 GB | ## Example diff --git a/mission-control/docs/guide/views/table/decimal.md b/mission-control/docs/guide/views/table/decimal.md index e0ee7520..e6b1d86a 100644 --- a/mission-control/docs/guide/views/table/decimal.md +++ b/mission-control/docs/guide/views/table/decimal.md @@ -8,10 +8,10 @@ The `decimal` column type displays precise floating-point numbers with configura ## Properties -| Property | Type | Description | -|----------|------|-------------| -| `precision` | integer | Number of decimal places | -| `unit` | string | Display unit (e.g., "$", "%") | +| Property | Type | Description | +| ----------- | ------- | ----------------------------- | +| `precision` | integer | Number of decimal places | +| `unit` | string | Display unit (e.g., "$", "%") | ## Example diff --git a/mission-control/docs/guide/views/table/gauge.md b/mission-control/docs/guide/views/table/gauge.md index 5fc918da..b838d036 100644 --- a/mission-control/docs/guide/views/table/gauge.md +++ b/mission-control/docs/guide/views/table/gauge.md @@ -8,12 +8,12 @@ The `gauge` column type displays numeric values as visual gauges with configurab ## Gauge Configuration -| Property | Type | Description | -|----------|------|-------------| -| `max` | string | Maximum value (can be CEL like `row.memory_limit`) | -| `min` | string | Minimum value | -| `precision` | int | Decimal places | -| `thresholds` | array | Color thresholds by percent | +| Property | Type | Description | +| ------------ | ------ | -------------------------------------------------- | +| `max` | string | Maximum value (can be CEL like `row.memory_limit`) | +| `min` | string | Minimum value | +| `precision` | int | Decimal places | +| `thresholds` | array | Color thresholds by percent | ## Example diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/number.md index c2008f16..3232805a 100644 --- a/mission-control/docs/guide/views/table/number.md +++ b/mission-control/docs/guide/views/table/number.md @@ -8,10 +8,10 @@ The `number` column type displays numeric values (integers and decimals). ## Properties -| Property | Type | Description | -|----------|------|-------------| -| `precision` | integer | Decimal places to display | -| `unit` | string | Display unit (e.g., "pods", "req/s") | +| Property | Type | Description | +| ----------- | ------- | ------------------------------------ | +| `precision` | integer | Decimal places to display | +| `unit` | string | Display unit (e.g., "pods", "req/s") | ## Example diff --git a/mission-control/docs/integrations/flux/catalog.md b/mission-control/docs/integrations/flux/catalog.md index f85a9d13..97aa4276 100644 --- a/mission-control/docs/integrations/flux/catalog.md +++ b/mission-control/docs/integrations/flux/catalog.md @@ -29,7 +29,6 @@ Mission Control provides built-in support for relating Flux resources to each ot - Enable ClickOps workflows backed by git. diff --git a/mission-control/docs/reference/canary-checker/check.md b/mission-control/docs/reference/canary-checker/check.md index 095a3db8..3d840469 100644 --- a/mission-control/docs/reference/canary-checker/check.md +++ b/mission-control/docs/reference/canary-checker/check.md @@ -2,25 +2,25 @@ title: Check --- -| Field | Description | Scheme | -| ---------------------- | ----------------------------------------------------------- | ------------------------------- | -| `id` | ID of the check | `uuid` | -| `canary_id` | ID of the canary | `uuid` | -| `agent_id` | ID of the agent | `uuid` | -| `type` | The type of the check | `string` | -| `name` | The name of the check | `string` | -| `namespace` | The namespace of the check | `string` | -| `labels` | The labels of the check | `map[string]string` | -| `description` | The description of the check | `string` | -| `status` | The status of the check _(healthy/unhealthy)_ | `string` | -| `owner` | The owner of the check | `string` | -| `severity` | The severity of the check _(info/low/medium/high/critical)_ | `string` | +| Field | Description | Scheme | +| ---------------------- | ----------------------------------------------------------- | ------------------------------------ | +| `id` | ID of the check | `uuid` | +| `canary_id` | ID of the canary | `uuid` | +| `agent_id` | ID of the agent | `uuid` | +| `type` | The type of the check | `string` | +| `name` | The name of the check | `string` | +| `namespace` | The namespace of the check | `string` | +| `labels` | The labels of the check | `map[string]string` | +| `description` | The description of the check | `string` | +| `status` | The status of the check _(healthy/unhealthy)_ | `string` | +| `owner` | The owner of the check | `string` | +| `severity` | The severity of the check _(info/low/medium/high/critical)_ | `string` | | `icon` | The icon of the check | [`Icon`](/docs/reference/types#icon) | -| `transformed` | The transformed of the check | `bool` | -| `last_runtime` | The last runtime of the check | `*time` | -| `next_runtime` | The next runtime of the check | `*time` | -| `last_transition_time` | The last transition time of the check | `*time` | -| `created_at` | The created at of the check | `time` | -| `updated_at` | The updated at of the check | `time` | -| `deleted_at` | The deleted at of the check | `*time` | -| `silenced_at` | The silenced at of the check | `*time` | +| `transformed` | The transformed of the check | `bool` | +| `last_runtime` | The last runtime of the check | `*time` | +| `next_runtime` | The next runtime of the check | `*time` | +| `last_transition_time` | The last transition time of the check | `*time` | +| `created_at` | The created at of the check | `time` | +| `updated_at` | The updated at of the check | `time` | +| `deleted_at` | The deleted at of the check | `*time` | +| `silenced_at` | The silenced at of the check | `*time` | diff --git a/mission-control/docs/reference/config-db/properties.md b/mission-control/docs/reference/config-db/properties.md index dc6a0d97..f72d3976 100644 --- a/mission-control/docs/reference/config-db/properties.md +++ b/mission-control/docs/reference/config-db/properties.md @@ -3,30 +3,30 @@ title: Property description: Property fields for config items --- -| Field | Description | Scheme | Required | -| ---------- | ---------------------------------------------------------------------------- | ------------------------------- | ---------- | -| `name` | Set name for component property. | `string` | | -| `value` | Mutually exclusive with `text` | `int64` | | -| `text` | Mutually exclusive with `value` | `string` | | -| `type` | Specify type of component property, one of `currency`, `number`, `url` | `string` | | -| `unit` | Unit for component property e.g. milliseconds, bytes, millicores, epoch etc. | `string` | | -| `color` | Set color for component property. | `string` | | -| `headline` | Toggle headline for component property. | `bool` | | +| Field | Description | Scheme | Required | +| ---------- | ---------------------------------------------------------------------------- | ------------------------------------ | ---------- | +| `name` | Set name for component property. | `string` | | +| `value` | Mutually exclusive with `text` | `int64` | | +| `text` | Mutually exclusive with `value` | `string` | | +| `type` | Specify type of component property, one of `currency`, `number`, `url` | `string` | | +| `unit` | Unit for component property e.g. milliseconds, bytes, millicores, epoch etc. | `string` | | +| `color` | Set color for component property. | `string` | | +| `headline` | Toggle headline for component property. | `bool` | | | `icon` | Specify icon for component. | [`Icon`](/docs/reference/types#icon) | | -| `label` | Specify label for component property. | `string` | | -| `links` | Set links pertaining to component. | [`[]Link`](#link) | | -| `max` | Set maximum value for components to display. | `int64` | `optional` | -| `min` | Set minimum value for components to display. | `int64` | | -| `order` | Set integer value order for component property. | `int` | | -| `tooltip` | Set tooltip outlining information pertaining to the component. | `string` | | +| `label` | Specify label for component property. | `string` | | +| `links` | Set links pertaining to component. | [`[]Link`](#link) | | +| `max` | Set maximum value for components to display. | `int64` | `optional` | +| `min` | Set minimum value for components to display. | `int64` | | +| `order` | Set integer value order for component property. | `int` | | +| `tooltip` | Set tooltip outlining information pertaining to the component. | `string` | | ## Link -| Field | Description | Schema | Required | -| --------- | ------------------------ | ------------------------------- | -------- | -| `type` | The type of the link. | `string` | | -| `url` | The url of the link. | `string` | | -| `tooltip` | The tooltip of the link. | `string` | | +| Field | Description | Schema | Required | +| --------- | ------------------------ | ------------------------------------ | -------- | +| `type` | The type of the link. | `string` | | +| `url` | The url of the link. | `string` | | +| `tooltip` | The tooltip of the link. | `string` | | | `icon` | The icon of the link. | [`Icon`](/docs/reference/types#icon) | | -| `text` | The text of the link. | `string` | | -| `label` | The label of the link. | `string` | | +| `text` | The text of the link. | `string` | | +| `label` | The label of the link. | `string` | | diff --git a/mission-control/docs/reference/config-db/scrape-result.md b/mission-control/docs/reference/config-db/scrape-result.md index 49dd3aee..7f2f78c1 100644 --- a/mission-control/docs/reference/config-db/scrape-result.md +++ b/mission-control/docs/reference/config-db/scrape-result.md @@ -3,21 +3,21 @@ title: Scrape Result description: Fields available during scrape transform --- -| Field | Description | Scheme | -| -------------- | ------------------------------------------------------ | ------------------------------- | -| `id` | Designated id (or the external id) of this config item | `string` | -| `config_class` | Class of the config item | `string` | -| `config_type` | Type of the config item | `string` | -| `status` | Status extracted from the config itself | `string` | -| `name` | Name of the config item | `string` | -| `namespace` | Namespace of the config item | `string` | -| `description` | Description of the config item | `string` | -| `aliases` | Aliases associated with the config item | `[]string` | -| `source` | Source of the config item | `string` | -| `config` | Configuration details | `interface{}` | -| `format` | Format of the config item | `string` | +| Field | Description | Scheme | +| -------------- | ------------------------------------------------------ | ------------------------------------ | +| `id` | Designated id (or the external id) of this config item | `string` | +| `config_class` | Class of the config item | `string` | +| `config_type` | Type of the config item | `string` | +| `status` | Status extracted from the config itself | `string` | +| `name` | Name of the config item | `string` | +| `namespace` | Namespace of the config item | `string` | +| `description` | Description of the config item | `string` | +| `aliases` | Aliases associated with the config item | `[]string` | +| `source` | Source of the config item | `string` | +| `config` | Configuration details | `interface{}` | +| `format` | Format of the config item | `string` | | `icon` | Icon associated with the config item | [`Icon`](/docs/reference/types#icon) | -| `tags` | Tags associated with the config item | `JSONStringMap` | -| `analysis` | Analysis result of the config item | `*AnalysisResult` | -| `action` | Action related to the config item | `string` | -| `properties` | Properties associated with the config item | `types.Properties` | +| `tags` | Tags associated with the config item | `JSONStringMap` | +| `analysis` | Analysis result of the config item | `*AnalysisResult` | +| `action` | Action related to the config item | `string` | +| `properties` | Properties associated with the config item | `types.Properties` | diff --git a/mission-control/docs/reference/playbooks/events.md b/mission-control/docs/reference/playbooks/events.md index d8ba8046..b44de5c4 100644 --- a/mission-control/docs/reference/playbooks/events.md +++ b/mission-control/docs/reference/playbooks/events.md @@ -8,11 +8,11 @@ Multiple playbooks could be listening to the same event and likewise a playbook Filters can give you fine-grained control over the events that can trigger the playbook. -| Field | Description | Scheme | Required | -| -------- | ------------------------------------------------------------------------------------- | ------------------------------- | -------- | -| `event` | Event to listen for. | `string` | `true` | +| Field | Description | Scheme | Required | +| -------- | ------------------------------------------------------------------------------------- | ------------------------------------ | -------- | +| `event` | Event to listen for. | `string` | `true` | | `filter` | Filter events to trigger on | [CEL](/docs/reference/scripting/cel) | `true` | -| `labels` | Labels specifies the key-value pairs that the associated event's resource must match. | `map[string]string` | `false` | +| `labels` | Labels specifies the key-value pairs that the associated event's resource must match. | `map[string]string` | `false` | ## Canary diff --git a/mission-control/docs/reference/playbooks/index.md b/mission-control/docs/reference/playbooks/index.md index 6537648c..cba9e2c0 100644 --- a/mission-control/docs/reference/playbooks/index.md +++ b/mission-control/docs/reference/playbooks/index.md @@ -5,24 +5,24 @@ sidebar_custom_props: icon: playbook --- -| Field | Description | Scheme | -| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | -| **`description`** | A short description | `string` | +| Field | Description | Scheme | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | +| **`description`** | A short description | `string` | | `icon` | Icon for the playbook | [`Icon`](/docs/reference/types#icon) | -| `timeout` | Maximum duration to let the playbook run before cancellation. Valid time units are "s", "m", "h", "d", "w", "y". Defaults to 30 minutes. | `string` | -| `on.canary` | Run a playbook when a health check fails or passes | [`EventTrigger`](./events#canary) | -| `on.component` | Run a playbook when a part becomes heathy/unhealthy | [`EventTrigger`](./events#component) | -| `on.config` | Run a playbook when someone creates/updates/deletes a config item or changes its state | [`EventTrigger`](./events#config) | -| `on.webhook` | Run a playbook when someone calls a webhook | [`Webhook`](./webhooks) | -| `runsOn` | Which [runner](/docs/guide/playbooks/concepts/runners) (agent) to run the playbook on | [`[]Agent`](/docs/reference/types#agent) | -| `templatesOn` | Where the templating of actions occurs
For `host` the templating occurs on the mission control instance before sending to the agent
For `agent` the templating occurs on the agent/runner where there might be secrets not accessible by the primary instance. | `host` or `agent` | +| `timeout` | Maximum duration to let the playbook run before cancellation. Valid time units are "s", "m", "h", "d", "w", "y". Defaults to 30 minutes. | `string` | +| `on.canary` | Run a playbook when a health check fails or passes | [`EventTrigger`](./events#canary) | +| `on.component` | Run a playbook when a part becomes heathy/unhealthy | [`EventTrigger`](./events#component) | +| `on.config` | Run a playbook when someone creates/updates/deletes a config item or changes its state | [`EventTrigger`](./events#config) | +| `on.webhook` | Run a playbook when someone calls a webhook | [`Webhook`](./webhooks) | +| `runsOn` | Which [runner](/docs/guide/playbooks/concepts/runners) (agent) to run the playbook on | [`[]Agent`](/docs/reference/types#agent) | +| `templatesOn` | Where the templating of actions occurs
For `host` the templating occurs on the mission control instance before sending to the agent
For `agent` the templating occurs on the agent/runner where there might be secrets not accessible by the primary instance. | `host` or `agent` | | `checks` | Which health checks this playbook can run on | [`[]ResourceSelector`](/docs/reference/resource-selector) | | `configs` | Which config items this playbook can run on | [`[]ResourceSelector`](/docs/reference/resource-selector) | | `components` | Which parts this playbook can run on | [`[]ResourceSelector`](/docs/reference/resource-selector) | | `env` | Variables to lookup, available as `env` map in templating/filters | [[]EnvVar](/docs/reference/env-var) | -| `parameters` | Variables that users need to enter. Do not use parameters for sensitive values. | [`[]Parameter`](./parameters) | -| `actions` | Individual actions or steps to perform | [`[]Action`](#actions) | -| `approval` | Optional approvals required before a playbook runs | [`Approval`](#approvals) | +| `parameters` | Variables that users need to enter. Do not use parameters for sensitive values. | [`[]Parameter`](./parameters) | +| `actions` | Individual actions or steps to perform | [`[]Action`](#actions) | +| `approval` | Optional approvals required before a playbook runs | [`Approval`](#approvals) | ## Run @@ -73,22 +73,22 @@ scheme: 'string', ## Actions -| Field | Description | Scheme | Required | -| --------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | -------- | -| **`name`** | Step Name | `string` | `true` | -| `runsOn` | Which [runner](/docs/guide/playbooks/concepts/runners) (agent) to run the action on | [`[]Agent`](/docs/reference/types#agent) | | -| `templatesOn` | Where templating (and secret management) of actions occurs | `host` or `agent` | | -| `delay` | A delay before running the action e.g. `8h` | [`Duration`](/docs/reference/types#duration) or [CEL](/docs/reference/scripting/cel) with [Playbook Context](./context) | | -| `filter` | Conditionally run an action | [CEL](/docs/reference/scripting/cel) with [Playbook Context](./context) | | -| `timeout` | Timeout on this action. | [`Duration`](/docs/reference/types#duration) | | -| `azureDevopsPipeline` | Trigger a pipeline run | [AzureDevops](/docs/guide/playbooks/actions/azure_devops_pipeline) | | -| `exec` | Run a script e.g. to use `kubectl` or `aws` `CLIs` | [Exec](/docs/guide/playbooks/actions/exec) | | -| `github` | Trigger Github Action | [Github Action](/docs/guide/playbooks/actions/github) | | -| `gitops` | Update a git repository (directly or via pull request) | [Gitops](/docs/guide/playbooks/actions/gitops) | | -| `http` | Call an HTTP Endpoint | [Http](/docs/guide/playbooks/actions/http) | | -| `sql` | Execute a SQL query | [Sql](/docs/guide/playbooks/actions/sql) | | -| `pod` | Run a kubernetes pod. | [Pod](/docs/guide/playbooks/actions/pod) | | -| `notification` | Specify notification of action. | [Notification](/docs/guide/playbooks/actions/notification) | | +| Field | Description | Scheme | Required | +| --------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------- | +| **`name`** | Step Name | `string` | `true` | +| `runsOn` | Which [runner](/docs/guide/playbooks/concepts/runners) (agent) to run the action on | [`[]Agent`](/docs/reference/types#agent) | | +| `templatesOn` | Where templating (and secret management) of actions occurs | `host` or `agent` | | +| `delay` | A delay before running the action e.g. `8h` | [`Duration`](/docs/reference/types#duration) or [CEL](/docs/reference/scripting/cel) with [Playbook Context](./context) | | +| `filter` | Conditionally run an action | [CEL](/docs/reference/scripting/cel) with [Playbook Context](./context) | | +| `timeout` | Timeout on this action. | [`Duration`](/docs/reference/types#duration) | | +| `azureDevopsPipeline` | Trigger a pipeline run | [AzureDevops](/docs/guide/playbooks/actions/azure_devops_pipeline) | | +| `exec` | Run a script e.g. to use `kubectl` or `aws` `CLIs` | [Exec](/docs/guide/playbooks/actions/exec) | | +| `github` | Trigger Github Action | [Github Action](/docs/guide/playbooks/actions/github) | | +| `gitops` | Update a git repository (directly or via pull request) | [Gitops](/docs/guide/playbooks/actions/gitops) | | +| `http` | Call an HTTP Endpoint | [Http](/docs/guide/playbooks/actions/http) | | +| `sql` | Execute a SQL query | [Sql](/docs/guide/playbooks/actions/sql) | | +| `pod` | Run a kubernetes pod. | [Pod](/docs/guide/playbooks/actions/pod) | | +| `notification` | Specify notification of action. | [Notification](/docs/guide/playbooks/actions/notification) | | > Only 1 action should be specified per step diff --git a/mission-control/docs/reference/resource-selector.md b/mission-control/docs/reference/resource-selector.md index de9d4591..d0bc489b 100644 --- a/mission-control/docs/reference/resource-selector.md +++ b/mission-control/docs/reference/resource-selector.md @@ -10,5 +10,3 @@ import ResourceSelector from '@site/docs/snippets/\_resource-selector.mdx'; # Resource Selectors - - diff --git a/prompts/blog.md b/prompts/blog.md index b817d0aa..54804c39 100644 --- a/prompts/blog.md +++ b/prompts/blog.md @@ -2,7 +2,7 @@ Write a 1250-1500 introductor blog post for a DevOps / Platform Engineering focu The tone should be developer-friendly, technical and informative without sounding salesy or promotional. -The writing should have no fluff, use short punchy sentences, avoid buzzwords and speak like a senior engineer would. +The writing should have no fluff, use short punchy sentences, avoid buzzwords and speak like a senior engineer would. The purpose of this copy is to generate interest in a new approach to a feature, educate DevOps engineers, increase awareness and reduce friction to trial @@ -16,7 +16,7 @@ Format the output in raw markdown suitable for copy and pasting into vscode. Write a blog post on Flanksource MIssion Control approach to AIops, primarily building a real-time and update to mirror state of cloud resources that can be queried rapidly, plus an advanced graph that builds relationships between resources e.g. Cloudformation -> Auto Scaling Group > EC2 instance and then layers on soft relationsyhips like ebs volumes, subnets, IAM poilcies - For Kubernetes it understands Flux and Gitops being able to build a graph of a Flux Kustomization object creating a HelmRelease CRD, which then creates a deployment -> replicset -> pod and then layeying relationships like services, nodes, PVC, ingress, etc.. -State based alerting (i.e. whene resource self-report failure) and traditioanl alerts from APM tools trigger playbooks that can then proactively collect infomation in a distrubuted fashion from agents deployed closest to the data, the graph, changes to the graph resources, events and pro-acrtive playboks are then fed into the model which tan the recommend futher playbooks to execute. +State based alerting (i.e. whene resource self-report failure) and traditioanl alerts from APM tools trigger playbooks that can then proactively collect infomation in a distrubuted fashion from agents deployed closest to the data, the graph, changes to the graph resources, events and pro-acrtive playboks are then fed into the model which tan the recommend futher playbooks to execute. This is advantage as acess to systems is pushed down to agents who can use secrets like pod identity and service accounts to collect duta, new agent actions are use to create with YAML based playbooks. @@ -26,30 +26,27 @@ contrasting metrics vs state driven alerting, store with concepts such as RED an Highlight the drawbacks of the canary-checker approach that is poll-based and does not scale very well and demononstrate how https://github.com/flanksource/config-db takes this one step further by using a state driven approach that watches for changes to cloud resources, and then fires events when the state becomes unhealthy. - - is more scalable and can be used to monitor the health of a cluster or application in real-time. +is more scalable and can be used to monitor the health of a cluster or application in real-time. Optionally, include {optional elements} (e.g. a strong CTA, technical example, code snippet, customer proof, comparison table). - Act as a technical blog writer targeting devops and platform engineers working with Kubernetes, GitOps, Helm and Flux, when editing and rewriting content follow these instructions strictly: 1. Use the following outline for the blog: - * Introduction - introduce the topic of the blog with a pain point or teaser - * Background - Describe the context and initial challenges. - * Step by step guide - * Common Pitfalls - Highlight common mistakes and how to avoid them and add use-cases that are not a good fiit - * Conclustion - Offer final thoughts and potential future implications. + - Introduction - introduce the topic of the blog with a pain point or teaser + - Background - Describe the context and initial challenges. + - Step by step guide + - Common Pitfalls - Highlight common mistakes and how to avoid them and add use-cases that are not a good fiit + - Conclustion - Offer final thoughts and potential future implications. 2. Write at a Grade 10 level 3. Use clear, concise simple language, even when explaining complex topics. 4. Bias toward short sentences. 5. Mix and match lists and paragraphs 6. Do not use any salesy or marketing terms, Do not use adverbs 7. Use MDX formatting -8. Precede every command with an explanation of what the command does. After the command, provide additional details about the command, such as what the arguments do and why your reader is using them. -9. Explicitly tell the user to create or open each file you’ll have them use. +8. Precede every command with an explanation of what the command does. After the command, provide additional details about the command, such as what the arguments do and why your reader is using them. +9. Explicitly tell the user to create or open each file you’ll have them use. 10. Like commands, always introduce a file or script by describing its general purpose, then explain any changes that the reader will be making in the file. Without these explanations, readers won’t be able to customize, update, or troubleshoot issues in the long run. 11. If you’re asking the reader to write code, follow the same approach for commands: introduce the code block with a high-level explanation of what it does. Then show the code, and then call out any important details. 12. Do not use the term "this document", when referring to the system or product being documented always use "Mission Control" 13. Ensure all examples and use cases are relevant - diff --git a/prompts/style.md b/prompts/style.md index e95a2c4c..3adc8093 100644 --- a/prompts/style.md +++ b/prompts/style.md @@ -5,26 +5,31 @@ Follow these strict rules: 1. Avoid adverbs and complex language ## Formating + - Format all output using MDX (markdowon) - Format code and examples using this example: ```yaml title=some-title.yaml + ``` + - Do not remove any "```" or "//highlight-next-line" text - Follow standard markdown rules provided by markdownlint - ## Verb Tense + - Use present tense verbs instead of future tense. - Say "this happens" rather than "this will happen." - Avoid words like "will," "shall," "won't," "shan't," and contractions with "'ll." ## Voice + - Do not use first person (I, me, my, mine, we, our). - Avoid phrases like "I'd," "I'll," "I'm," and "I've." - Use passive voice sparingly. Active voice is generally clearer. ## Inclusive Language + - Use considerate language that respects all readers. - Use "they" as a singular pronoun instead of "he/she" or "s/he." - Avoid terms that might be insensitive: @@ -35,11 +40,13 @@ Follow these strict rules: - Avoid phrases like "fall on deaf ears" or "blind spot" ## Tone + - Don't assume success with statements like "congratulations," "that's it," or "you did it." - Avoid condescending terms like "obvious," "obviously," "simple," "simply," "easy," "easily," "of course," "clearly," or "everyone knows." - Don't add "-ly" to ordinal numbers (avoid "firstly," "secondly," etc.) ## Clarity and Brevity + - Use simple words instead of complex ones. - Avoid foreign phrases like "i.e.," "viz.," or "ergo." - Eliminate wordiness and redundant phrases: diff --git a/scripts/README.md b/scripts/README.md index 380c5dc0..7f99d17b 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -50,4 +50,4 @@ The script resolves code imports in two formats: 1. Regular paths: `file="../examples/config.yaml"` 2. Root paths: `file=/modules/examples/config.yaml"` -Failed imports will be noted in the output with error messages. \ No newline at end of file +Failed imports will be noted in the output with error messages. From 48b53e807218e6a69ba5f843f27d250725f3638f Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Thu, 4 Dec 2025 14:26:19 +0545 Subject: [PATCH 7/8] update: fixture reference --- .../docs/guide/views/queries/sql.md | 2 +- .../docs/guide/views/table/boolean.md | 2 +- .../docs/guide/views/table/datetime.md | 2 +- .../docs/guide/views/table/decimal.md | 20 ------------------- .../docs/guide/views/table/labels.md | 2 +- .../docs/guide/views/table/number.md | 2 +- 6 files changed, 5 insertions(+), 25 deletions(-) delete mode 100644 mission-control/docs/guide/views/table/decimal.md diff --git a/mission-control/docs/guide/views/queries/sql.md b/mission-control/docs/guide/views/queries/sql.md index ba5a740d..ba8ecd68 100644 --- a/mission-control/docs/guide/views/queries/sql.md +++ b/mission-control/docs/guide/views/queries/sql.md @@ -21,7 +21,7 @@ Mission Control hydrates the connection details before executing the query, so s ## Example -```yaml title="sql-incidents.yaml" file=/modules/mission-control/fixtures/views/sql-incidents.yaml {7-28} +```yaml title="failing-health-checks.yaml" file=/modules/mission-control/fixtures/views/failing-health-checks.yaml {33-59} ``` diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/boolean.md index b671ee9e..6866bc1d 100644 --- a/mission-control/docs/guide/views/table/boolean.md +++ b/mission-control/docs/guide/views/table/boolean.md @@ -8,7 +8,7 @@ The `boolean` column type renders `true`/`false` values as friendly yes/no text ## Example -```yaml title="boolean-example.yaml" file=/modules/mission-control/fixtures/views/boolean-example.yaml {7-27} +```yaml title="boolean-example.yaml" file=/modules/mission-control/fixtures/views/boolean-example.yaml {24-26} ``` diff --git a/mission-control/docs/guide/views/table/datetime.md b/mission-control/docs/guide/views/table/datetime.md index 5402f0c5..dcce45ae 100644 --- a/mission-control/docs/guide/views/table/datetime.md +++ b/mission-control/docs/guide/views/table/datetime.md @@ -8,6 +8,6 @@ The `datetime` column type displays timestamps with human-readable formatting. ## Example -```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {30-31} +```yaml title="cronjobs.yaml" file=/modules/mission-control/fixtures/views/cronjobs.yaml {32-33} ``` diff --git a/mission-control/docs/guide/views/table/decimal.md b/mission-control/docs/guide/views/table/decimal.md deleted file mode 100644 index e6b1d86a..00000000 --- a/mission-control/docs/guide/views/table/decimal.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Decimal -sidebar_custom_props: - icon: mdi:decimal ---- - -The `decimal` column type displays precise floating-point numbers with configurable decimal places. - -## Properties - -| Property | Type | Description | -| ----------- | ------- | ----------------------------- | -| `precision` | integer | Number of decimal places | -| `unit` | string | Display unit (e.g., "$", "%") | - -## Example - -```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {76-80} - -``` diff --git a/mission-control/docs/guide/views/table/labels.md b/mission-control/docs/guide/views/table/labels.md index 2b6e7eff..efc09b41 100644 --- a/mission-control/docs/guide/views/table/labels.md +++ b/mission-control/docs/guide/views/table/labels.md @@ -8,7 +8,7 @@ The `labels` column type renders key/value labels and supports include/exclude f ## Example -```yaml title="labels.yaml" file=/modules/mission-control/fixtures/views/labels.yaml {17-20} +```yaml title="pods.yaml" file=/modules/mission-control/fixtures/views/pods.yaml {49-50} ``` diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/number.md index 3232805a..52ff2dcc 100644 --- a/mission-control/docs/guide/views/table/number.md +++ b/mission-control/docs/guide/views/table/number.md @@ -15,6 +15,6 @@ The `number` column type displays numeric values (integers and decimals). ## Example -```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/notification-send-history.yaml {115-119} +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/notification-send-history.yaml {27-30} ``` From c08c5c5a0cd2ea693b68d41723638369ea4481f8 Mon Sep 17 00:00:00 2001 From: Aditya Thebe Date: Thu, 4 Dec 2025 14:36:07 +0545 Subject: [PATCH 8/8] chore: migrate columns --- mission-control-chart | 2 +- .../guide/views/table/{ => columns}/badge.md | 0 .../views/table/{ => columns}/boolean.md | 0 .../guide/views/table/{ => columns}/bytes.md | 0 .../views/table/{ => columns}/config-item.md | 0 .../views/table/{ => columns}/datetime.md | 0 .../views/table/{ => columns}/duration.md | 0 .../guide/views/table/{ => columns}/gauge.md | 0 .../guide/views/table/{ => columns}/health.md | 0 .../guide/views/table/{ => columns}/index.mdx | 5 +- .../guide/views/table/{ => columns}/labels.md | 0 .../views/table/{ => columns}/millicore.md | 0 .../guide/views/table/{ => columns}/number.md | 0 .../guide/views/table/{ => columns}/status.md | 0 .../guide/views/table/{ => columns}/string.md | 0 .../docs/guide/views/table/index.md | 47 +++++++++++++++++++ modules/canary-checker | 2 +- modules/config-db | 2 +- modules/duty | 2 +- modules/mission-control | 2 +- modules/mission-control-chart | 2 +- modules/mission-control-registry | 2 +- 22 files changed, 56 insertions(+), 10 deletions(-) rename mission-control/docs/guide/views/table/{ => columns}/badge.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/boolean.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/bytes.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/config-item.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/datetime.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/duration.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/gauge.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/health.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/index.mdx (96%) rename mission-control/docs/guide/views/table/{ => columns}/labels.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/millicore.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/number.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/status.md (100%) rename mission-control/docs/guide/views/table/{ => columns}/string.md (100%) create mode 100644 mission-control/docs/guide/views/table/index.md diff --git a/mission-control-chart b/mission-control-chart index c53bd62b..2a91080d 160000 --- a/mission-control-chart +++ b/mission-control-chart @@ -1 +1 @@ -Subproject commit c53bd62b539b63059121bd096b8262ec3773cfbb +Subproject commit 2a91080def4f14679f38331c6b0fe05f610380cd diff --git a/mission-control/docs/guide/views/table/badge.md b/mission-control/docs/guide/views/table/columns/badge.md similarity index 100% rename from mission-control/docs/guide/views/table/badge.md rename to mission-control/docs/guide/views/table/columns/badge.md diff --git a/mission-control/docs/guide/views/table/boolean.md b/mission-control/docs/guide/views/table/columns/boolean.md similarity index 100% rename from mission-control/docs/guide/views/table/boolean.md rename to mission-control/docs/guide/views/table/columns/boolean.md diff --git a/mission-control/docs/guide/views/table/bytes.md b/mission-control/docs/guide/views/table/columns/bytes.md similarity index 100% rename from mission-control/docs/guide/views/table/bytes.md rename to mission-control/docs/guide/views/table/columns/bytes.md diff --git a/mission-control/docs/guide/views/table/config-item.md b/mission-control/docs/guide/views/table/columns/config-item.md similarity index 100% rename from mission-control/docs/guide/views/table/config-item.md rename to mission-control/docs/guide/views/table/columns/config-item.md diff --git a/mission-control/docs/guide/views/table/datetime.md b/mission-control/docs/guide/views/table/columns/datetime.md similarity index 100% rename from mission-control/docs/guide/views/table/datetime.md rename to mission-control/docs/guide/views/table/columns/datetime.md diff --git a/mission-control/docs/guide/views/table/duration.md b/mission-control/docs/guide/views/table/columns/duration.md similarity index 100% rename from mission-control/docs/guide/views/table/duration.md rename to mission-control/docs/guide/views/table/columns/duration.md diff --git a/mission-control/docs/guide/views/table/gauge.md b/mission-control/docs/guide/views/table/columns/gauge.md similarity index 100% rename from mission-control/docs/guide/views/table/gauge.md rename to mission-control/docs/guide/views/table/columns/gauge.md diff --git a/mission-control/docs/guide/views/table/health.md b/mission-control/docs/guide/views/table/columns/health.md similarity index 100% rename from mission-control/docs/guide/views/table/health.md rename to mission-control/docs/guide/views/table/columns/health.md diff --git a/mission-control/docs/guide/views/table/index.mdx b/mission-control/docs/guide/views/table/columns/index.mdx similarity index 96% rename from mission-control/docs/guide/views/table/index.mdx rename to mission-control/docs/guide/views/table/columns/index.mdx index 95078bce..3ce712da 100644 --- a/mission-control/docs/guide/views/table/index.mdx +++ b/mission-control/docs/guide/views/table/columns/index.mdx @@ -1,8 +1,7 @@ --- -sidebar_position: 3 -title: Table Columns +title: Columns sidebar_custom_props: - icon: view-details + icon: mdi:table-column --- Tables define the structure and display of view data. Each column has a type that controls how values are rendered and filtered. diff --git a/mission-control/docs/guide/views/table/labels.md b/mission-control/docs/guide/views/table/columns/labels.md similarity index 100% rename from mission-control/docs/guide/views/table/labels.md rename to mission-control/docs/guide/views/table/columns/labels.md diff --git a/mission-control/docs/guide/views/table/millicore.md b/mission-control/docs/guide/views/table/columns/millicore.md similarity index 100% rename from mission-control/docs/guide/views/table/millicore.md rename to mission-control/docs/guide/views/table/columns/millicore.md diff --git a/mission-control/docs/guide/views/table/number.md b/mission-control/docs/guide/views/table/columns/number.md similarity index 100% rename from mission-control/docs/guide/views/table/number.md rename to mission-control/docs/guide/views/table/columns/number.md diff --git a/mission-control/docs/guide/views/table/status.md b/mission-control/docs/guide/views/table/columns/status.md similarity index 100% rename from mission-control/docs/guide/views/table/status.md rename to mission-control/docs/guide/views/table/columns/status.md diff --git a/mission-control/docs/guide/views/table/string.md b/mission-control/docs/guide/views/table/columns/string.md similarity index 100% rename from mission-control/docs/guide/views/table/string.md rename to mission-control/docs/guide/views/table/columns/string.md diff --git a/mission-control/docs/guide/views/table/index.md b/mission-control/docs/guide/views/table/index.md new file mode 100644 index 00000000..4632ddd4 --- /dev/null +++ b/mission-control/docs/guide/views/table/index.md @@ -0,0 +1,47 @@ +--- +slug: /guide/table +title: Table +sidebar_position: 6 +sidebar_custom_props: + icon: view-details +--- + +Tables are the primary way to explore view data in Mission Control. They render rows from your queries, apply mappings, and drive filters, cards, and links into configs or other views. + +## When to Use + +- You need sortable, filterable rows for configs, changes, or metrics. +- You want to mix multiple data sources into one grid via SQL `merge`. +- You want card layouts (titles, subtitles, gauges) backed by the same table data. + +## Anatomy of a Table View + +- **columns**: Define the schema and rendering (type, filters, card placement, URLs). +- **queries**: Pull data from configs, changes, Prometheus, SQL, or other views. +- **merge**: Optional SQL to join multiple queries into one result set. +- **mapping**: Optional CEL to reshape query fields into your columns. +- **templating**: Variables used inside queries and filters for user-scoped data. + +## Example: Namespace Table + +This view shows how card positioning, gauges, and filters are driven by columns: + +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {7-66} + +``` + +### Joining Multiple Data Sources + +Use `merge` to combine configs with Prometheus metrics into one table: + +```yaml title="namespace.yaml" file=/modules/mission-control/fixtures/views/namespace.yaml {85-114} + +``` + +## Best Practices + +- Always set `primaryKey` on at least one column (composite keys allowed). +- Prefer `mapping` to normalize field names and units (e.g., bytes, millicores). +- Keep `merge` focused on shaping/joins; leave presentation to columns. +- Enable `filter.type: multiselect` on columns users need to slice without refresh. +- Use templated variables for scoping (e.g., cluster/namespace) instead of hard-coding tags. diff --git a/modules/canary-checker b/modules/canary-checker index 806a8ba3..379f28f0 160000 --- a/modules/canary-checker +++ b/modules/canary-checker @@ -1 +1 @@ -Subproject commit 806a8ba3ca9357cc8ba1c09d97bf4ac6e92584de +Subproject commit 379f28f0ed6de8a2575d0b833ec7ce2031966a32 diff --git a/modules/config-db b/modules/config-db index 4d7b9237..f26106b2 160000 --- a/modules/config-db +++ b/modules/config-db @@ -1 +1 @@ -Subproject commit 4d7b9237164e0931e31286927fa7c0e48ee8fc23 +Subproject commit f26106b24ae909a29d588d483374923abcfb6f4e diff --git a/modules/duty b/modules/duty index 38310f70..744f283f 160000 --- a/modules/duty +++ b/modules/duty @@ -1 +1 @@ -Subproject commit 38310f7004af13dc628d61fd430f89fbc345cc64 +Subproject commit 744f283f8783e607bd6a78d2477ebf1e998dd080 diff --git a/modules/mission-control b/modules/mission-control index fa1448e7..b76b2b28 160000 --- a/modules/mission-control +++ b/modules/mission-control @@ -1 +1 @@ -Subproject commit fa1448e7bb20ff5cb5797b4b3a0b8d9d9d9bae49 +Subproject commit b76b2b284613bc987064cc8d2e3eba0f4a2ba8ab diff --git a/modules/mission-control-chart b/modules/mission-control-chart index c53bd62b..2a91080d 160000 --- a/modules/mission-control-chart +++ b/modules/mission-control-chart @@ -1 +1 @@ -Subproject commit c53bd62b539b63059121bd096b8262ec3773cfbb +Subproject commit 2a91080def4f14679f38331c6b0fe05f610380cd diff --git a/modules/mission-control-registry b/modules/mission-control-registry index 145d4761..3acb35cf 160000 --- a/modules/mission-control-registry +++ b/modules/mission-control-registry @@ -1 +1 @@ -Subproject commit 145d476118a30aca6dd62e04783139d5edbcb07b +Subproject commit 3acb35cfda6c27d637efe8fd8e38bf7f07bb0110