Network Instrumentation
Generates: Spans
Automatically instruments HTTP requests made via OkHttp and HttpURLConnection.
How It Works
Pulse Android SDK automatically instruments HTTP requests when using:
- OkHttp 3.0+ - Most popular HTTP client library for Android
- HttpURLConnection - Standard Java HTTP client
- HttpsURLConnection - Secure HTTP connections
The instrumentation operates by intercepting application calls to these APIs, creating client HTTP spans with request/response metadata.
Quick Start
Add these dependencies to your project
Replace BYTEBUDDY_VERSION with the latest
release.
Byte buddy compilation plugin
This plugin leverages Android's Transform API to instrument bytecode at compile time. You can find more info on its repo page.
Root Project dependencies
plugins {
id("net.bytebuddy.byte-buddy-gradle-plugin") version "BYTEBUDDY_VERSION"
}
Project dependencies
// if you are using OkHttp then use below libraries
implementation("in.horizonos.instrumentation:okhttp3-library:0.0.1-alpha")
byteBuddy("in.horizonos.instrumentation:okhttp3-agent:0.0.1-alpha")
// for httpurlconnection
implementation("in.horizonos.instrumentation:httpurlconnection-library:0.0.1-alpha")
byteBuddy("in.horizonos.instrumentation:httpurlconnection-agent:0.0.1-alpha")
After adding the plugin and the dependencies to your project, your OkHttp requests will be traced automatically.
Configuration
Network instrumentation is enabled by default when using the Android agent. You can configure it during SDK initialization:
PulseSDK.INSTANCE.initialize(
application = this,
endpointBaseUrl = "https://your-backend.com",
) {
network {
enabled(true) // Enabled by default
}
}
What Gets Tracked
All HTTP requests are automatically captured, including:
- OkHttp requests (OkHttp 3.0+)
- HttpURLConnection requests
- HttpsURLConnection requests
Each network request automatically captures HTTP method, URL, status code, protocol version, server information, headers, and error details. See the Attributes section below for complete details.
Generated Telemetry
Type: Span
Span Name: HTTP {method} (e.g., HTTP GET, HTTP POST)
Span Kind: CLIENT
pulse.type: network
Attributes
Network-Specific Attributes
| Attribute | Description | Example | Always Present |
|---|---|---|---|
pulse.type | Instrumentation type | "network" | ✅ Yes |
http.method | HTTP method | "GET", "POST" | ✅ Yes |
http.url | Normalized request URL See URL Normalization for details on how URLs are normalized. | "https://api.example.com/users/[redacted]" | ✅ Yes |
http.scheme | URL scheme | "https" | ⚠️ Only if URL is parseable |
http.host | Request hostname | "api.example.com" | ⚠️ Only if URL is parseable |
http.target | Request path | "/users/123" | ⚠️ Only if URL is parseable |
http.flavor | Protocol version | "1.1", "2.0" | ⚠️ Only if available |
http.status_code | Response status code | 200, 404, 500 | ⚠️ Only if response received |
net.peer.name | Server hostname | "api.example.com" | ⚠️ Only if URL is parseable |
net.peer.port | Port number | 443, 8080 | ⚠️ Only if URL contains port |
Error Attributes (on failure)
| Attribute | Description | Example |
|---|---|---|
error | Error flag | true |
exception.type | Exception class name | "java.net.SocketTimeoutException" |
exception.message | Exception message | "Connection timed out" |
Note: The SDK automatically records exceptions on spans when network requests fail, following OpenTelemetry semantic conventions.
URL Normalization
The Pulse Android SDK automatically normalizes URLs in the http.url attribute to protect sensitive data and improve aggregation. URL normalization applies the following transformations:
Normalization Process
-
Query Parameters Removal: All query parameters are removed from the URL before normalization patterns are applied.
- Original:
https://api.example.com/users/123?token=abc&page=1 - Normalized:
https://api.example.com/users/123(before pattern matching)
- Original:
-
Pattern-Based Redaction: The following patterns in URL path segments are replaced with
[redacted]:
| Pattern | Description | Example | Normalized Result |
|---|---|---|---|
| 64-character hex strings | SHA-256 hashes | /api/files/a1b2c3d4e5f6... (64 hex chars) | /api/files/[redacted] |
| 40-character hex strings | SHA-1 hashes | /api/commits/abc123... (40 hex chars) | /api/commits/[redacted] |
| 32-character hex strings | MD5 hashes or short IDs | /api/sessions/def456... (32 hex chars) | /api/sessions/[redacted] |
| UUID format | 8-4-4-4-12 hex pattern | /api/users/550e8400-e29b-41d4-a716-446655440000 | /api/users/[redacted] |
| 24-character hex strings | MongoDB ObjectIds, etc. | /api/documents/507f1f77bcf86cd799439011 | /api/documents/[redacted] |
| 26-character ULID | ULID identifiers | /api/orders/01ARZ3NDEKTSV4RRFFQ69G5FAV | /api/orders/[redacted] |
| 3+ digit numbers | Numeric IDs (user IDs, order IDs, etc.) | /api/users/12345 | /api/users/[redacted] |
| 16+ character alphanumeric | Long alphanumeric IDs | /api/tokens/AbC123XyZ789QwE456 | /api/tokens/[redacted] |
Rationale for Normalization Patterns
-
64/40/32/24-character hex strings: These typically represent cryptographic hashes (SHA-256, SHA-1, MD5) or database IDs (MongoDB ObjectIds) that are unique identifiers and don't provide meaningful aggregation value.
-
UUID format: Universally Unique Identifiers are designed to be unique and don't benefit from being stored as-is in telemetry.
-
ULID (26 characters): Time-ordered unique identifiers that are unique per entity and don't aggregate well.
-
3+ digit numbers: Numeric IDs with 3 or more digits are commonly used for:
- User IDs (e.g.,
/users/12345) - Order IDs (e.g.,
/orders/999) - Resource IDs (e.g.,
/posts/456)
These IDs are typically unique per entity and can contain sensitive information. Normalizing them allows for better aggregation of similar endpoints while protecting user privacy. Numbers with fewer than 3 digits (like
/api/v1or/api/v2) are preserved as they often represent version numbers or small enumerations that are useful for aggregation. - User IDs (e.g.,
-
16+ character alphanumeric strings: Long alphanumeric identifiers are often tokens, session IDs, or other sensitive identifiers that should be redacted.
Note: The normalization only affects the
http.urlattribute. Other attributes likehttp.targetmay still contain the original path with query parameters, depending on how the URL is parsed.
Sample Payload: Successful Network Request
{
"name": "HTTP GET",
"kind": "CLIENT",
"startTimeUnixNano": "1701000020000000000",
"endTimeUnixNano": "1701000020317250000",
"duration": "317.25ms",
"attributes": {
"pulse.type": "network",
"http.method": "GET",
"http.url": "https://api.example.com/users/[redacted]",
"http.scheme": "https",
"http.host": "api.example.com",
"http.target": "/users/123",
"http.status_code": 200,
"http.flavor": "1.1",
"net.peer.name": "api.example.com",
"net.peer.port": 443
}
}
Sample Payload: Failed Network Request
{
"name": "HTTP POST",
"kind": "CLIENT",
"status": "ERROR",
"startTimeUnixNano": "1701000030000000000",
"endTimeUnixNano": "1701000030500000000",
"duration": "50ms",
"attributes": {
"pulse.type": "network",
"http.method": "POST",
"http.url": "https://api.example.com/orders",
"http.scheme": "https",
"http.host": "api.example.com",
"http.target": "/orders",
"http.status_code": 0,
"net.peer.name": "api.example.com",
"error": true,
"exception.type": "java.net.SocketTimeoutException",
"exception.message": "Connection timed out"
}
}
Global Attributes
All network spans include global attributes (service, device, OS, session, network carrier, etc.). See Global Attributes for complete list.