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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions docs/custom_fences.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
"""
Custom fence processors for MkDocs documentation.

Fences available:
- yaml-toolset-config: Creates 3 tabs (Holmes CLI, Holmes Helm Chart, Robusta Helm Chart) for toolset configurations
- yaml-helm-values: Creates 2 tabs (Holmes Helm Chart, Robusta Helm Chart) for Helm-only configurations like permissions
"""

import html
import uuid


def toolset_config_fence_format(source, language, css_class, options, md, **kwargs):
"""
Format YAML content into Holmes CLI, Holmes Helm Chart, and Robusta Helm Chart tabs for toolset configuration.
This fence does NOT process Jinja2, so {{ env.VAR }} stays as-is.
"""
# Generate unique IDs for this tab group to prevent conflicts
tab_group_id = str(uuid.uuid4()).replace("-", "_")
tab_id_1 = f"__tabbed_{tab_group_id}_1"
tab_id_2 = f"__tabbed_{tab_group_id}_2"
tab_id_3 = f"__tabbed_{tab_group_id}_3"
group_name = f"__tabbed_{tab_group_id}"

# Escape HTML in the source to prevent XSS
escaped_source = html.escape(source)

# Strip any leading/trailing whitespace
yaml_content = source.strip()

# Indent the yaml content for Robusta (add 2 spaces to each line under holmes:)
robusta_yaml_lines = yaml_content.split("\n")
robusta_yaml_indented = "\n".join(
" " + line if line else "" for line in robusta_yaml_lines
)

# Build the tabbed HTML structure for CLI, Holmes Helm, and Robusta
tabs_html = f"""
<div class="tabbed-set" data-tabs="1:3">
<input checked="checked" id="{tab_id_1}" name="{group_name}" type="radio">
<input id="{tab_id_2}" name="{group_name}" type="radio">
<input id="{tab_id_3}" name="{group_name}" type="radio">
<div class="tabbed-labels">
<label for="{tab_id_1}">Holmes CLI</label>
<label for="{tab_id_2}">Holmes Helm Chart</label>
<label for="{tab_id_3}">Robusta Helm Chart</label>
</div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>Add the following to <strong>~/.holmes/config.yaml</strong>. Create the file if it doesn't exist:</p>
<pre><code class="language-yaml">{escaped_source}</code></pre>
</div>
<div class="tabbed-block">
<p>When using the <strong>standalone Holmes Helm Chart</strong>, update your <code>values.yaml</code>:</p>
<pre><code class="language-yaml">{escaped_source}</code></pre>
<p>Apply the configuration:</p>
<pre><code class="language-bash">helm upgrade holmes holmes/holmes --values=values.yaml</code></pre>
</div>
<div class="tabbed-block">
<p>When using the <strong>Robusta Helm Chart</strong> (which includes HolmesGPT), update your <code>generated_values.yaml</code>:</p>
<pre><code class="language-yaml">holmes:
{html.escape(robusta_yaml_indented)}</code></pre>
<p>Apply the configuration:</p>
<pre><code class="language-bash">helm upgrade robusta robusta/robusta --values=generated_values.yaml --set clusterName=&lt;YOUR_CLUSTER_NAME&gt;</code></pre>
</div>
</div>
</div>"""

return tabs_html


def helm_tabs_fence_format(source, language, css_class, options, md, **kwargs):
"""
Format YAML content into Holmes and Robusta Helm Chart tabs.
This fence does NOT process Jinja2, so {{ env.VAR }} stays as-is.
"""
# Generate unique IDs for this tab group to prevent conflicts
tab_group_id = str(uuid.uuid4()).replace("-", "_")
tab_id_1 = f"__tabbed_{tab_group_id}_1"
tab_id_2 = f"__tabbed_{tab_group_id}_2"
group_name = f"__tabbed_{tab_group_id}"

# Escape HTML in the source to prevent XSS
escaped_source = html.escape(source)

# Strip any leading/trailing whitespace
yaml_content = source.strip()

# Indent the yaml content for Robusta (add 2 spaces to each line)
robusta_yaml_lines = yaml_content.split("\n")
robusta_yaml_indented = "\n".join(
" " + line if line else "" for line in robusta_yaml_lines
)

# Build the tabbed HTML structure
tabs_html = f"""
<div class="tabbed-set" data-tabs="1:2">
<input checked="checked" id="{tab_id_1}" name="{group_name}" type="radio">
<input id="{tab_id_2}" name="{group_name}" type="radio">
<div class="tabbed-labels">
<label for="{tab_id_1}">Holmes Helm Chart</label>
<label for="{tab_id_2}">Robusta Helm Chart</label>
</div>
<div class="tabbed-content">
<div class="tabbed-block">
<p>When using the <strong>standalone Holmes Helm Chart</strong>, update your <code>values.yaml</code>:</p>
<pre><code class="language-yaml">{escaped_source}</code></pre>
<p>Apply the configuration:</p>
<pre><code class="language-bash">helm upgrade holmes holmes/holmes --values=values.yaml</code></pre>
</div>
<div class="tabbed-block">
<p>When using the <strong>Robusta Helm Chart</strong> (which includes HolmesGPT), update your <code>generated_values.yaml</code> (note: add the <code>holmes:</code> prefix):</p>
<pre><code class="language-yaml">enableHolmesGPT: true
holmes:
{html.escape(robusta_yaml_indented)}</code></pre>
<p>Apply the configuration:</p>
<pre><code class="language-bash">helm upgrade robusta robusta/robusta --values=generated_values.yaml --set clusterName=&lt;YOUR_CLUSTER_NAME&gt;</code></pre>
</div>
</div>
</div>"""

return tabs_html
48 changes: 12 additions & 36 deletions docs/data-sources/builtin-toolsets/coralogix-logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,42 +16,18 @@ For example if you access Coralogix at `https://my-team.app.eu2.coralogix.com/`

## Configuration

=== "Holmes CLI"

Add the following to **~/.holmes/config.yaml**. Create the file if it doesn't exist:

```yaml
toolsets:
coralogix/logs:
enabled: true
config:
api_key: "<your Coralogix API key>"
domain: "eu2.coralogix.com"
team_hostname: "your-company-name"

kubernetes/logs:
enabled: false # Disable default Kubernetes logging
```

--8<-- "snippets/toolset_refresh_warning.md"

=== "Robusta Helm Chart"

```yaml
holmes:
toolsets:
coralogix/logs:
enabled: true
config:
api_key: "<your Coralogix API key>"
domain: "eu2.coralogix.com"
team_hostname: "your-company-name"

kubernetes/logs:
enabled: false # Disable default Kubernetes logging
```

--8<-- "snippets/helm_upgrade_command.md"
```yaml-toolset-config
toolsets:
coralogix/logs:
enabled: true
config:
api_key: "<your Coralogix API key>"
domain: "eu2.coralogix.com"
team_hostname: "your-company-name"

kubernetes/logs:
enabled: false # Disable default Kubernetes logging
```

## Capabilities

Expand Down
134 changes: 34 additions & 100 deletions docs/data-sources/builtin-toolsets/grafanaloki.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,120 +36,54 @@ curl -s -u admin:admin http://localhost:3000/api/datasources | jq '.[] | select(

### Configuration (Grafana Proxy)

=== "Holmes CLI"

Add the following to **~/.holmes/config.yaml**. Create the file if it doesn't exist:

```yaml
toolsets:
grafana/loki:
enabled: true
config:
api_key: <your grafana API key>
url: https://xxxxxxx.grafana.net # Your Grafana cloud account URL
grafana_datasource_uid: <the UID of the loki data source in Grafana>

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

--8<-- "snippets/toolset_refresh_warning.md"

=== "Robusta Helm Chart"

```yaml
holmes:
toolsets:
grafana/loki:
enabled: true
config:
api_key: <your grafana API key>
url: https://xxxxxxx.grafana.net # Your Grafana cloud account URL
grafana_datasource_uid: <the UID of the loki data source in Grafana>

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

--8<-- "snippets/helm_upgrade_command.md"
```yaml-toolset-config
toolsets:
grafana/loki:
enabled: true
config:
api_key: <your grafana API key>
url: https://xxxxxxx.grafana.net # Your Grafana cloud account URL
grafana_datasource_uid: <the UID of the loki data source in Grafana>

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

## Direct Connection

The toolset can directly connect to a Loki instance without proxying through a Grafana instance. This is done by not setting the `grafana_datasource_uid` field. Not setting this field makes HolmesGPT assume that it is directly connecting to Loki.

### Configuration (Direct Connection)

=== "Holmes CLI"

Add the following to **~/.holmes/config.yaml**. Create the file if it doesn't exist:

```yaml
toolsets:
grafana/loki:
enabled: true
config:
url: http://loki.logging
headers:
X-Scope-OrgID: "<tenant id>" # Set the X-Scope-OrgID if loki multitenancy is enabled

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

--8<-- "snippets/toolset_refresh_warning.md"

=== "Robusta Helm Chart"

```yaml
holmes:
toolsets:
grafana/loki:
enabled: true
config:
url: http://loki.logging
headers:
X-Scope-OrgID: "<tenant id>" # Set the X-Scope-OrgID if loki multitenancy is enabled

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

--8<-- "snippets/helm_upgrade_command.md"
```yaml-toolset-config
toolsets:
grafana/loki:
enabled: true
config:
url: http://loki.logging
headers:
X-Scope-OrgID: "<tenant id>" # Set the X-Scope-OrgID if loki multitenancy is enabled

kubernetes/logs:
enabled: false # HolmesGPT's default logging mechanism MUST be disabled
```

## Advanced Configuration

### Search Labels

You can tweak the labels used by the toolset to identify Kubernetes resources. This is only needed if your Loki logs settings for `pod` and `namespace` differ from the defaults.

=== "Holmes CLI"

Add the following to **~/.holmes/config.yaml**:

```yaml
toolsets:
grafana/loki:
enabled: true
config:
url: ...
labels:
pod: "pod"
namespace: "namespace"
```

=== "Robusta Helm Chart"

```yaml
holmes:
toolsets:
grafana/loki:
enabled: true
config:
url: ...
labels:
pod: "pod"
namespace: "namespace"
```
```yaml-toolset-config
toolsets:
grafana/loki:
enabled: true
config:
url: ...
labels:
pod: "pod"
namespace: "namespace"
```

Use the following commands to list Loki's labels and determine which ones to use:

Expand Down
Loading
Loading