Logfmt Log Parser
observability.parse_logfmt
Overview
You send logfmt text and we return one record per line plus an error report that names the line and column of every pair we could not read. The grammar is published in full: a bare value may contain an equals sign, a bare key comes back as null where an empty assignment comes back as an empty string, and an unterminated quote ends that line rather than turning the rest of it into fields nobody logged. Malformed pairs never fail the call, so one stray quote in fifty thousand lines still gives you the other lines. We hold nothing, forward nothing and read no clock.
Nothing else in the catalog turns logfmt into structured fields: the log redactor labels the format but still returns text, so you had to write the grammar yourself and get the equals-sign and quoting rules wrong.
Reliability
Fully deterministic: the same body and options always give you the same records, independent of locale, default time zone and default charset. Malformed pairs are reported rather than fatal, so plan on reading errors on a successful call. Failures, none worth retrying unchanged: OBS_LOGFMT_INPUT_MISSING means neither logs nor fileRef arrived, so send one of them. OBS_LOGFMT_INPUT_INVALID means logs or fileRef was not a string, or the body was empty, so check the payload shape. OBS_LOGFMT_INPUT_TOO_LARGE means the inline body went past 2097152 bytes, so upload it and pass a file reference instead. OBS_LOGFMT_FILE_REF_NOT_ACCESSIBLE means the reference is not readable with these credentials, so upload the object again and use the new reference. OBS_LOGFMT_FILE_TOO_LARGE means the referenced object went past 10000000 bytes, so split it and call once per part. OBS_LOGFMT_LINE_LIMIT_EXCEEDED means the body carries more lines than your maxLines allows, so raise it up to 50000 or split the body. OBS_LOGFMT_FIELD_LIMIT_EXCEEDED means the parse produced more than 200000 fields in total, more than a response can carry, so split the body or turn includeRecords off. OBS_LOGFMT_LIMITS_INVALID means one of the limits fell outside its published range, so bring it back inside and send it again. OBS_LOGFMT_OPTION_UNSUPPORTED means a property or an option value is not one we accept, so drop it or pick a listed value. OBS_LOGFMT_WORK_REFUSED means the projected work went past 16000000 units, and the answer carries both the projection and the budget so you can size a request that fits. OBS_LOGFMT_OUTPUT_TOO_LARGE means the records would not fit the inline response ceiling, so set includeRecords false or send fewer lines.
Context footprint
Returns one record per line, so a large body comes back large; set includeRecords false when you only want the counts and the error report. A successful call costs 3 execution credits.
When to use it
When you hold logfmt text and want records you can query, plus a precise report of what your producer is emitting badly.
When your lines are JSON objects, when you want them grouped rather than parsed, or when you need the text redacted.
Scope
Non-goals
- Does not store, buffer, index or forward anything between calls
- Does not scrape, poll or receive logs over a network
- Does not redact or mask anything — send the text to security.redact_secrets first
- Does not interpret what a field means or what an error was caused by
- Does not accept a caller-supplied regular expression on any field
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
File limits
Constraints this skill applies to your input and generated files. The “Limited by” column shows the static source of each cap; none of these can be raised by upgrading your plan.
| Limit | Value | Limited by |
|---|---|---|
| Maximum size per input file | 9.5 MiB | Skill and platform maximum |
| Maximum number of input files | 1 | Skill maximum |
How we handle your data
What this means
This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response may contain submitted or transformed content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| logs | string | No | Required unless fileRef is provided. Logfmt text of 1 to 2097152 UTF-8 bytes. |
| fileRef | string | No | Optional Squillify file reference holding up to 10000000 bytes of logfmt text; omit it to parse the inline logs field. |
| limits | object | No | Closed caps you can tighten; omit it for maxLines 50000, maxLineLength 8192, maxFieldsPerLine 64, maxValueLength 1024 and maxErrors 500. |
| includeRecords | boolean | No | Whether parsed records are echoed; omit it for true. |
| onDuplicateKey | string | No | Which occurrence of a repeated key survives; omit it for LAST_WINS. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| records | array | Yes | One {line, fields} object per parsed line; empty when includeRecords is false. |
| errors | array | Yes | Up to maxErrors malformed pairs, each a closed {line, column, code} object with optional key. |
| summary | object | Yes | Closed run counters: lineCount, recordCount, blankLineCount, fieldCount, errorCount, errorsTruncated, truncated and sourceKind. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"observability.parse_logfmt","input":{"logs":"level=info msg=\"request served\" duration_ms=42\n"}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("observability.parse_logfmt", {"logs":"level=info msg=\"request served\" url=https://api.example.com/p?a=b&c=d retry\nlevel=warn msg=\"slow upstream\" duration_ms=812\n"});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| OBS_LOGFMT_INPUT_MISSING | 400 | No | The request payload failed this skill's input validation. |
| OBS_LOGFMT_INPUT_INVALID | 400 | No | The request payload failed this skill's input validation. |
| OBS_LOGFMT_INPUT_TOO_LARGE | 429 | No | A size, quota, rate, or time limit was exceeded. |
| OBS_LOGFMT_FILE_REF_NOT_ACCESSIBLE | 412 | No | The input is valid but cannot be processed as-is. |
| OBS_LOGFMT_FILE_TOO_LARGE | 429 | No | A size, quota, rate, or time limit was exceeded. |
| OBS_LOGFMT_LINE_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| OBS_LOGFMT_FIELD_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| OBS_LOGFMT_LIMITS_INVALID | 400 | No | The request payload failed this skill's input validation. |
| OBS_LOGFMT_OPTION_UNSUPPORTED | 400 | No | The skill does not support the requested variant. |
| OBS_LOGFMT_WORK_REFUSED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| OBS_LOGFMT_OUTPUT_TOO_LARGE | 429 | No | A size, quota, rate, or time limit was exceeded. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not store, buffer, index or forward anything between calls
- Does not scrape, poll or receive logs over a network
- Does not redact or mask anything — send the text to security.redact_secrets first
- Does not interpret what a field means or what an error was caused by
- Does not accept a caller-supplied regular expression on any field
- Reading newline-delimited JSON logs, which observability.parse_json_logs answers
- Removing secrets from a log body before you share it
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "observability.parse_logfmt",
"input": {
"logs": "level=info msg=\"request served\" url=https://api.example.com/p?a=b&c=d retry\nlevel=warn msg=\"slow upstream\" duration_ms=812\n"
}
}Examples
Two request lines with a bare key and a URL value
{
"logs": "level=info msg=\"request served\" url=https://api.example.com/p?a=b&c=d retry\nlevel=warn msg=\"slow upstream\" duration_ms=812\n"
}{
"records": [
{
"line": 1,
"fields": {
"level": "info",
"msg": "request served",
"url": "https://api.example.com/p?a=b&c=d",
"retry": null
}
},
{
"line": 2,
"fields": {
"level": "warn",
"msg": "slow upstream",
"duration_ms": "812"
}
}
],
"errors": [],
"summary": {
"lineCount": 2,
"recordCount": 2,
"blankLineCount": 0,
"fieldCount": 7,
"errorCount": 0,
"errorsTruncated": false,
"truncated": false,
"sourceKind": "INLINE"
}
}A stray quote reported without failing the call
{
"includeRecords": false,
"logs": "level=error msg=\"unterminated\n"
}{
"records": [],
"errors": [
{
"line": 1,
"code": "UNTERMINATED_QUOTE",
"column": 17,
"key": "msg"
}
],
"summary": {
"lineCount": 1,
"recordCount": 1,
"blankLineCount": 0,
"fieldCount": 1,
"errorCount": 1,
"errorsTruncated": false,
"truncated": false,
"sourceKind": "INLINE"
}
}Recommended use cases
- Turn a captured logfmt stream into records you can filter and join
- Find the exact line and column where a producer emits malformed pairs
Avoid for
- Reading newline-delimited JSON logs, which observability.parse_json_logs answers
- Removing secrets from a log body before you share it
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.