Skip to content

Commit a096157

Browse files
committed
docs: add comprehensive k6/x/dns extension documentation
- Add complete documentation for k6/x/dns module with _index.md overview - Create resolve.md documenting dns.resolve() function with parameters, examples, and error handling - Create lookup.md documenting dns.lookup() function for system DNS resolution - Include installation instructions, API reference, and metrics documentation - Add comprehensive examples for IPv4/IPv6 resolution, performance testing, and validation - Use IPv6 DNS server (2606:4700:4700::1111) in IPv6 examples for consistency - Replace check() usage with k6-jslib-testing expect() assertions throughout examples - Follow k6 documentation conventions matching existing API documentation structure
1 parent 34f5bd4 commit a096157

File tree

6 files changed

+578
-44
lines changed

6 files changed

+578
-44
lines changed

AGENTS.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Repository Guidelines
2+
3+
## Project Structure & Module Organization
4+
- Markdown sources live in `docs/sources/k6/<version>`; update both `next` and the current `vX.Y.x` folder when fixing published content.
5+
- `docs/sources/k6/*/shared` holds reusable fragments invoked through the `shared` shortcode; keep shared snippets backward-compatible.
6+
- `docs/Makefile` and the checked-in `make-docs` script wrap the containerised Hugo toolchain used to serve the site locally.
7+
- Utility scripts in `scripts/` (for example, `apply-patch`) help port commits between versions—run them from the repository root.
8+
9+
## Build, Test, and Development Commands
10+
- `npm start` builds the docs in Docker/Podman and serves them at `http://localhost:3002/docs/k6/`.
11+
- `cd docs && make docs PULL=false` skips image pulls when you already have `grafana/docs-base:latest` locally.
12+
- `cd docs && make vale` runs Vale linting inside the writers-toolkit container.
13+
- `cd docs && make update` refreshes `docs.mk` and `make-docs` from the upstream Writers’ Toolkit.
14+
15+
## Coding Style & Naming Conventions
16+
- Prettier enforces single quotes, trailing commas, and a 100-character Markdown width; run `npx prettier --write docs/sources/k6/path/to/file.md` before committing.
17+
- Name Markdown files with lowercase hyphenated slugs (for example, `docs/sources/k6/next/testing/load-testing.md`) to match URL patterns.
18+
- Embedded code blocks are linted via ESLint/MDX; prefer declarations over assignments, keep snippets runnable, and include needed imports/constants.
19+
- Follow the Grafana Writers’ Toolkit for tone, front matter expectations, and shortcode usage to stay aligned with brand guidance.
20+
21+
## Testing Guidelines
22+
- Preview every change with `npm start` and verify both the `next` and targeted version folders render as expected.
23+
- Run `make vale` for terminology, style, and broken-link checks; treat warnings as actionable feedback.
24+
- Use `scripts/apply-patch HEAD~ docs/sources/k6/next docs/sources/k6/v1.0.x` (adjust arguments) to sync updates across supported versions.
25+
26+
## Commit & Pull Request Guidelines
27+
- Commits follow `type(scope): short description (#issue)`; scopes mirror directories (for example, `docs(browser)` or `fix(k6-operator)`).
28+
- Group related edits per commit and describe user-visible changes in the body when necessary.
29+
- Pull requests should list affected pages, note any version backports, attach screenshots for UI-oriented edits, and link related issues or discussions.
30+
- Request reviewers from CODEOWNERS and wait for the deploy preview check before merging.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
---
2+
title: 'k6/x/dns'
3+
description: 'k6 DNS extension API'
4+
weight: 11
5+
---
6+
7+
# DNS
8+
9+
{{< docs/shared source="k6" lookup="extension.md" version="<K6_VERSION>" >}}
10+
11+
The `k6/x/dns` modul enables DNS resolution testing in k6, allowing you to resolve DNS names to IP addresses using custom DNS servers or the system's default DNS configuration. This module is particularly useful for testing DNS server performance, validating DNS configurations, and incorporating DNS resolution into your load testing scenarios.
12+
13+
## Key features
14+
15+
- The [`dns.resolve()`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-x-dns/resolve) function resolves DNS names using a specified DNS server, allowing you to test custom DNS configurations and server performance.
16+
- The [`dns.lookup()`](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-x-dns/lookup) function resolves DNS names using the system's default DNS servers, providing a way to test standard DNS resolution behavior.
17+
- Support for A (IPv4) and AAAA (IPv6) record types.
18+
- Automatic metrics collection for DNS resolution performance analysis.
19+
20+
### Use cases
21+
22+
- Load testing DNS servers to ensure they can handle high query volumes.
23+
- Validating DNS configurations in staging and production environments.
24+
- Testing DNS failover mechanisms and redundancy.
25+
- Incorporating DNS resolution time into overall application performance testing.
26+
27+
## API
28+
29+
| Function/Object | Description |
30+
| ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
31+
| [resolve](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-x-dns/resolve) | Resolves a DNS name to IP addresses using a specified DNS server. |
32+
| [lookup](https://grafana.com/docs/k6/<K6_VERSION>/javascript-api/k6-x-dns/lookup) | Resolves a DNS name to IP addresses using the system's default DNS servers. |
33+
34+
## Metrics
35+
36+
The extension automatically generates the following metrics:
37+
38+
- `dns_resolutions`: Counter tracking the number of DNS resolution attempts.
39+
- `dns_resolution_duration`: Trend measuring DNS resolution response times.
40+
- `dns_lookups`: Counter tracking the number of DNS lookup attempts.
41+
- `dns_lookup_duration`: Trend measuring DNS lookup response times.
42+
43+
## Examples
44+
45+
### Basic DNS resolution with custom server
46+
47+
{{< code >}}
48+
49+
<!-- md-k6:skip -->
50+
51+
```javascript
52+
import dns from 'k6/x/dns';
53+
54+
export default async function () {
55+
// Resolve k6.io using Cloudflare's DNS server
56+
const ips = await dns.resolve('k6.io', 'A', '1.1.1.1:53');
57+
console.log('k6.io resolves to:', ips);
58+
}
59+
```
60+
61+
{{< /code >}}
62+
63+
### DNS lookup using system defaults
64+
65+
{{< code >}}
66+
67+
<!-- md-k6:skip -->
68+
69+
```javascript
70+
import dns from 'k6/x/dns';
71+
72+
export default async function () {
73+
// Resolve k6.io using system DNS servers
74+
const ips = await dns.lookup('k6.io');
75+
console.log('k6.io resolves to:', ips);
76+
}
77+
```
78+
79+
{{< /code >}}
80+
81+
### Comprehensive DNS testing
82+
83+
{{< code >}}
84+
85+
<!-- md-k6:skip -->
86+
87+
```javascript
88+
import dns from 'k6/x/dns';
89+
import { expect } from 'https://jslib.k6.io/k6-testing/{{< param "JSLIB_TESTING_VERSION" >}}/index.js';
90+
91+
export const options = {
92+
vus: 10,
93+
duration: '30s',
94+
};
95+
96+
export default async function () {
97+
// Test both IPv4 and IPv6 resolution
98+
const ipv4Results = await dns.resolve('example.com', 'A', '8.8.8.8:53');
99+
const ipv6Results = await dns.resolve('example.com', 'AAAA', '[2606:4700:4700::1111]:53');
100+
101+
// Test system DNS
102+
const systemResults = await dns.lookup('example.com');
103+
104+
// Validate results
105+
expect(ipv4Results.length).toBeGreaterThan(0);
106+
expect(ipv6Results.length).toBeGreaterThan(0);
107+
expect(systemResults.length).toBeGreaterThan(0);
108+
}
109+
```
110+
111+
{{< /code >}}
Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
---
2+
title: 'lookup( hostname )'
3+
description: 'Lookup the IP addresses a DNS name is bound to using system configured DNS servers'
4+
weight: 30
5+
---
6+
7+
# lookup( hostname )
8+
9+
The `dns.lookup` function performs DNS resolution using the system's default DNS configuration and returns a promise that resolves to an array of IP addresses. This function is useful, for instance, for testing standard DNS resolution behavior and comparing it with custom DNS server results.
10+
11+
## Parameters
12+
13+
| Parameter | Type | Description |
14+
| :-------- | :----- | :------------------------------------------------------------------------ |
15+
| hostname | string | The domain name to resolve (e.g., "example.com", "k6.io") |
16+
17+
## Returns
18+
19+
A promise resolving to an array of strings, where each string is an IP address that the domain name resolves to. The function returns the same IP addresses that would be returned by the system's standard DNS resolution mechanism.
20+
21+
## Emitted metrics
22+
23+
When using `dns.lookup`, the following metrics are automatically generated:
24+
25+
- `dns_lookups`: Counter incremented for each lookup attempt
26+
- `dns_lookup_duration`: Trend measuring the time taken for DNS lookup
27+
28+
These metrics help you monitor DNS performance using your system's DNS configuration.
29+
30+
## Examples
31+
32+
### Basic lookup
33+
34+
{{< code >}}
35+
36+
<!-- md-k6:skip -->
37+
38+
```javascript
39+
import dns from 'k6/x/dns';
40+
41+
export default async function () {
42+
// Resolve using system DNS servers
43+
const addresses = await dns.lookup('k6.io');
44+
console.log('k6.io resolves to:', addresses);
45+
// Output: k6.io resolves to: ["104.21.7.127", "172.67.154.74"]
46+
}
47+
```
48+
49+
{{< /code >}}
50+
51+
### Comparing system vs custom DNS
52+
53+
{{< code >}}
54+
55+
<!-- md-k6:skip -->
56+
57+
```javascript
58+
import dns from 'k6/x/dns';
59+
import { expect } from 'https://jslib.k6.io/k6-testing/{{< param "JSLIB_TESTING_VERSION" >}}/index.js';
60+
61+
export default async function () {
62+
const domain = 'example.com';
63+
64+
// Get results from system DNS
65+
const systemResults = await dns.lookup(domain);
66+
67+
// Get results from Google's DNS
68+
const googleResults = await dns.resolve(domain, 'A', '8.8.8.8:53');
69+
70+
console.log('System DNS results:', systemResults);
71+
console.log('Google DNS results:', googleResults);
72+
73+
// Check if both methods return results
74+
expect(systemResults.length).toBeGreaterThan(0);
75+
expect(googleResults.length).toBeGreaterThan(0);
76+
77+
// Compare results (they might differ due to different DNS configurations)
78+
const hasCommonAddress = systemResults.some(ip => googleResults.includes(ip));
79+
expect(hasCommonAddress).toBeTruthy();
80+
}
81+
```
82+
83+
{{< /code >}}
84+
85+
### Testing DNS consistency
86+
87+
{{< code >}}
88+
89+
<!-- md-k6:skip -->
90+
91+
```javascript
92+
import dns from 'k6/x/dns';
93+
import { expect } from 'https://jslib.k6.io/k6-testing/{{< param "JSLIB_TESTING_VERSION" >}}/index.js';
94+
95+
export const options = {
96+
vus: 1,
97+
iterations: 10,
98+
};
99+
100+
export default async function () {
101+
const domain = 'k6.io';
102+
103+
try {
104+
const results = await dns.lookup(domain);
105+
106+
expect(results.length).toBeGreaterThan(0);
107+
expect(results.every(ip =>
108+
/^\d+\.\d+\.\d+\.\d+$/.test(ip) || /^[0-9a-fA-F:]+$/.test(ip)
109+
)).toBeTruthy();
110+
111+
console.log(`Iteration ${__ITER}: ${domain} -> ${results.join(', ')}`);
112+
} catch (error) {
113+
console.error('DNS lookup failed:', error);
114+
}
115+
}
116+
```
117+
118+
{{< /code >}}
119+
120+
### Load testing with system DNS
121+
122+
{{< code >}}
123+
124+
<!-- md-k6:skip -->
125+
126+
```javascript
127+
import dns from 'k6/x/dns';
128+
import { sleep } from 'k6';
129+
import { expect } from 'https://jslib.k6.io/k6-testing/{{< param "JSLIB_TESTING_VERSION" >}}/index.js';
130+
import { Trend, Rate } from 'k6/metrics';
131+
132+
const lookupDuration = new Trend('dns_lookup_duration_custom');
133+
const successRate = new Rate('dns_lookup_success_rate');
134+
135+
export const options = {
136+
vus: 10,
137+
duration: '60s',
138+
};
139+
140+
const domains = [
141+
'k6.io',
142+
'example.com',
143+
'google.com',
144+
'github.com',
145+
'stackoverflow.com',
146+
];
147+
148+
export default async function () {
149+
const domain = domains[Math.floor(Math.random() * domains.length)];
150+
const startTime = Date.now();
151+
152+
try {
153+
const results = await dns.lookup(domain);
154+
const duration = Date.now() - startTime;
155+
156+
lookupDuration.add(duration);
157+
successRate.add(true);
158+
159+
expect(results.length).toBeGreaterThan(0);
160+
161+
console.log(`${domain} resolved in ${duration}ms to ${results.length} addresses`);
162+
} catch (error) {
163+
const duration = Date.now() - startTime;
164+
lookupDuration.add(duration);
165+
successRate.add(false);
166+
167+
console.error(`Failed to resolve ${domain}: ${error.message}`);
168+
}
169+
170+
sleep(1);
171+
}
172+
```
173+
174+
{{< /code >}}
175+
176+
### Validating DNS configuration
177+
178+
{{< code >}}
179+
180+
<!-- md-k6:skip -->
181+
182+
```javascript
183+
import dns from 'k6/x/dns';
184+
import { expect } from 'https://jslib.k6.io/k6-testing/{{< param "JSLIB_TESTING_VERSION" >}}/index.js';
185+
186+
export default async function () {
187+
const testDomains = [
188+
'k6.io',
189+
'grafana.com',
190+
'example.com',
191+
];
192+
193+
for (const domain of testDomains) {
194+
try {
195+
const results = await dns.lookup(domain);
196+
197+
expect(results.length).toBeGreaterThan(0);
198+
expect(results.every(ip => {
199+
// Basic IPv4/IPv6 validation
200+
return /^\d+\.\d+\.\d+\.\d+$/.test(ip) || /^[0-9a-fA-F:]+$/.test(ip);
201+
})).toBeTruthy();
202+
203+
console.log(`${domain}: ${results.join(', ')}`);
204+
} catch (error) {
205+
console.error(`${domain}: ${error.message}`);
206+
}
207+
}
208+
}
209+
```
210+
211+
{{< /code >}}
212+
213+
## Error handling
214+
215+
The `lookup` function may throw errors in the following cases:
216+
217+
- Invalid hostname format
218+
- DNS resolution timeout
219+
- No DNS servers configured on the system
220+
- Network connectivity issues
221+
222+
{{< code >}}
223+
224+
<!-- md-k6:skip -->
225+
226+
```javascript
227+
import dns from 'k6/x/dns';
228+
229+
export default async function () {
230+
try {
231+
const results = await dns.lookup('nonexistent.invalid.domain.test');
232+
console.log('Unexpected success:', results);
233+
} catch (error) {
234+
console.log('Expected DNS lookup error:', error.message);
235+
}
236+
237+
// Test with invalid hostname format
238+
try {
239+
const results = await dns.lookup('');
240+
console.log('Unexpected success with empty hostname:', results);
241+
} catch (error) {
242+
console.log('Expected error for empty hostname:', error.message);
243+
}
244+
}
245+
```
246+
247+
{{< /code >}}

0 commit comments

Comments
 (0)