Fetch
⚙️ _fetch
(fetchWithLogging) — Internal Fetch Wrapper
_fetch
(fetchWithLogging) — Internal Fetch WrapperOverview
_fetch
is a globally available, logging-enhanced wrapper around the native fetch
API.
It provides automatic timeout handling, structured logging, redaction of sensitive data, and configurable request inspection — all without changing the core fetch
syntax.
Use _fetch
for all HTTP requests inside helper functions or services that require observability and safe logging.
✳️ Usage Example
const res = await _fetch("https://api.example.com/v1/data", {
method: "POST",
headers: {
"content-type": "application/json",
authorization: `Bearer ${token}`,
},
body: JSON.stringify({ name: "Alice", password: "secret" }),
options: {
timeoutMs: 5000,
logBody: true,
logHeaders: true,
logQueryValues: true,
excludePatterns: [/password/i],
excludeMode: "redact",
},
});
const data = await res.json();
🧩 Key Features
Feature | Description |
---|---|
Timeout control | Automatically cancels requests after timeoutMs milliseconds using AbortController . |
Structured logging | Emits a logger.log("http_response", {...}) event with request, response, and timing details. |
Header/body scrubbing | Automatically removes or redacts sensitive fields using regular expressions. |
Signal combination | Combines user-provided and internal signals so either can abort the request. |
Query/response capture | Logs both request and response URLs (with final redirects, if applicable). |
Drop-in compatible | Fully compatible with native fetch — same syntax, same return type. |
Injects identifying headers | Adds headers to each request identifying point, organization, and user making the request. |
🧱 Function Signature
await _fetch(input, init);
Parameter | Type | Description | |
---|---|---|---|
input | `string | Request` | The URL or a pre-built Request object. |
init | object | Standard fetch init options (method, headers, body, signal, etc.). | |
init.options | object | Extended logging and behavior controls (see below). |
⚙️ Extended Options (init.options
)
init.options
)Option | Type | Default | Description | |
---|---|---|---|---|
timeoutMs | number | undefined | Aborts the request if it exceeds this duration (in ms). | |
logBody | boolean | false | Include request body in logs (with sensitive fields removed/redacted). | |
logHeaders | boolean | false | Include request headers in logs. | |
logQueryValues | boolean | true | Include query string values in logs (non-sensitive values only). | |
captureResponseUrl | boolean | true | Log the final response URL (useful for redirects). | |
excludePatterns | RegExp[] | [] | List of key patterns to omit or redact from logs. | |
excludeMode | `"omit" | "redact"` | "omit" | How to handle excluded keys (omit deletes them; redact replaces with [EXCLUDED] ). |
metadata | object | {} | Custom metadata to include in the log output (merged with system metadata). |
🧰 Logging Behavior
Every _fetch
call automatically produces a structured log record with the tag http_response
.
This object includes both request and response metadata.
Example log object
{
"point_name": "arc_engine_api",
"method": "POST",
"url": "https://api.example.com/v1/data",
"domain": "api.example.com",
"path": "/v1/data",
"query": { "page": "1" },
"body": { "name": "Alice", "password": "[EXCLUDED]" },
"requestHeaders": { "content-type": "application/json", "authorization": "[REDACTED]" },
"status": 200,
"ok": true,
"duration": 312,
"final_url": "https://api.example.com/v1/data",
"response_content_type": "application/json"
}
🔐 Redaction and Exclusion Rules
_fetch
automatically prevents sensitive data from being logged.
Built-in protections:
- Header keys like
authorization
,cookie
, orx-api-key
are redacted automatically. - Query parameters containing
token
,secret
,pass
,key
,session
, orsignature
are replaced with[REDACTED]
. - Body fields are sanitized using
excludePatterns
.
Custom redaction examples:
options: {
excludePatterns: [/password/i, /^x-private-/i],
excludeMode: "omit",
}
This will remove all matching keys entirely from logs.
⏱️ Timeout and Abort Logic
- If
timeoutMs
is set,_fetch
creates an internalAbortController
to cancel the request after that duration. - If the user also provides a
signal
, both signals are combined — either one can abort the request. - When a timeout occurs,
_fetch
throws:
Error("Request timed out after <timeoutMs>ms")
.
🧾 Returned Value
_fetch
returns the same object as native fetch
— a standard Response
instance.
All of the following methods work the same way:
const res = await _fetch(url);
const text = await res.text();
const json = await res.json();
const ok = res.ok;
const status = res.status;
If a network error occurs, _fetch
throws an Error
(never returns an incomplete Response
).
📦 Integration Example (inside a helper)
async function createUser({ payload, timeoutMs = 10000 }) {
const res = await _fetch(`${api_host}/v1/users`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify(payload),
options: {
timeoutMs,
logBody: true,
logHeaders: true,
excludePatterns: [/password/i],
excludeMode: "redact",
},
});
if (!res.ok) throw new Error(`Failed to create user: ${res.status}`);
return await res.json();
}
📋 Best Practices
✅ Always use _fetch
instead of fetch
to ensure consistent logging.
✅ Use excludePatterns
aggressively to avoid logging secrets.
✅ Prefer redact
over omit
to maintain visibility into removed keys.
✅ Set timeoutMs
for all network calls — unbounded requests can hang indefinitely.
✅ Avoid logging large binary bodies; _fetch
already truncates long bodies with an ellipsis (…
).
✅ Don’t catch and suppress _fetch
errors silently — propagate them with context.
🧩 Advanced: Injected Headers
_fetch
automatically injects context headers for observability:
Header | Description |
---|---|
x-options-point-name | Name of the current point (if available). |
x-options-point-organization-id | Organization ID in context. |
x-options-point-user | Current user (if defined globally). |
These are added transparently to every request unless overridden.
🧠 Summary
_fetch
is a global, enhanced replacement for the native fetch
function — it behaves the same but adds structured logging, timeouts, and automatic redaction of sensitive data. Use it for all HTTP requests inside helpers or services to ensure secure and consistent observability.
const res = await _fetch("https://api.example.com/v1/data", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ name: "Alice", password: "secret" }),
options: {
timeoutMs: 5000,
logBody: true,
logHeaders: true,
excludePatterns: [/password/i],
excludeMode: "redact",
},
});
const data = await res.json();
You can use all standard fetch
methods (res.json()
, res.text()
, etc.), but _fetch
will automatically log request and response details, redact sensitive fields, and enforce timeouts — no extra setup required.
Maintained by: Platform Engineering
Function: _fetch
(alias: fetchWithLogging
)
Version: 1.0
Scope: Global — available to all helper modules
Updated about 15 hours ago