Skip to content

Commit 1e50807

Browse files
rochdevBridgeAR
andauthored
chore: add editorconfig validation to linting (#7594)
* ci: add editorconfig validation to linting This adds an editorconfig check to CI plus an `.editorconfig-checker.json` ignore list for binary fixtures and recorded cassettes. The check runs through the `mstruebing/editorconfig-checker` Docker image rather than the npm binary so CI does not fetch the checker binary over the network on every run. * style: normalize files to satisfy editorconfig Bring existing files into compliance with the editorconfig rules enforced by the new check. Whitespace only: final newlines, LF line endings, trailing whitespace, tabs converted to spaces, and indentation aligned to a multiple of two. * fix(test): keep streamtest fixture free of a trailing newline The editorconfig normalization appended a final newline to the streamtest fixture, which response_blocking.spec.js streams verbatim and asserts equals 'writefileend'. The extra byte made the streamed body 'writefile\nend' and failed the no-attack case. Restore the fixture and carve it out of the final-newline rule, matching the existing fine-tune.jsonl exclusion. * test(llmobs): cover google-genai metrics and streaming output formatting The `extractMetrics` token fallback (derive the total from prompt + candidate counts when `totalTokenCount` is absent) and the streaming special-case branch in `formatOutputMessages` (functionCall / executableCode / codeExecutionResult parts routed through non-streaming formatting) had no direct coverage. Add a unit spec pinning both branches and their token-count siblings. --------- Co-authored-by: Ruben Bridgewater <ruben.bridgewater@datadoghq.com>
1 parent 13c5eaa commit 1e50807

70 files changed

Lines changed: 1357 additions & 1247 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.agents/skills/apm-integrations/SKILL.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,16 @@ Two ways to fetch the source locally:
8282

8383
1. **Shallow clone** the installed version:
8484

85-
```bash
86-
git clone --depth 1 --branch v<x.y.z> https://github.com/<org>/<repo>.git /tmp/<lib>-versions/v<x.y.z>
87-
```
85+
```bash
86+
git clone --depth 1 --branch v<x.y.z> https://github.com/<org>/<repo>.git /tmp/<lib>-versions/v<x.y.z>
87+
```
8888

8989
2. **`npm pack`** when the published runtime artifact is what matters:
9090

91-
```bash
92-
cd /tmp/<lib>-versions && npm pack <lib>@<x.y.z>
93-
tar -xzf <lib>-<x.y.z>.tgz -C v<x.y.z> --strip-components=1
94-
```
91+
```bash
92+
cd /tmp/<lib>-versions && npm pack <lib>@<x.y.z>
93+
tar -xzf <lib>-<x.y.z>.tgz -C v<x.y.z> --strip-components=1
94+
```
9595

9696
Read the file the wrap hooks, the base classes the hooked methods inherit from, and files the wrap doesn't currently touch — a public method, an internal channel, or a metadata field the current instrumentation skipped often gives a cleaner hook (e.g., kafka `cluster.brokerPool.metadata.clusterId`, couchbase `tracingChannel`).
9797

@@ -156,20 +156,20 @@ For the complete list by base class, see [Reference Plugins](references/referenc
156156
Follow these steps when creating or modifying an integration:
157157

158158
1. **Investigate** — Read the upstream library's source (see [Read Upstream Source First](#read-upstream-source-first)). Read 1-2 reference integrations of the same type (see table above). Understand the instrumentation and plugin patterns before writing code.
159-
2. **Implement instrumentation** — Create the instrumentation in `packages/datadog-instrumentations/src/`. Use orchestrion for instrumentation.
159+
2. **Implement instrumentation** — Create the instrumentation in `packages/datadog-instrumentations/src/`. Use orchestrion for instrumentation.
160160
3. **Implement plugin** — Create the plugin in `packages/datadog-plugin-<name>/src/`. Extend the correct base class.
161161
4. **Register** — Add entries in `packages/dd-trace/src/plugins/index.js`, `index.d.ts`, `docs/test.ts`, `docs/API.md`, and `.github/workflows/apm-integrations.yml`.
162162
5. **Write tests** — Add unit tests and ESM integration tests. See [Testing](references/testing.md) for templates.
163163
6. **Run tests** — Validate with:
164-
```bash
165-
# Run plugin tests (preferred CI command — handles yarn services automatically)
166-
PLUGINS="<name>" npm run test:plugins:ci
164+
```bash
165+
# Run plugin tests (preferred CI command — handles yarn services automatically)
166+
PLUGINS="<name>" npm run test:plugins:ci
167167

168-
# If the plugin needs external services (databases, message brokers, etc.),
169-
# check docker-compose.yml for available service names, then:
168+
# If the plugin needs external services (databases, message brokers, etc.),
169+
# check docker-compose.yml for available service names, then:
170170
docker compose up -d <service>
171-
PLUGINS="<name>" npm run test:plugins:ci
172-
```
171+
PLUGINS="<name>" npm run test:plugins:ci
172+
```
173173
7. **Verify** — Confirm all tests pass before marking work as complete.
174174

175175
## Reference Files

.agents/skills/apm-integrations/references/async-iterator-pattern.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ async getStream() { /* returns Promise<ReadableStream> */ }
2525
**When `kind: 'AsyncIterator'` is used, Orchestrion automatically creates TWO channels:**
2626

2727
1. **Base channel**: `tracing:orchestrion:{package}:{channelName}:*`
28-
- Fires when the method is called (before iteration starts)
29-
- Used to create the span
28+
- Fires when the method is called (before iteration starts)
29+
- Used to create the span
3030

3131
2. **Next channel**: `tracing:orchestrion:{package}:{channelName}_next:*`
32-
- Fires on EACH iteration (`next()` call)
33-
- Used to finish the span when `result.done === true`
32+
- Fires on EACH iteration (`next()` call)
33+
- Used to finish the span when `result.done === true`
3434

3535
## Critical Implementation Requirements
3636

.agents/skills/apm-integrations/references/orchestrion.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,9 @@ This pattern is complex and easy to get wrong. The reference document covers:
162162

163163
1. Install the package: `npm install <package>`
164164
2. Search for the method definition:
165-
```bash
166-
grep -r "methodName" node_modules/<package>/
167-
```
165+
```bash
166+
grep -r "methodName" node_modules/<package>/
167+
```
168168
3. Use the path relative to the package root
169169

170170
**IMPORTANT: Patch both CJS and ESM code paths.** Many libraries duplicate their classes across separate CJS and ESM builds (e.g., `dist/cjs/client.js` and `dist/esm/client.js`). Each file path needs its own entry in the instrumentations array with the same `functionQuery` and `channelName`. If only one is patched, the instrumentation will silently fail for the other module format.

.agents/skills/llmobs-integration/SKILL.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,16 @@ See [references/plugin-architecture.md](references/plugin-architecture.md) for t
6363
Answer these questions by reading the code:
6464

6565
1. **Does the package make direct HTTP calls to LLM provider endpoints?**
66-
- YES → Go to question 2
67-
- NO → Go to question 3
66+
- YES → Go to question 2
67+
- NO → Go to question 3
6868

6969
2. **Does it support multiple LLM providers via configuration?**
70-
- YES → **`LlmObsCategory.MULTI_PROVIDER`**
71-
- NO → **`LlmObsCategory.LLM_CLIENT`**
70+
- YES → **`LlmObsCategory.MULTI_PROVIDER`**
71+
- NO → **`LlmObsCategory.LLM_CLIENT`**
7272

7373
3. **Does it implement workflow/graph orchestration with state management?**
74-
- YES → **`LlmObsCategory.ORCHESTRATION`**
75-
- NO → **`LlmObsCategory.INFRASTRUCTURE`**
74+
- YES → **`LlmObsCategory.ORCHESTRATION`**
75+
- NO → **`LlmObsCategory.INFRASTRUCTURE`**
7676

7777
See [references/category-detection.md](references/category-detection.md) for detailed heuristics and examples.
7878

@@ -108,31 +108,31 @@ See [references/message-extraction.md](references/message-extraction.md) for pro
108108
## Implementation Steps
109109

110110
1. **Detect package category** (REQUIRED FIRST STEP)
111-
- Follow decision tree above
112-
- Output: category, confidence, reasoning
111+
- Follow decision tree above
112+
- Output: category, confidence, reasoning
113113

114114
2. **Create plugin file**
115-
- Location: `packages/dd-trace/src/llmobs/plugins/{integration}/index.js`
116-
- Extend: `LLMObsPlugin` base class
117-
- Implement: Required methods per plugin architecture
115+
- Location: `packages/dd-trace/src/llmobs/plugins/{integration}/index.js`
116+
- Extend: `LLMObsPlugin` base class
117+
- Implement: Required methods per plugin architecture
118118

119119
3. **Implement `getLLMObsSpanRegisterOptions(ctx)`**
120-
- Extract model provider and name from context
121-
- Determine span kind (usually `'llm'`)
122-
- Return registration options object
120+
- Extract model provider and name from context
121+
- Determine span kind (usually `'llm'`)
122+
- Return registration options object
123123

124124
4. **Implement `setLLMObsTags(ctx)`**
125-
- Extract input messages from `ctx.arguments`
126-
- Extract output messages from `ctx.result`
127-
- Extract token metrics (input_tokens, output_tokens, total_tokens)
128-
- Extract metadata (temperature, max_tokens, etc.)
129-
- Tag span using `this._tagger` methods
125+
- Extract input messages from `ctx.arguments`
126+
- Extract output messages from `ctx.result`
127+
- Extract token metrics (input_tokens, output_tokens, total_tokens)
128+
- Extract metadata (temperature, max_tokens, etc.)
129+
- Tag span using `this._tagger` methods
130130

131131
5. **Handle edge cases**
132-
- Streaming responses (if applicable)
133-
- Error cases (empty output messages)
134-
- Non-standard message formats
135-
- Missing metadata
132+
- Streaming responses (if applicable)
133+
- Error cases (empty output messages)
134+
- Non-standard message formats
135+
- Missing metadata
136136

137137
See [references/plugin-architecture.md](references/plugin-architecture.md) for step-by-step implementation guide.
138138

.agents/skills/llmobs-integration/references/category-detection.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,16 @@ Follow this tree to determine category:
8787

8888
```
8989
1. Does the package make direct HTTP calls to LLM provider endpoints?
90-
├─ YES → Go to question 2
91-
└─ NO → Go to question 3
90+
├─ YES → Go to question 2
91+
└─ NO → Go to question 3
9292
9393
2. Does it support multiple LLM providers via configuration?
94-
├─ YES → LlmObsCategory.MULTI_PROVIDER
95-
└─ NO → LlmObsCategory.LLM_CLIENT
94+
├─ YES → LlmObsCategory.MULTI_PROVIDER
95+
└─ NO → LlmObsCategory.LLM_CLIENT
9696
9797
3. Does it implement workflow/graph orchestration with state management?
98-
├─ YES → LlmObsCategory.ORCHESTRATION
99-
└─ NO → LlmObsCategory.INFRASTRUCTURE
98+
├─ YES → LlmObsCategory.ORCHESTRATION
99+
└─ NO → LlmObsCategory.INFRASTRUCTURE
100100
```
101101

102102
## Detection Process

.agents/skills/llmobs-testing/references/assertion-helpers.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -99,34 +99,34 @@ assertLlmObsSpanEvent(events[0], {
9999
## Best Practices
100100

101101
1. **Use MOCK_* for non-deterministic values:**
102-
- Output text: `MOCK_STRING` (real responses vary)
103-
- Token counts: `MOCK_NOT_NULLISH` (counts vary but should exist)
104-
- Error objects: `MOCK_OBJECT` (error details vary)
102+
- Output text: `MOCK_STRING` (real responses vary)
103+
- Token counts: `MOCK_NOT_NULLISH` (counts vary but should exist)
104+
- Error objects: `MOCK_OBJECT` (error details vary)
105105

106106
2. **Use exact values for inputs:**
107-
- Input messages: You control these in tests
108-
- Model parameters: You set these (temperature, max_tokens)
109-
- Model name: You specify this
107+
- Input messages: You control these in tests
108+
- Model parameters: You set these (temperature, max_tokens)
109+
- Model name: You specify this
110110

111111
3. **Always validate core fields:**
112-
- `spanKind` (required for every span)
113-
- `name` (operation identifier)
114-
- `modelName` and `modelProvider` (for LLM spans)
112+
- `spanKind` (required for every span)
113+
- `name` (operation identifier)
114+
- `modelName` and `modelProvider` (for LLM spans)
115115

116116
4. **Validate message format:**
117-
- Ensure `{content: string, role: string}` structure
118-
- Check role values: `'user'`, `'assistant'`, `'system'`, `'tool'`
117+
- Ensure `{content: string, role: string}` structure
118+
- Check role values: `'user'`, `'assistant'`, `'system'`, `'tool'`
119119

120120
5. **Test error paths:**
121-
- Verify empty `outputMessages: [{content: '', role: ''}]` on errors
122-
- Assert `error` field exists with `MOCK_OBJECT`
121+
- Verify empty `outputMessages: [{content: '', role: ''}]` on errors
122+
- Assert `error` field exists with `MOCK_OBJECT`
123123

124124
6. **Match span kind to operation:**
125-
- Chat/completions → `spanKind: 'llm'`
126-
- Workflow execution → `spanKind: 'workflow'`
127-
- Agent runs → `spanKind: 'agent'`
128-
- Tool calls → `spanKind: 'tool'`
129-
- Embeddings → `spanKind: 'embedding'`
125+
- Chat/completions → `spanKind: 'llm'`
126+
- Workflow execution → `spanKind: 'workflow'`
127+
- Agent runs → `spanKind: 'agent'`
128+
- Tool calls → `spanKind: 'tool'`
129+
- Embeddings → `spanKind: 'embedding'`
130130

131131
## Reference Test Implementation
132132

.editorconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,16 @@ end_of_line = lf
99
charset = utf-8
1010
trim_trailing_whitespace = true
1111
insert_final_newline = true
12+
13+
[*.avro]
14+
charset = unset
15+
end_of_line = unset
16+
insert_final_newline = unset
17+
18+
# TODO: fix OpenAI tests
19+
[packages/datadog-plugin-openai/test/fine-tune.jsonl]
20+
insert_final_newline = unset
21+
22+
# Streamed verbatim and asserted byte-for-byte by the response-blocking test.
23+
[packages/dd-trace/test/appsec/streamtest.txt]
24+
insert_final_newline = false

.editorconfig-checker.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"Verbose": false,
3+
"Debug": false,
4+
"IgnoreDefaults": false,
5+
"SpacesAfterTabs": false,
6+
"NoColor": false,
7+
"Exclude": [
8+
"^\\.nyc_output/",
9+
"^LICENSE",
10+
"^coverage/",
11+
"^packages/dd-trace/test/appsec/bad-formatted-rules\\.json$",
12+
"^packages/dd-trace/test/llmobs/cassettes/",
13+
"^vendor/"
14+
],
15+
"AllowedContentTypes": [],
16+
"PassedFiles": []
17+
}

.github/actions/node/setup/action.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ runs:
3131
maintenance) version=$(node_version 20) ;;
3232
active) version=$(node_version 24) ;;
3333
latest) version=${LATEST_VERSION:-$(node_version 26)}
34-
# When a custom/nightly version is requested via latest,
35-
# force tracer init past the engines upper-bound guard.
36-
[ -n "$LATEST_VERSION" ] && echo "DD_INJECT_FORCE=true" >> "$GITHUB_ENV" || true ;;
34+
# When a custom/nightly version is requested via latest,
35+
# force tracer init past the engines upper-bound guard.
36+
[ -n "$LATEST_VERSION" ] && echo "DD_INJECT_FORCE=true" >> "$GITHUB_ENV" || true ;;
3737
*) version=$VERSION ;;
3838
esac
3939
echo "version=$version" >> "$GITHUB_OUTPUT"

.github/selenium/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ RUN apt-get update && apt-get install -y curl git gnupg libatomic1 unzip wget \
99
RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub \
1010
| gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg \
1111
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] http://dl.google.com/linux/chrome/deb/ stable main" \
12-
> /etc/apt/sources.list.d/google-chrome.list \
12+
> /etc/apt/sources.list.d/google-chrome.list \
1313
&& apt-get update \
1414
&& apt-get install -y google-chrome-stable \
1515
&& rm -rf /var/lib/apt/lists/*
1616

1717
# Install ChromeDriver matching the installed Chrome version
1818
RUN CHROME_VER=$(google-chrome --version | awk '{print $3}' | cut -d. -f1-3) \
1919
&& curl -sf https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json \
20-
> /tmp/chrome-versions.json \
20+
> /tmp/chrome-versions.json \
2121
&& DRIVER_URL=$(CHROME_VER="$CHROME_VER" node -e " \
2222
const d = JSON.parse(require('fs').readFileSync('/tmp/chrome-versions.json', 'utf8')); \
2323
const prefix = process.env.CHROME_VER; \

0 commit comments

Comments
 (0)