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
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ These two skills have a strict boundary: **application code vs Collector configu
When content could live in either skill, apply this rule: if the guidance tells an agent how to modify **application code or deployment specs**, it belongs in `otel-instrumentation`; if it tells an agent how to modify **Collector YAML configuration or Collector deployment manifests**, it belongs in `otel-collector`.
Cross-reference the other skill for context, but do not duplicate Collector configuration in `otel-instrumentation` or SDK/pod-spec configuration in `otel-collector`.

## Keeping SKILL.md index lists in sync with rule files

Some `SKILL.md` files contain a bullet list that mirrors the `##` headings in a referenced rule file (marked with a `<!-- keep-in-sync -->` comment).
When adding, removing, or renaming a `##` heading in the rule file, update the corresponding list in `SKILL.md` so the entries match one-to-one.

## Prose rules

Follow these rules when writing or editing prose in this project.
Expand Down
90 changes: 11 additions & 79 deletions skills/otel-ottl/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,85 +101,17 @@ service:

## Common patterns

### Set attributes

```
set(resource.attributes["k8s.cluster.name"], "prod-aws-us-west-2")
```

### Redact sensitive data

See [redaction](./rules/redaction.md) for strategies (replace, mask, hash, delete, drop) with examples.

### Drop telemetry by pattern

```
IsMatch(metric.name, "^k8s\\.replicaset\\..*$")
```

### Drop stale data

```
time_unix_nano < UnixNano(Now()) - 21600000000000
```

### Backfill missing timestamps

```yaml
processors:
transform:
log_statements:
- context: log
statements:
- set(log.observed_time, Now()) where log.observed_time_unix_nano == 0
- set(log.time, log.observed_time) where log.time_unix_nano == 0
```

### Filter processor example

```yaml
processors:
filter:
metrics:
datapoint:
- 'IsMatch(ConvertCase(String(metric.name), "lower"), "^k8s\\.replicaset\\.")'

service:
pipelines:
metrics:
receivers: [otlp]
processors: [filter, batch]
exporters: [debug]
```

### Transform processor example

```yaml
processors:
transform:
trace_statements:
- context: span
statements:
- set(span.status.code, STATUS_CODE_ERROR) where span.attributes["http.response.status_code"] >= 500
- set(span.attributes["env"], "production") where resource.attributes["deployment.environment"] == "prod"

service:
pipelines:
traces:
receivers: [otlp]
processors: [transform, batch]
exporters: [debug]
```

### Defensive nil checks

```
resource.attributes["service.namespace"] != nil
and
IsMatch(ConvertCase(String(resource.attributes["service.namespace"]), "lower"), "^platform.*$")
```

See [cardinality](./rules/cardinality.md) for normalizing high-cardinality attributes (path segments, IP masking, attribute count/length limits) and [enrichment](./rules/enrichment.md) for adding static resource attributes.
<!-- keep-in-sync: each entry must match a ## heading in ./rules/patterns.md -->
- [Set attributes](./rules/patterns.md#set-attributes)
- [Drop telemetry by pattern](./rules/patterns.md#drop-telemetry-by-pattern)
- [Drop stale data](./rules/patterns.md#drop-stale-data)
- [Backfill missing timestamps](./rules/patterns.md#backfill-missing-timestamps)
- [Filter processor example](./rules/patterns.md#filter-processor-example)
- [Transform processor example](./rules/patterns.md#transform-processor-example)
- [Defensive nil checks](./rules/patterns.md#defensive-nil-checks)
- [Redact sensitive data](./rules/redaction.md) — strategies: replace, mask, hash, delete, and drop.
- [Normalize high-cardinality attributes](./rules/cardinality.md) — path segments, IP masking, and attribute count/length limits.
- [Enrich telemetry with static attributes](./rules/enrichment.md)

## Error handling

Expand Down
75 changes: 75 additions & 0 deletions skills/otel-ottl/rules/patterns.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Common OTTL patterns

## Set attributes

```
set(resource.attributes["k8s.cluster.name"], "prod-aws-us-west-2")
```

## Drop telemetry by pattern

```
IsMatch(metric.name, "^k8s\\.replicaset\\..*$")
```

## Drop stale data

```
time_unix_nano < UnixNano(Now()) - 21600000000000
```

## Backfill missing timestamps

```yaml
processors:
transform:
log_statements:
- context: log
statements:
- set(log.observed_time, Now()) where log.observed_time_unix_nano == 0
- set(log.time, log.observed_time) where log.time_unix_nano == 0
```

## Filter processor example

```yaml
processors:
filter:
metrics:
datapoint:
- 'IsMatch(ConvertCase(String(metric.name), "lower"), "^k8s\\.replicaset\\.")'

service:
pipelines:
metrics:
receivers: [otlp]
processors: [filter, batch]
exporters: [debug]
```

## Transform processor example

```yaml
processors:
transform:
trace_statements:
- context: span
statements:
- set(span.status.code, STATUS_CODE_ERROR) where span.attributes["http.response.status_code"] >= 500
- set(span.attributes["env"], "production") where resource.attributes["deployment.environment"] == "prod"

service:
pipelines:
traces:
receivers: [otlp]
processors: [transform, batch]
exporters: [debug]
```

## Defensive nil checks

```
resource.attributes["service.namespace"] != nil
and
IsMatch(ConvertCase(String(resource.attributes["service.namespace"]), "lower"), "^platform.*$")
```