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.