Skip to content

Commit bb5c6b6

Browse files
committed
Use SDK audit log download helpers
1 parent e6754da commit bb5c6b6

1 file changed

Lines changed: 18 additions & 59 deletions

File tree

info/audit-logs.mdx

Lines changed: 18 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ The export API returns one chunk per request. Export paging uses a cursor rather
105105

106106
Repeat requests until `X-Has-More` is `false`, passing `X-Next-Cursor` back as `cursor`. With the `jsonl.gz` format, each chunk is an independent gzip member, and appending the members produces a valid gzip file. With `jsonl`, each chunk contains raw JSON Lines that you can also append.
107107

108-
The following minimal examples write all chunks to one file. For a hardened export with checksum verification and retries, use the [CLI](/reference/cli/audit-logs#kernel-audit-logs-download).
108+
The SDK download helpers verify each chunk, retry transient transfer failures, and write the complete export to a destination you provide. They don't close the destination.
109109

110110
<CodeGroup>
111111
```typescript TypeScript
@@ -118,23 +118,15 @@ const kernel = new Kernel({
118118

119119
const file = await open('audit-logs.jsonl.gz', 'w');
120120
try {
121-
let cursor: string | undefined;
122-
while (true) {
123-
const response = await kernel.auditLogs.exportChunk({
121+
await kernel.auditLogs.download(
122+
{
124123
start: '2026-06-01T00:00:00Z',
125124
end: '2026-06-02T00:00:00Z',
126125
format: 'jsonl.gz',
127126
exclude_method: ['GET'],
128-
cursor,
129-
});
130-
131-
await file.writeFile(Buffer.from(await response.arrayBuffer()));
132-
133-
if (response.headers.get('x-has-more') !== 'true') {
134-
break;
135-
}
136-
cursor = response.headers.get('x-next-cursor') ?? undefined;
137-
}
127+
},
128+
file,
129+
);
138130
} finally {
139131
await file.close();
140132
}
@@ -146,28 +138,21 @@ from kernel import Kernel
146138

147139
client = Kernel(api_key=os.environ["KERNEL_API_KEY"])
148140

149-
params = {
150-
"start": "2026-06-01T00:00:00Z",
151-
"end": "2026-06-02T00:00:00Z",
152-
"format": "jsonl.gz",
153-
"exclude_method": ["GET"],
154-
}
155-
156141
with open("audit-logs.jsonl.gz", "wb") as file:
157-
while True:
158-
response = client.audit_logs.export_chunk(**params)
159-
file.write(response.read())
160-
if response.headers.get("x-has-more") != "true":
161-
break
162-
params["cursor"] = response.headers.get("x-next-cursor")
142+
client.audit_logs.download(
143+
to=file,
144+
start="2026-06-01T00:00:00Z",
145+
end="2026-06-02T00:00:00Z",
146+
format="jsonl.gz",
147+
exclude_method=["GET"],
148+
)
163149
```
164150

165151
```go Go
166152
package main
167153

168154
import (
169155
"context"
170-
"io"
171156
"os"
172157
"time"
173158

@@ -184,46 +169,20 @@ func main() {
184169
}
185170
defer file.Close()
186171

187-
params := kernel.AuditLogExportChunkParams{
172+
_, err = client.AuditLogs.Download(ctx, kernel.AuditLogDownloadParams{
188173
Start: time.Date(2026, time.June, 1, 0, 0, 0, 0, time.UTC),
189174
End: time.Date(2026, time.June, 2, 0, 0, 0, 0, time.UTC),
190175
Format: kernel.AuditLogExportChunkParamsFormatJSONLGz,
191176
ExcludeMethod: []string{"GET"},
192-
}
193-
194-
for {
195-
response, err := client.AuditLogs.ExportChunk(ctx, params)
196-
if err != nil {
197-
panic(err)
198-
}
199-
_, copyErr := io.Copy(file, response.Body)
200-
closeErr := response.Body.Close()
201-
if copyErr != nil {
202-
panic(copyErr)
203-
}
204-
if closeErr != nil {
205-
panic(closeErr)
206-
}
207-
208-
if response.Header.Get("X-Has-More") != "true" {
209-
break
210-
}
211-
params.Cursor = kernel.String(response.Header.Get("X-Next-Cursor"))
177+
}, file)
178+
if err != nil {
179+
panic(err)
212180
}
213181
}
214182
```
215183
</CodeGroup>
216184

217-
<Warning>
218-
Don't use these minimal loops for production exports without these safeguards:
219-
220-
- Buffer each chunk's exact response bytes and verify their SHA-256 hash against `X-Content-Sha256` before writing.
221-
- When `X-Has-More` is `true`, require a non-empty `X-Next-Cursor` that differs from the current cursor.
222-
- Persist the cursor only after the verified chunk is safely written.
223-
- Retry transient failures.
224-
225-
The [CLI download command](/reference/cli/audit-logs#kernel-audit-logs-download) implements these safeguards.
226-
</Warning>
185+
For atomic file replacement and cleanup after failed downloads, use the [CLI download command](/reference/cli/audit-logs#kernel-audit-logs-download).
227186

228187
Export chunks contain one JSON object per line. They use the same fields as search results and add `event_id`, which provides a stable tie-breaker when multiple events share a timestamp.
229188

0 commit comments

Comments
 (0)