Custom Logs
Ingest your application or infrastructure logs into Middleware and analyze them in the Logs module alongside built-in sources. This guide shows how to post logs with OTLP/HTTP (JSON) using cURL, explains each field, and maps required attributes.
Prerequisites
- Your Middleware credentials
- Outbound network access from the sender to your workspace URL.
Post Your Custom Data
You can send custom logs to the Middleware backend using the API below.
HTTP endpoint:
1POST https://<YOUR_WORKSPACE>.middleware.io:443/v1/logsAuthenticate Your Request
Pass the Middleware API key in the Authorization header as shown here:
1API_KEY="<YOUR_API_KEY>"
2MW_ENDPOINT="https://<YOUR_WORKSPACE>.middleware.io:443"
3
4curl -X POST "$MW_ENDPOINT/v1/logs" \
5 -H "Accept: application/json" \
6 -H "Content-Type: application/json" \
7 -H "Authorization: $API_KEY" \
8 -d @- << 'EOF'
9{
10 "resource_logs": [
11 {
12 "resource": {
13 "attributes": [
14 { "key": "mw.resource_type", "value": { "string_value": "custom" } },
15 { "key": "service.name", "value": { "string_value": "nginx-123" } },
16 { "key": "mw.account_key", "value": { "string_value": "<YOUR_API_KEY>" } }
17 ]
18 },
19 "scope_logs": [
20 {
21 "log_records": [
22 {
23 "severity_text": "WARN",
24 "severity_number": 11,
25 "body": { "string_value": "upstream server is not accepting request" },
26 "attributes": [
27 { "key": "server", "value": { "string_value": "nginx" } }
28 ],
29 "time_unix_nano": 1758484251000000000
30 }
31 ]
32 }
33 ]
34 }
35 ]
36}
37EOFTip: Use environment variables or a secret manager for the key and avoid hard-coding.
Here:
Authorizationheader: Authenticates the HTTP request.resource.attributes.mw.resource_type=custom: Labels the source as Custom so it is easy to find in the Logs UI.resource.attributes.service.name: Lets you filter by service (optional but useful).resource.attributes.mw.account_key: Account scoping as indicated by the schema.log_records[].severity_text/severity_number: Sets human label and numeric level.log_records[].body: The actual log message (string).log_records[].attributes: Any extra dimensions you want to query on (e.g., server, environment).log_records[].time_unix_nano: Nanoseconds since Unix epoch (controls event time in the UI).
You can send multiple logs at once by adding more items to log_records (and/or more resource blocks to resource_logs) in the same request.
Understanding Resource Attributes
(JSON path: resource_logs[] → resource → attributes[])
| Key | Compliance | Description |
|---|---|---|
mw.account_key | required | Used to authenticate your data with your Middleware account. |
mw.resource_type | required | Labels the log source as "custom". |
service.name | optional | Helpful for filtering in the Logs module (e.g., service.name: nginx). |
Understanding Log Records
(JSON path: resource_logs[] → scope_logs[] → log_records[])
| Key | Compliance | Description |
|---|---|---|
severity_text | optional | One of: FATAL, ERROR, WARN, INFO, DEBUG, TRACE. |
severity_number | optional | Mapping: 1–4=TRACE, 5–8=DEBUG, 9–12=INFO, 13–16=WARN, 17–20=ERROR, 21–24=FATAL. |
body | required | The log body you want to ingest (string). |
time_unix_nano | required | Event timestamp in nanoseconds since Unix epoch (controls placement on the timeline). |
Add custom attributes (e.g., environment, host.id, region) to supercharge search, filters, and saved views.
Explore Logs & Build Queries
- Open Logs in Middleware.
- Use the search bar and filters to narrow by
service.name,mw.resource_type, severity, attributes, and time. - Save frequent queries as Saved Views for quick reuse by your team.
Set up Alerts
- Create a new Log Alert.
- Define a query (e.g.,
mw.resource_type:custom AND service.name:nginx-123 AND severity>=WARN). - Choose the evaluation window and notification channels.
- Save and monitor. Incidents trigger when the condition matches within the window.
Troubleshooting & Best Practices
- 401/403 / “No data”: Verify the
Authorizationheader, workspace URL, and (if used)mw.account_key. - Wrong time on events: Ensure
time_unix_nanois correct and the sender’s clock is synced (NTP). - Can’t find logs by service: Include
service.nameconsistently; attribute names are case-sensitive. - Sensitive data: Avoid sending secrets in
bodyor attributes; use redaction in your log pipeline where possible. - Throughput: Batch multiple
log_recordsin one request to reduce overhead.
OTLP/HTTP JSON field reference (at a glance)
| Concept | Where to put it | Example |
|---|---|---|
| Dataset tag | resource.attributes[] | mw.resource_type=custom |
| Account key | resource.attributes[] | mw.account_key=<YOUR_API_KEY> |
| Service | resource.attributes[] | service.name=nginx-123 |
| Message | log_records[].body.string_value | "upstream server is not accepting request" |
| Severity | log_records[].severity_text/number | WARN / 11 |
| Extra dims | log_records[].attributes[] | server=nginx, environment=production |
| Timestamp | log_records[].time_unix_nano | 1758484251000000000 |
Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.