From 2e91fdb637ce7074d52925c6364a1c9dbb44bf1e Mon Sep 17 00:00:00 2001 From: Circadian Date: Thu, 6 Aug 2026 02:46:28 +0200 Subject: [PATCH 1/2] Add llms.txt to docs site, document it in AGENTS.md Adds docs/public/llms.txt, served at the site root, listing all docs pages with a one-line description for AI assistants and other automated readers. Generated from the Starlight content tree; the generator config is committed at docs/starlight-docs/llms-txt/ so the file can be rebuilt as pages change. Updates AGENTS.md and CONTRIBUTING.md to mark llms.txt as a maintained, generated artifact and describe when to regenerate it. CLAUDE.md is a symlink to AGENTS.md, so that edit covers both files. llms-full.txt is intentionally not included: 34 of 138 pages are MDX files importing Starlight components, which the generator cannot render, so a full-content export would be degraded. Noted as a known limitation in the PR description. Closes #262 Signed-off-by: Circadian-agent <309102505+Circadian-agent@users.noreply.github.com> --- AGENTS.md | 5 + CONTRIBUTING.md | 9 + docs/public/llms.txt | 190 ++++++++++++++++++ docs/starlight-docs/llms-txt/gen-config.mjs | 172 ++++++++++++++++ .../llms-txt/postprocess-llms.mjs | 86 ++++++++ .../starlight-docs/llms-txt/sourcey.config.ts | 128 ++++++++++++ 6 files changed, 590 insertions(+) create mode 100644 docs/public/llms.txt create mode 100644 docs/starlight-docs/llms-txt/gen-config.mjs create mode 100644 docs/starlight-docs/llms-txt/postprocess-llms.mjs create mode 100644 docs/starlight-docs/llms-txt/sourcey.config.ts diff --git a/AGENTS.md b/AGENTS.md index b7820b99..f928ffe9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -862,6 +862,11 @@ The docs site is built with [Starlight](https://starlight.astro.build/) (Astro). - **Do not use frontmatter `sidebar.label` or `sidebar.order` to control group/section headings.** Frontmatter only controls individual page labels, not the group name shown in the sidebar for a directory. Use explicit `items` with `label` in `astro.config.mjs` instead (see "Send Data" and "Get Started" sections as examples). - Sections using `autogenerate` derive group labels from directory names (lowercase). Replace `autogenerate` with explicit `items` when proper casing or custom ordering is needed. +**llms.txt:** +- `docs/public/llms.txt` is a maintained artifact, served at the site root (`https://observability.opensearch.org/llms.txt`). It lists every docs page with a one-line description, for AI assistants and other automated readers. +- It is generated, not hand-written. Regenerate it whenever a page is added, removed, or renamed, or a page's `title`/`description` frontmatter changes. Do not hand-edit `docs/public/llms.txt` directly. +- The generator config lives in `docs/starlight-docs/llms-txt/`. All links in the file are fully qualified `https://observability.opensearch.org/...` URLs, not relative paths, because the file is read out of page context. + ### Icons Use OpenSearch UI (OUI) icons for documentation components. Browse the full set at https://oui.opensearch.org/1.23/#/display/icons. SVG sources are at https://github.com/opensearch-project/oui/tree/main/src/components/icon/assets. Prefer 32x32 icons over 16x16 for consistent sizing. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 190676aa..fe488516 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -391,6 +391,15 @@ AI coding assistants are welcome to contribute! When contributing as an AI agent - Include configuration patterns - Keep AI-assistant focused +### llms.txt + +`docs/public/llms.txt` is a first-class doc artifact, on the same footing as README.md and AGENTS.md. It lists every page in the docs site with a one-line description, served at the site root for AI assistants and other automated readers. + +Update it whenever you change something it reflects: adding, removing, or renaming a docs page, or changing a page's `title` or `description` frontmatter. + +- Do not hand-edit `docs/public/llms.txt`. It is generated; regenerate it instead using the config in `docs/starlight-docs/llms-txt/`. +- After regenerating, check that every link is a fully qualified `https://observability.opensearch.org/...` URL, not a relative `/docs/...` path, and that the title and tagline lines at the top are unchanged. + ### Code Comments - Explain *why*, not just *what* diff --git a/docs/public/llms.txt b/docs/public/llms.txt new file mode 100644 index 00000000..ced56593 --- /dev/null +++ b/docs/public/llms.txt @@ -0,0 +1,190 @@ +# OpenSearch Observability Stack + +> Open-source, OpenTelemetry-native observability for services and AI agents. + +## Overview + +- [OpenSearch Observability Stack](https://observability.opensearch.org/docs/): Open-source, OpenTelemetry-native observability for services and AI agents. + +## Agent Health + +- [Agent Health](https://observability.opensearch.org/docs/agent-health/): Evaluation and observability framework for AI agents with Golden Path trajectory comparison +- [CLI Reference](https://observability.opensearch.org/docs/agent-health/cli/): Command-line interface reference for Agent Health +- [Configuration](https://observability.opensearch.org/docs/agent-health/configuration/): Configure Agent Health to connect your AI agent, set up storage, and customize evaluation behavior +- [Connectors](https://observability.opensearch.org/docs/agent-health/configuration/connectors/): Create custom connectors for Agent Health to support different AI agent protocols +- [Evaluations](https://observability.opensearch.org/docs/agent-health/evaluations/): How Agent Health evaluates AI agents using Golden Path trajectory comparison and LLM judges +- [Experiments](https://observability.opensearch.org/docs/agent-health/evaluations/experiments/): Run batch evaluations and compare AI agent performance across configurations +- [Test Cases](https://observability.opensearch.org/docs/agent-health/evaluations/test-cases/): Create and manage test cases for AI agent evaluation in Agent Health +- [Getting Started](https://observability.opensearch.org/docs/agent-health/getting-started/): Install Agent Health and run your first AI agent evaluation +- [Trace Visualization](https://observability.opensearch.org/docs/agent-health/traces/): Real-time trace monitoring and comparison for AI agent executions in Agent Health + +## AI Observability + +- [AI Observability](https://observability.opensearch.org/docs/ai-observability/): Observe, debug, and evaluate AI agent workflows with OpenTelemetry GenAI conventions +- [Agent Traces](https://observability.opensearch.org/docs/ai-observability/agent-tracing/): Explore, debug, and monitor AI agent execution traces in OpenSearch Dashboards +- [Agent Graph & Path](https://observability.opensearch.org/docs/ai-observability/agent-tracing/graph/): Visualize agent execution as a directed graph with interactive flow diagrams, tree views, and timeline charts +- [Evaluation & Scoring](https://observability.opensearch.org/docs/ai-observability/evaluation/): Score agent traces, run experiments against datasets, and upload evaluation results +- [Evaluation Integrations](https://observability.opensearch.org/docs/ai-observability/evaluation-integrations/): Bridge external evaluation frameworks like DeepEval, RAGAS, MLflow, and pytest into the observability stack +- [Getting Started](https://observability.opensearch.org/docs/ai-observability/getting-started/): Instrument an AI agent, view traces, and score quality - end to end in 5 minutes + +## Alerting + +- [Alerting](https://observability.opensearch.org/docs/alerting/): Configure monitors, triggers, and notifications to alert on observability data +- [Unified Alerts View](https://observability.opensearch.org/docs/alerting/unified-alerts/): One list for OpenSearch monitors and Prometheus alerts, with rules and routing in the same app + +## Anomaly Detection + +- [Anomaly Detection](https://observability.opensearch.org/docs/anomaly-detection/): Detect anomalies in your observability data using machine learning + +## Application Monitoring + +- [Application Monitoring](https://observability.opensearch.org/docs/apm/): Monitor application performance with service maps, RED metrics, and service-level views +- [Configuring APM in OpenSearch Dashboards](https://observability.opensearch.org/docs/apm/configuring-apm/): Create datasets, index patterns, and connect data sources to enable APM features +- [Configuring Telemetry Ingestion](https://observability.opensearch.org/docs/apm/configuring-telemetry-ingestion/): Set up the OpenTelemetry Collector and Data Prepper to ingest traces, logs, and metrics for APM +- [Application Map](https://observability.opensearch.org/docs/apm/service-map/): Visualize service dependencies and communication patterns +- [Services](https://observability.opensearch.org/docs/apm/services/): Browse the service catalog, inspect service health, and drill into operations and dependencies +- [Sizing Calculator](https://observability.opensearch.org/docs/apm/sizing-calculator/): Estimate APM storage, metrics, and ingest requirements based on your workload + +## Claude Code + +- [Claude Code](https://observability.opensearch.org/docs/claude-code/): Give Claude observability skills for querying traces, logs, and metrics from your OpenSearch stack +- [Showcase](https://observability.opensearch.org/docs/claude-code/showcase/): Real-world examples demonstrating the power of Claude Code with observability data +- [Usage Guide](https://observability.opensearch.org/docs/claude-code/usage/): Sample questions and real-world workflows for each observability skill + +## Dashboards & Visualize + +- [Dashboards & Visualize](https://observability.opensearch.org/docs/dashboards/): Build, customize, and share observability dashboards in OpenSearch +- [Build a Dashboard](https://observability.opensearch.org/docs/dashboards/build/): Create dashboards, add visualization panels, and arrange layouts for observability monitoring +- [Sharing Dashboards](https://observability.opensearch.org/docs/dashboards/sharing/): Share dashboards, export reports, and manage dashboard best practices +- [Troubleshooting Dashboards](https://observability.opensearch.org/docs/dashboards/troubleshooting/): Diagnose and fix common issues with dashboard panels, visualizations, and performance +- [Dashboard Variables](https://observability.opensearch.org/docs/dashboards/variables/): Parameterize dashboards with dropdown variables that drive panel queries +- [Managing dashboard variables](https://observability.opensearch.org/docs/dashboards/variables/managing-variables/): You can create, edit, delete, organize, and view dashboard variables from within a dashboard. +- [Using dashboard variables](https://observability.opensearch.org/docs/dashboards/variables/using-variables/): You can reference dashboard variables in queries in the visualization editor to create dynamic, interactive dashboards. +- [Creating visualizations using queries](https://observability.opensearch.org/docs/dashboards/visualize/): The _visualization editor_ lets you create visualizations by writing Piped Processing Language (PPL) or Prometheus Query Language (PromQL) queries. The editor automatically maps query result fields to chart axes and suggests a chart type based on the shape of your data. +- [Area chart](https://observability.opensearch.org/docs/dashboards/visualize/area-chart/): An area chart plots data points connected by lines with the region below filled in, making it ideal for visualizing volume and composition over time. You can stack multiple series to see how each category contributes to the total. +- [Bar chart](https://observability.opensearch.org/docs/dashboards/visualize/bar-chart/): A bar chart displays data as vertical or horizontal bars, making it ideal for comparing discrete categories. You can use a Color field to break categories into sub-groups and add threshold lines to flag values higher or lower than a target. +- [Bar gauge chart](https://observability.opensearch.org/docs/dashboards/visualize/bar-gauge-chart/): A bar gauge chart displays numeric values as horizontal or vertical bars against a scale, reducing each field to a single value. Unlike a bar chart, a bar gauge chart is designed for comparing values against defined thresholds. +- [Configuring visualizations](https://observability.opensearch.org/docs/dashboards/visualize/configuring-visualizations/): The visualization editor provides shared configuration options that apply across multiple visualization types. Each visualization type page documents its specific options. The following configurations are common to most visualizations. +- [Thresholds](https://observability.opensearch.org/docs/dashboards/visualize/configuring-visualizations/thresholds/): A threshold is a boundary value that, when reached or exceeded by a data point, triggers a visual change in color. Use thresholds to define meaningful ranges so that you can immediately understand whether values are within normal, warning, or critical zones. +- [Value calculations](https://observability.opensearch.org/docs/dashboards/visualize/configuring-visualizations/value-calculations/): When a visualization receives a numeric field, the data often contains a series of values rather than a single number. Use the **Calculation** setting to select a reducer function that aggregates the series into one representative value for display. +- [Gauge chart](https://observability.opensearch.org/docs/dashboards/visualize/gauge-chart/): A gauge chart displays a single numeric value on a semicircular arc, making it ideal for showing how a metric compares against defined thresholds or a target range. +- [Heatmap](https://observability.opensearch.org/docs/dashboards/visualize/heatmap-chart/): A heatmap uses color to represent the magnitude of values in a dataset. Each cell in the map corresponds to a combination of two dimensions, with the cell's color intensity reflecting the value associated with that combination. +- [Histogram](https://observability.opensearch.org/docs/dashboards/visualize/histogram-chart/): A histogram chart displays the distribution of a numeric field by grouping values into bins (buckets) and showing the count of values in each bin as vertical bars. +- [Line chart](https://observability.opensearch.org/docs/dashboards/visualize/line-chart/): A line chart plots data points connected by lines, making it ideal for visualizing trends and changes over time. You can compare multiple series on the same time axis and use a secondary Y-axis to correlate metrics with different scales. +- [Metric chart](https://observability.opensearch.org/docs/dashboards/visualize/metric-chart/): A metric chart displays a single numeric value prominently, making it ideal for showing key performance indicators (KPIs) or summary statistics at a glance. +- [Pie chart](https://observability.opensearch.org/docs/dashboards/visualize/pie-chart/): A pie chart displays data as proportional slices of a circle, making it ideal for visualizing part-to-whole relationships. +- [Scatter plot](https://observability.opensearch.org/docs/dashboards/visualize/scatter-chart/): A scatter chart visualizes relationships between two numerical variables. Each point on the chart represents an observation from the dataset, with its position determined by the values of the two variables. You can split data by a categorical field to compare how different groups distribute across the same dimensions. +- [State timeline](https://observability.opensearch.org/docs/dashboards/visualize/state-timeline-chart/): A state timeline displays a series of horizontal bars that represent state changes over time. Each bar, known as a state region, represents a specific state, and its length indicates the duration of that state. +- [Table](https://observability.opensearch.org/docs/dashboards/visualize/table-chart/): A table chart displays query results in a tabular format with rows and columns, making it ideal for viewing raw data or summary statistics. +- [Visualization Transformations](https://observability.opensearch.org/docs/dashboards/visualize/transformations/): Reshape query results with a user-defined transformation pipeline before they reach the chart + +## Deploy to Cloud + +- [Deploy to Cloud](https://observability.opensearch.org/docs/deploy/): The Observability Stack runs locally via Docker Compose out of the box. When you're ready to move to the cloud, you have two paths: +- [AWS Managed Services](https://observability.opensearch.org/docs/deploy/aws/): Deploy the Observability Stack to AWS using managed services. This creates the same observability platform as the local Docker Compose stack, backed by: +- [Kubernetes (Helm)](https://observability.opensearch.org/docs/deploy/kubernetes/): Deploy the Observability Stack to any Kubernetes cluster using the Helm umbrella chart. This creates the same observability platform as the local Docker Compose stack — OpenSearch, OpenSearch Dashboards, Data Prepper, OTel Collector, and Prometheus — as Kubernetes workloads. + +## Forecasting + +- [Forecasting](https://observability.opensearch.org/docs/forecasting/): Predict future values of time-series observability data + +## Get Started + +- [Core Concepts](https://observability.opensearch.org/docs/get-started/core-concepts/): Key terms and ideas for the OpenSearch Observability Stack +- [Installation](https://observability.opensearch.org/docs/get-started/installation/): Install and run the OpenSearch Observability Stack +- [Platform Overview](https://observability.opensearch.org/docs/get-started/overview/): Architecture and data flow overview for OpenSearch Observability Stack +- [Create Your First Dashboard](https://observability.opensearch.org/docs/get-started/quickstart/first-dashboard/): Build your first observability dashboard in OpenSearch Dashboards +- [Ingest Your First Traces](https://observability.opensearch.org/docs/get-started/quickstart/first-traces/): Instrument your application to send traces to the Observability Stack + +## Discover + +- [Investigate](https://observability.opensearch.org/docs/investigate/): Explore, query, and analyze your observability data across logs, traces, and metrics using Discover +- [Correlations](https://observability.opensearch.org/docs/investigate/correlations/): Link trace datasets with logs datasets to accelerate root cause analysis +- [Datasets](https://observability.opensearch.org/docs/investigate/datasets/): Create and manage datasets for organizing observability data in OpenSearch Dashboards +- [Discover Logs](https://observability.opensearch.org/docs/investigate/discover-logs/): Explore and analyze application logs using PPL in OpenSearch Dashboards +- [Discover Metrics](https://observability.opensearch.org/docs/investigate/discover-metrics/): Discover, query, and visualize time-series metric data using PromQL in OpenSearch Dashboards +- [Discover Traces](https://observability.opensearch.org/docs/investigate/discover-traces/): Explore and analyze distributed trace data in OpenSearch Dashboards +- [Explore Logs](https://observability.opensearch.org/docs/investigate/explore-logs/): Browse the indexes and datasets in a cluster, preview their logs, and turn a raw index into a queryable dataset +- [Troubleshooting Queries](https://observability.opensearch.org/docs/investigate/troubleshooting/): Diagnose and fix common issues with PPL and PromQL queries in Discover + +## MCP + +- [MCP Server](https://observability.opensearch.org/docs/mcp/): Query OpenSearch using the built-in Model Context Protocol server + +## PPL - Query Language + +- [Piped Processing Language (PPL)](https://observability.opensearch.org/docs/ppl/): PPL is the native query language for OpenSearch Observability - a pipe-based, human-readable language for exploring logs, traces, and telemetry at scale. +- [PPL Command Reference](https://observability.opensearch.org/docs/ppl/commands/): Complete reference for all PPL commands - syntax, parameters, and examples with live playground links for OpenTelemetry observability data. +- [dedup](https://observability.opensearch.org/docs/ppl/commands/dedup/): Remove duplicate documents based on field values - deduplicate results for unique combinations. +- [describe](https://observability.opensearch.org/docs/ppl/commands/describe/): Query index metadata - discover available fields, types, and schema information. +- [eval](https://observability.opensearch.org/docs/ppl/commands/eval/): Create computed fields by evaluating expressions - arithmetic, string operations, conditionals, and more. +- [eventstats](https://observability.opensearch.org/docs/ppl/commands/eventstats/): Add aggregation statistics as new fields to every event - enrich each row with group-level context. +- [expand](https://observability.opensearch.org/docs/ppl/commands/expand/): Expand nested array fields into multiple documents - one row per array element. +- [fields](https://observability.opensearch.org/docs/ppl/commands/fields/): Keep or remove fields from search results - control which columns appear in output. +- [fillnull](https://observability.opensearch.org/docs/ppl/commands/fillnull/): Replace null values with specified defaults - clean up missing data for analysis and visualization. +- [flatten](https://observability.opensearch.org/docs/ppl/commands/flatten/): Flatten struct or object fields into separate top-level fields - simplify nested data structures. +- [grok](https://observability.opensearch.org/docs/ppl/commands/grok/): Extract fields using grok patterns - a higher-level alternative to regex with 200+ predefined patterns. +- [head](https://observability.opensearch.org/docs/ppl/commands/head/): Return the first N results from the search - limit output for exploration and top-N queries. +- [join](https://observability.opensearch.org/docs/ppl/commands/join/): Combine two datasets together - correlate logs with traces, enrich data from reference indices. +- [lookup](https://observability.opensearch.org/docs/ppl/commands/lookup/): Enrich events with data from a lookup index - add context like team names, environment labels, or cost data. +- [ml](https://observability.opensearch.org/docs/ppl/commands/ml/): Apply machine learning algorithms in your query pipeline - anomaly detection and clustering without external tools. +- [parse](https://observability.opensearch.org/docs/ppl/commands/parse/): Extract fields from text using regular expressions - turn unstructured log data into structured fields. +- [patterns](https://observability.opensearch.org/docs/ppl/commands/patterns/): Automatically discover log patterns - cluster similar log messages without writing regex. +- [rare](https://observability.opensearch.org/docs/ppl/commands/rare/): Find the least common values of a field - surface anomalies and unusual patterns. +- [rename](https://observability.opensearch.org/docs/ppl/commands/rename/): Rename fields in search results - simplify long OTel attribute names for readability. +- [rex](https://observability.opensearch.org/docs/ppl/commands/rex/): Extract or substitute fields using regex - with support for sed-mode text replacement and multiple matches. +- [search](https://observability.opensearch.org/docs/ppl/commands/search/): Retrieve documents from an index - the starting point of every PPL query. +- [sort](https://observability.opensearch.org/docs/ppl/commands/sort/): Sort search results by one or more fields in ascending or descending order. +- [spath](https://observability.opensearch.org/docs/ppl/commands/spath/): Extract fields from structured JSON data - parse nested JSON within log bodies without re-indexing. +- [stats](https://observability.opensearch.org/docs/ppl/commands/stats/): Calculate aggregate statistics over search results - counts, averages, percentiles, and more with grouping. +- [streamstats](https://observability.opensearch.org/docs/ppl/commands/streamstats/): Calculate cumulative and rolling window statistics - running totals, moving averages, and trend detection. +- [timechart](https://observability.opensearch.org/docs/ppl/commands/timechart/): Create time-based aggregations and charts - the go-to command for time-series visualization. +- [top](https://observability.opensearch.org/docs/ppl/commands/top/): Find the most common values of a field - quickly identify dominant patterns in your data. +- [trendline](https://observability.opensearch.org/docs/ppl/commands/trendline/): Calculate moving averages - simple (SMA) and weighted (WMA) for trend analysis and smoothing. +- [where](https://observability.opensearch.org/docs/ppl/commands/where/): Filter search results using boolean expressions - the primary filtering command in PPL. +- [PPL for DQL/Lucene Users](https://observability.opensearch.org/docs/ppl/dql-lucene-users/): A transition guide for users familiar with DQL or Lucene query syntax - the only difference is : becomes = and you gain a full pipeline after the filter. +- [PPL Observability Examples](https://observability.opensearch.org/docs/ppl/examples/): Real-world PPL queries for OpenTelemetry logs, traces, and AI agent observability - with live playground links to try each query instantly. +- [PPL Function Reference](https://observability.opensearch.org/docs/ppl/functions/): Complete reference for PPL built-in functions - aggregations, string manipulation, date/time, math, conditionals, JSON, IP, collections, and more. +- [PPL for SPL Users](https://observability.opensearch.org/docs/ppl/spl-users/): A transition guide for users familiar with Splunk Search Processing Language (SPL) - learn the PPL equivalents for the commands and patterns you already know. + +## Send Data + +- [Send Data](https://observability.opensearch.org/docs/send-data/): Learn how to send traces, metrics, and logs to OpenSearch Observability Stack +- [AI Agents](https://observability.opensearch.org/docs/send-data/ai-agents/): Instrument AI agent applications with the GenAI Observability SDKs +- [Integrations](https://observability.opensearch.org/docs/send-data/ai-agents/integrations/): Instrument popular AI agent frameworks with the GenAI Observability SDK +- [Python SDK](https://observability.opensearch.org/docs/send-data/ai-agents/python/): Reference for opensearch-genai-observability-sdk-py - instrument AI agent applications with OpenTelemetry +- [TypeScript SDK](https://observability.opensearch.org/docs/send-data/ai-agents/typescript/): Instrument TypeScript AI agent applications with the GenAI Observability SDK +- [Instrument Applications](https://observability.opensearch.org/docs/send-data/applications/): Add OpenTelemetry instrumentation to your application code to send traces, metrics, and logs to the observability stack +- [Browser / Frontend](https://observability.opensearch.org/docs/send-data/applications/browser/): Add real user monitoring to web applications with OpenTelemetry for browser-side traces and metrics +- [.NET](https://observability.opensearch.org/docs/send-data/applications/dotnet/): Instrument .NET applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Go](https://observability.opensearch.org/docs/send-data/applications/go/): Instrument Go applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Java](https://observability.opensearch.org/docs/send-data/applications/java/): Instrument Java applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Node.js](https://observability.opensearch.org/docs/send-data/applications/nodejs/): Instrument Node.js applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Python](https://observability.opensearch.org/docs/send-data/applications/python/): Instrument Python applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Ruby](https://observability.opensearch.org/docs/send-data/applications/ruby/): Instrument Ruby applications with OpenTelemetry to send traces, metrics, and logs to the observability stack +- [Data Pipeline](https://observability.opensearch.org/docs/send-data/data-pipeline/): Understand how telemetry data flows from collectors through Data Prepper into OpenSearch +- [Batching & Performance](https://observability.opensearch.org/docs/send-data/data-pipeline/batching/): Tune batch sizes, memory limits, and worker counts for production throughput +- [Data Prepper](https://observability.opensearch.org/docs/send-data/data-pipeline/data-prepper/): Configure Data Prepper pipelines for trace and log ingestion into OpenSearch +- [Ingest API](https://observability.opensearch.org/docs/send-data/data-pipeline/ingest-api/): Send pre-processed telemetry data directly to OpenSearch via the Bulk API +- [From Vendor Agents](https://observability.opensearch.org/docs/send-data/from-vendor/): Accept telemetry from Datadog, Jaeger, and Splunk agents without re-instrumenting your applications +- [Datadog](https://observability.opensearch.org/docs/send-data/from-vendor/datadog/): Accept Datadog agent and SDK telemetry in observability-stack +- [Jaeger](https://observability.opensearch.org/docs/send-data/from-vendor/jaeger/): Migrate Jaeger-instrumented applications to observability-stack +- [Splunk HEC](https://observability.opensearch.org/docs/send-data/from-vendor/splunk/): Route Splunk HTTP Event Collector traffic into OpenSearch +- [Infrastructure Monitoring](https://observability.opensearch.org/docs/send-data/infrastructure/): Collect metrics, logs, and traces from your infrastructure components using OpenTelemetry +- [AWS](https://observability.opensearch.org/docs/send-data/infrastructure/aws/): Integrate with AWS services using ADOT, CloudWatch, Lambda, ECS, and EKS +- [Docker](https://observability.opensearch.org/docs/send-data/infrastructure/docker/): Collect metrics and logs from Docker containers using the OpenTelemetry Collector +- [Fluentd & Fluent Bit](https://observability.opensearch.org/docs/send-data/infrastructure/fluentd/): Forward logs to OpenSearch using Fluentd or Fluent Bit lightweight agents +- [Kubernetes](https://observability.opensearch.org/docs/send-data/infrastructure/kubernetes/): Monitor Kubernetes clusters, pods, and workloads with OpenTelemetry +- [Logstash](https://observability.opensearch.org/docs/send-data/infrastructure/logstash/): Send logs and events through Logstash pipelines to OpenSearch +- [Prometheus](https://observability.opensearch.org/docs/send-data/infrastructure/prometheus/): Scrape and store Prometheus metrics with OTLP integration and resource attribute promotion +- [OpenTelemetry](https://observability.opensearch.org/docs/send-data/opentelemetry/): Understand OpenTelemetry signals, protocols, and how OTel integrates with the observability stack +- [Auto-Instrumentation](https://observability.opensearch.org/docs/send-data/opentelemetry/auto-instrumentation/): Zero-code instrumentation for popular frameworks and languages using OpenTelemetry agents +- [OTel Collector Configuration](https://observability.opensearch.org/docs/send-data/opentelemetry/collector/): Configure the OpenTelemetry Collector pipeline for traces, metrics, and logs +- [Manual Instrumentation](https://observability.opensearch.org/docs/send-data/opentelemetry/manual-instrumentation/): Add custom spans, metrics, and logs with the OpenTelemetry SDK +- [Sampling Strategies](https://observability.opensearch.org/docs/send-data/opentelemetry/sampling/): Control telemetry volume with head-based and tail-based sampling + +## SLO + +- [SLOs](https://observability.opensearch.org/docs/slo/): Define Service Level Objectives backed by Prometheus recording and burn-rate alerting rules, all from the OpenSearch Dashboards UI +- [Create an SLO](https://observability.opensearch.org/docs/slo/create/): Walk through the template-first SLO wizard — pick a template, define the SLI, set objectives, and preview the generated Prometheus rules +- [Explore an SLO](https://observability.opensearch.org/docs/slo/detail/): Understand the SLO detail page — attainment, error budget, multi-window burn-rate tiers, and the generated Prometheus rules diff --git a/docs/starlight-docs/llms-txt/gen-config.mjs b/docs/starlight-docs/llms-txt/gen-config.mjs new file mode 100644 index 00000000..ceeb5827 --- /dev/null +++ b/docs/starlight-docs/llms-txt/gen-config.mjs @@ -0,0 +1,172 @@ +#!/usr/bin/env node +// Builds sourcey.config.ts tabs from the real Starlight content tree, +// mapping index.md/index.mdx files to their directory slug (matching +// Starlight's own routing) instead of a literal ".../index" slug. +import { readFileSync, writeFileSync } from "node:fs"; +import { dirname, basename, extname } from "node:path"; + +const listPath = process.argv[2]; // all_pages.txt (relative paths, one per line) +const lines = readFileSync(listPath, "utf-8").trim().split("\n").filter(Boolean); + +// root index.mdx handled separately (overview tab) -- exclude from directory groups +const contentPages = lines.filter((p) => p !== "index.mdx"); + +function toSlug(relPath) { + const ext = extname(relPath); + const base = basename(relPath, ext); + if (base === "index") { + const dir = dirname(relPath); + return dir === "." ? "" : dir; // "" only for true root, already excluded + } + const noExt = relPath.slice(0, -ext.length); + return noExt; +} + +// group by top-level directory (first path segment) to mirror the real sidebar sections +const groups = new Map(); +for (const rel of contentPages) { + const top = rel.split("/")[0]; + const slug = toSlug(rel); + if (!groups.has(top)) groups.set(top, []); + groups.get(top).push({ slug, rel }); +} + +// sanity: detect slug collisions +const seenSlugs = new Map(); +for (const [top, pages] of groups) { + for (const { slug, rel } of pages) { + if (seenSlugs.has(slug)) { + console.error(`COLLISION: slug "${slug}" used by both ${seenSlugs.get(slug)} and ${rel}`); + process.exitCode = 1; + } + seenSlugs.set(slug, rel); + } +} + +// Human-readable labels for each top-level directory, so llms.txt gets +// section headings like "Agent Health" instead of the raw slug +// "agent-health". Sourced from docs/starlight-docs/astro.config.mjs, the +// Starlight sidebar config, which is the honest source for what a maintainer +// calls each section -- NOT invented here. Two kinds of source, both +// verified by reading that file directly: +// +// - CLEAN MATCH: a sidebar entry ("autogenerate: { directory: X }", or a +// hand-written group whose every item link falls under exactly one +// directory) maps 1:1 onto one of our directories. That sidebar label is +// used verbatim. +// - NO CLEAN MATCH: the sidebar groups several of our directories together +// for navigation ergonomics ("Alerting" spans alerting/, slo/, +// anomaly-detection/, forecasting/; "SDKs, MCP & Clients" spans two +// send-data pages plus mcp/) or references a page outside the directory +// ("Agent Observability" includes one send-data page alongside +// ai-observability/*). Forcing those merges onto our per-directory +// sections would require hand-picked page-level exceptions, which is +// inventing taxonomy, not reading it. For these, the label below is a +// plain title-case of the slug with known tech acronyms capitalized. +// +// Verified against docs/starlight-docs/astro.config.mjs at commit 6fd43fa: +const DIRECTORY_LABELS = { + "agent-health": "Agent Health", // sidebar: autogenerate directory 'agent-health' + "ai-observability": "AI Observability", // no clean match (sidebar's "Agent Observability" group also links one send-data page) -- title-case + AI acronym + "alerting": "Alerting", // no clean match (sidebar's "Alerting" group also spans slo/, anomaly-detection/, forecasting/) -- title-case, happens to equal the sidebar group's own name + "anomaly-detection": "Anomaly Detection", // no clean match (item lives inside the merged "Alerting" group) -- title-case, happens to equal the sidebar item's own label + "apm": "Application Monitoring", // sidebar: autogenerate directory 'apm' + "claude-code": "Claude Code", // sidebar: autogenerate directory 'claude-code' + "dashboards": "Dashboards & Visualize", // sidebar: hand-written group, every item under /dashboards/ + "deploy": "Deploy to Cloud", // sidebar: hand-written group, every item under /deploy/ + "forecasting": "Forecasting", // no clean match (item lives inside the merged "Alerting" group) -- title-case, happens to equal the sidebar item's own label + "get-started": "Get Started", // sidebar: hand-written group, every item under /get-started/ + "investigate": "Discover", // sidebar: autogenerate directory 'investigate', but the group is LABELED "Discover" -- not a slug-derived name, verify before assuming otherwise + "mcp": "MCP", // no clean match (grouped with 2 send-data pages under "SDKs, MCP & Clients") -- acronym + "ppl": "PPL - Query Language", // sidebar: hand-written group, every item under /ppl/ + "send-data": "Send Data", // sidebar: hand-written group, every item (incl. nested autogenerate subsections) under /send-data/ + "slo": "SLO", // no clean match (grouped inside merged "Alerting") -- acronym +}; + +// Fallback for any future top-level directory not yet reviewed against the +// sidebar above: plain title-case with a small acronym allowlist, so a new +// directory doesn't silently produce an unlabelled or wrong section instead +// of failing loudly. NOT a substitute for adding a reviewed entry above. +const ACRONYMS = new Set(["ai", "mcp", "ppl", "slo", "apm", "sdk", "api"]); +function fallbackLabel(slug) { + return slug + .split("-") + .map((word) => (ACRONYMS.has(word) ? word.toUpperCase() : word[0].toUpperCase() + word.slice(1))) + .join(" "); +} + +function labelFor(dir) { + if (DIRECTORY_LABELS[dir]) return DIRECTORY_LABELS[dir]; + console.error(`WARNING: no reviewed sidebar label for directory "${dir}", using algorithmic fallback "${fallbackLabel(dir)}". Add a reviewed entry to DIRECTORY_LABELS in gen-config.mjs.`); + return fallbackLabel(dir); +} + +// One TAB per top-level directory, not one tab with many groups, because +// sourcey's own llms.txt renderer (dist/renderer/llms.js, generateLlmsTxt) +// only ever emits an H2 ("## {tab.label}") per TAB -- it iterates +// navigation.tabs and filters pages by tab, but for a "markdown" source kind +// it prints a flat list straight from tabPages with no per-group heading at +// all. Groups exist for the adapter's own internal organisation but are +// invisible in llms.txt output. Confirmed by reading generateLlmsTxt: the +// markdown branch does `lines.push(`- [${doc.title}](${href})...`)` for +// every page in the tab with no group-keyed loop. So one H2 per real section +// requires one TAB per section, each with slug === its directory name so +// page output paths (which already start with "/...") pass +// through tabPath() unchanged instead of double-nesting -- verified this +// does not perturb any URL: pageOutputPath()'s tabPath(tabSlug, file) only +// prefixes when `file` does not already start with "/", and every +// page's slug here already starts with its own directory name. +const overviewTab = { + tab: "Overview", + slug: "", + pages: ["index"], +}; + +const dirTabs = [...groups.entries()] + .sort(([a], [b]) => a.localeCompare(b)) + .map(([top, pages]) => { + const sortedPages = pages.map((p) => p.slug).sort(); + return { tab: labelFor(top), slug: top, pages: sortedPages }; + }); + +// Overview tab must be emitted FIRST: sourcey's resolveSiteSummary() (same +// file) takes the frontmatter `description` of the first page across ALL +// tabs, in tabs-array order, as the whole site's "> tagline" line. That is +// unaffected by moving from groups to tabs -- it is still first-page-wins +// across the full assembled `pages` array -- but it does mean the Overview +// tab must stay first in this array regardless of alphabetical directory +// order, or the tagline bug returns. +const allTabs = [overviewTab, ...dirTabs]; + +function tabBlock({ tab, slug, pages }) { + return ` { + tab: ${JSON.stringify(tab)}, + slug: ${JSON.stringify(slug)}, + source: markdown({ + groups: [{ group: ${JSON.stringify(slug || "overview")}, pages: ${JSON.stringify(pages)} }], + }), + }`; +} + +const configTs = `// AUTO-GENERATED by gen-config.mjs. Do not hand-edit -- regenerate instead. +import { defineConfig, markdown } from "sourcey"; + +export default defineConfig({ + name: "OpenSearch Observability Stack", + siteUrl: "https://observability.opensearch.org", + baseUrl: "/docs", + prettyUrls: "slash", + repo: "https://github.com/opensearch-project/observability-stack", + editBranch: "main", + editBasePath: "docs/starlight-docs/src/content/docs", + navigation: { + tabs: [ +${allTabs.map(tabBlock).join(",\n")}, + ], + }, +}); +`; + +writeFileSync("sourcey.config.ts", configTs); +console.log(`Wrote sourcey.config.ts with ${contentPages.length} pages across ${allTabs.length} tabs (1 overview + ${dirTabs.length} sections).`); +console.log("Sections:", dirTabs.map((t) => `${t.tab} (${t.slug})`).join(", ")); diff --git a/docs/starlight-docs/llms-txt/postprocess-llms.mjs b/docs/starlight-docs/llms-txt/postprocess-llms.mjs new file mode 100644 index 00000000..65a31266 --- /dev/null +++ b/docs/starlight-docs/llms-txt/postprocess-llms.mjs @@ -0,0 +1,86 @@ +#!/usr/bin/env node +// Rewrites site-relative markdown links in a sourcey-generated llms.txt into +// fully-qualified links, because the file is served at the SITE ROOT +// (https://observability.opensearch.org/llms.txt) while every entry points +// under /docs/. An LLM fetching /llms.txt out of context has no HTML +// and no page origin to resolve a relative link against, so a bare "/docs/..." +// link is only meaningful if the reader already knows the site -- exactly the +// failure the file exists to avoid. Both exemplars cited by opensearch-project/ +// observability-stack issue #262 (Cloudflare, Stripe) ship fully-qualified +// links in their own llms.txt for this reason. +// +// Sourcey's own llms.txt renderer (dist/renderer/llms.js) always emits +// site-relative hrefs via toPublicPath() and has no config option to use the +// absolute toPublicUrl() variant instead, so this has to be a post-process +// step run on the file sourcey writes, not a sourcey.config.ts setting. +// +// Usage: node postprocess-llms.mjs +import { readFileSync, writeFileSync } from "node:fs"; + +const SITE_URL = "https://observability.opensearch.org"; +const filePath = process.argv[2]; +if (!filePath) { + console.error("Usage: node postprocess-llms.mjs "); + process.exit(1); +} + +const before = readFileSync(filePath, "utf-8"); + +// The H1 ("# ...") and tagline ("> ...") lines carry no markdown links and +// must be byte-identical before and after. Capture them up front so we can +// assert they didn't move. +const beforeLines = before.split("\n"); +const h1Before = beforeLines[0]; +const taglineBefore = beforeLines[2]; + +// Every entry line looks like "- [Title](/some/path/): description". Rewrite +// only "](/..." -> "](https://observability.opensearch.org/...". This never +// touches the H1 or tagline (neither contains "](/"), and it is naturally +// idempotent: a link that has already been rewritten starts with "](https://" +// not "](/", so re-running this script on its own output is a no-op. +const relativeLinkPattern = /\]\(\//g; +const relativeLinkCount = (before.match(relativeLinkPattern) ?? []).length; + +if (relativeLinkCount === 0) { + console.error("No site-relative links found (\"](/\"). Refusing to run: either " + + "the file is already fully-qualified (fine, but nothing to do) or the input " + + "is not the llms.txt this script expects. Aborting without writing."); + process.exit(1); +} + +const after = before.replace(relativeLinkPattern, `](${SITE_URL}/`); + +// --- Assertions: count-based, not spot-checked. --- + +// 1. Every relative link line got rewritten: zero bare "](/" survive. +const remainingRelative = (after.match(relativeLinkPattern) ?? []).length; +if (remainingRelative !== 0) { + throw new Error(`${remainingRelative} relative link(s) survived the rewrite -- expected 0.`); +} + +// 2. The rewritten link count matches the original relative link count +// exactly (nothing added, nothing dropped). +const qualifiedCount = (after.match(new RegExp(`\\]\\(${SITE_URL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/`, "g")) ?? []).length; +if (qualifiedCount !== relativeLinkCount) { + throw new Error(`Expected ${relativeLinkCount} fully-qualified links, found ${qualifiedCount}.`); +} + +// 3. No double-prefix: the origin must never appear twice in a row inside a +// single link (e.g. "https://observability.opensearch.orghttps://..."). +const doublePrefixPattern = new RegExp(`${SITE_URL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}${SITE_URL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`); +if (doublePrefixPattern.test(after)) { + throw new Error("Double-prefixed origin detected in output. Aborting without writing."); +} + +// 4. H1 and tagline lines are untouched. +const afterLines = after.split("\n"); +if (afterLines[0] !== h1Before) { + throw new Error(`H1 line changed. Before: "${h1Before}" After: "${afterLines[0]}"`); +} +if (afterLines[2] !== taglineBefore) { + throw new Error(`Tagline line changed. Before: "${taglineBefore}" After: "${afterLines[2]}"`); +} + +writeFileSync(filePath, after); +console.log(`Rewrote ${relativeLinkCount} relative links to fully-qualified ${SITE_URL}/... links.`); +console.log(`Remaining relative links: ${remainingRelative}. Double-prefix check: clean. H1/tagline: unchanged.`); diff --git a/docs/starlight-docs/llms-txt/sourcey.config.ts b/docs/starlight-docs/llms-txt/sourcey.config.ts new file mode 100644 index 00000000..69d054cd --- /dev/null +++ b/docs/starlight-docs/llms-txt/sourcey.config.ts @@ -0,0 +1,128 @@ +// AUTO-GENERATED by gen-config.mjs. Do not hand-edit -- regenerate instead. +import { defineConfig, markdown } from "sourcey"; + +export default defineConfig({ + name: "OpenSearch Observability Stack", + siteUrl: "https://observability.opensearch.org", + baseUrl: "/docs", + prettyUrls: "slash", + repo: "https://github.com/opensearch-project/observability-stack", + editBranch: "main", + editBasePath: "docs/starlight-docs/src/content/docs", + navigation: { + tabs: [ + { + tab: "Overview", + slug: "", + source: markdown({ + groups: [{ group: "overview", pages: ["index"] }], + }), + }, + { + tab: "Agent Health", + slug: "agent-health", + source: markdown({ + groups: [{ group: "agent-health", pages: ["agent-health","agent-health/cli","agent-health/configuration","agent-health/configuration/connectors","agent-health/evaluations","agent-health/evaluations/experiments","agent-health/evaluations/test-cases","agent-health/getting-started","agent-health/traces"] }], + }), + }, + { + tab: "AI Observability", + slug: "ai-observability", + source: markdown({ + groups: [{ group: "ai-observability", pages: ["ai-observability","ai-observability/agent-tracing","ai-observability/agent-tracing/graph","ai-observability/evaluation","ai-observability/evaluation-integrations","ai-observability/getting-started"] }], + }), + }, + { + tab: "Alerting", + slug: "alerting", + source: markdown({ + groups: [{ group: "alerting", pages: ["alerting","alerting/unified-alerts"] }], + }), + }, + { + tab: "Anomaly Detection", + slug: "anomaly-detection", + source: markdown({ + groups: [{ group: "anomaly-detection", pages: ["anomaly-detection"] }], + }), + }, + { + tab: "Application Monitoring", + slug: "apm", + source: markdown({ + groups: [{ group: "apm", pages: ["apm","apm/configuring-apm","apm/configuring-telemetry-ingestion","apm/service-map","apm/services","apm/sizing-calculator"] }], + }), + }, + { + tab: "Claude Code", + slug: "claude-code", + source: markdown({ + groups: [{ group: "claude-code", pages: ["claude-code","claude-code/showcase","claude-code/usage"] }], + }), + }, + { + tab: "Dashboards & Visualize", + slug: "dashboards", + source: markdown({ + groups: [{ group: "dashboards", pages: ["dashboards","dashboards/build","dashboards/sharing","dashboards/troubleshooting","dashboards/variables","dashboards/variables/managing-variables","dashboards/variables/using-variables","dashboards/visualize","dashboards/visualize/area-chart","dashboards/visualize/bar-chart","dashboards/visualize/bar-gauge-chart","dashboards/visualize/configuring-visualizations","dashboards/visualize/configuring-visualizations/thresholds","dashboards/visualize/configuring-visualizations/value-calculations","dashboards/visualize/gauge-chart","dashboards/visualize/heatmap-chart","dashboards/visualize/histogram-chart","dashboards/visualize/line-chart","dashboards/visualize/metric-chart","dashboards/visualize/pie-chart","dashboards/visualize/scatter-chart","dashboards/visualize/state-timeline-chart","dashboards/visualize/table-chart","dashboards/visualize/transformations"] }], + }), + }, + { + tab: "Deploy to Cloud", + slug: "deploy", + source: markdown({ + groups: [{ group: "deploy", pages: ["deploy","deploy/aws","deploy/kubernetes"] }], + }), + }, + { + tab: "Forecasting", + slug: "forecasting", + source: markdown({ + groups: [{ group: "forecasting", pages: ["forecasting"] }], + }), + }, + { + tab: "Get Started", + slug: "get-started", + source: markdown({ + groups: [{ group: "get-started", pages: ["get-started/core-concepts","get-started/installation","get-started/overview","get-started/quickstart/first-dashboard","get-started/quickstart/first-traces"] }], + }), + }, + { + tab: "Discover", + slug: "investigate", + source: markdown({ + groups: [{ group: "investigate", pages: ["investigate","investigate/correlations","investigate/datasets","investigate/discover-logs","investigate/discover-metrics","investigate/discover-traces","investigate/explore-logs","investigate/troubleshooting"] }], + }), + }, + { + tab: "MCP", + slug: "mcp", + source: markdown({ + groups: [{ group: "mcp", pages: ["mcp"] }], + }), + }, + { + tab: "PPL - Query Language", + slug: "ppl", + source: markdown({ + groups: [{ group: "ppl", pages: ["ppl","ppl/commands","ppl/commands/dedup","ppl/commands/describe","ppl/commands/eval","ppl/commands/eventstats","ppl/commands/expand","ppl/commands/fields","ppl/commands/fillnull","ppl/commands/flatten","ppl/commands/grok","ppl/commands/head","ppl/commands/join","ppl/commands/lookup","ppl/commands/ml","ppl/commands/parse","ppl/commands/patterns","ppl/commands/rare","ppl/commands/rename","ppl/commands/rex","ppl/commands/search","ppl/commands/sort","ppl/commands/spath","ppl/commands/stats","ppl/commands/streamstats","ppl/commands/timechart","ppl/commands/top","ppl/commands/trendline","ppl/commands/where","ppl/dql-lucene-users","ppl/examples","ppl/functions","ppl/spl-users"] }], + }), + }, + { + tab: "Send Data", + slug: "send-data", + source: markdown({ + groups: [{ group: "send-data", pages: ["send-data","send-data/ai-agents","send-data/ai-agents/integrations","send-data/ai-agents/python","send-data/ai-agents/typescript","send-data/applications","send-data/applications/browser","send-data/applications/dotnet","send-data/applications/go","send-data/applications/java","send-data/applications/nodejs","send-data/applications/python","send-data/applications/ruby","send-data/data-pipeline","send-data/data-pipeline/batching","send-data/data-pipeline/data-prepper","send-data/data-pipeline/ingest-api","send-data/from-vendor","send-data/from-vendor/datadog","send-data/from-vendor/jaeger","send-data/from-vendor/splunk","send-data/infrastructure","send-data/infrastructure/aws","send-data/infrastructure/docker","send-data/infrastructure/fluentd","send-data/infrastructure/kubernetes","send-data/infrastructure/logstash","send-data/infrastructure/prometheus","send-data/opentelemetry","send-data/opentelemetry/auto-instrumentation","send-data/opentelemetry/collector","send-data/opentelemetry/manual-instrumentation","send-data/opentelemetry/sampling"] }], + }), + }, + { + tab: "SLO", + slug: "slo", + source: markdown({ + groups: [{ group: "slo", pages: ["slo","slo/create","slo/detail"] }], + }), + }, + ], + }, +}); From 8e2c1b86f974031e9e6fa60bd4e0bc19f5041933 Mon Sep 17 00:00:00 2001 From: Circadian Date: Thu, 6 Aug 2026 02:47:59 +0200 Subject: [PATCH 2/2] I, Circadian , hereby add my Signed-off-by to this commit: 2e91fdb637ce7074d52925c6364a1c9dbb44bf1e Signed-off-by: Circadian