
Cx Data Pipeline
- 1.4k installs
- 113 repo stars
- Updated August 4, 2026
- coralogix/cx-cli
cx-data-pipeline is a Coralogix cx-cli skill that configures log parsing, enrichment tables, Events2Metrics conversions, and PromQL recording rules from the terminal for developers who manage Coralogix data pipelines.
About
cx-data-pipeline is a Coralogix cx-cli skill (metadata version 0.1.0) for configuring how ingested logs and spans are parsed, enriched, and converted into metrics without leaving the coding agent. It wraps four CLI command families: cx parsing-rules, cx enrichments (including custom lookup tables), cx e2m for Events2Metrics, and cx recording-rules for PromQL precomputation. The recommended workflow templates existing JSON with get, edits fields, then create or update via --from-file to avoid payload format errors—the documented top cause of failed rule attempts. Coverage includes regex field extraction, geo enrichment, labels cardinality checks, E2M troubleshooting when series are missing, and bulk-delete for parsing rules. Reach for cx-data-pipeline when you need to reduce log costs via metrics aggregation, add lookup context to logs, or stand up recording rules alongside Coralogix telemetry querying.
- Manages parsing rules: list, get, create, update, delete, bulk-delete, usage-limits
- Handles enrichments including lookup tables, geo enrichment, and custom context
- Creates and troubleshoots Events2Metrics (E2M) definitions to convert logs/spans to metrics
- Supports PromQL recording rules and precomputed metrics for cost reduction
- Covers 20+ trigger phrases for data pipeline configuration and optimization
Cx Data Pipeline by the numbers
- 1,374 all-time installs (skills.sh)
- +107 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #220 of 2,064 Data Science & ML skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/coralogix/cx-cli --skill cx-data-pipelineAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.4k |
|---|---|
| repo stars | ★ 113 |
| Last updated | August 4, 2026 |
| Repository | coralogix/cx-cli ↗ |
How do you configure Coralogix log parsing and E2M rules?
Configure Coralogix log parsing, enrichment tables, Events2Metrics conversions, and recording rules without leaving the coding agent.
Who is it for?
Platform and observability engineers managing Coralogix pipelines who want agent-guided cx CLI configuration for parsing, enrichment, and metrics.
Skip if: Skip cx-data-pipeline when you are not on Coralogix or only need to query existing logs without changing parsing, enrichment, or E2M rules.
When should I use this skill?
User asks to set up log parsing, enrichment tables, Events2Metrics, recording rules, or fix E2M series not appearing in Coralogix.
What you get
Parsing rule groups, enrichment tables, Events2Metrics definitions, and PromQL recording rule JSON configs
- parsing rule group JSON
- E2M definition
- recording rule group config
By the numbers
- Covers 4 cx CLI command families for data pipeline configuration
- Skill metadata version 0.1.0
Files
Data Pipeline Skill
Use this skill when configuring how Coralogix processes, enriches, and transforms data. It covers parsing rules (extract structured fields from raw logs), enrichments (add context from lookup tables), Events2Metrics (derive metrics from log/span events), and recording rules (precompute PromQL expressions).
---
CLI Commands
| Command | Subcommands | Purpose |
|---|---|---|
cx parsing-rules | list, get, create, update, delete, bulk-delete, usage-limits | Manage log parsing rules |
cx enrichments | list, add, remove, overwrite, limit, settings | Manage enrichment rules |
cx enrichments custom | list, get, create, update, delete, search | Manage custom enrichment tables |
cx e2m | list, get, create, update, delete, labels-cardinality, limits | Manage Events2Metrics definitions |
cx recording-rules | list, get, create, update, delete | Manage Prometheus recording rule groups |
Key flags:
- All create/update operations use
--from-file <path>(or-for stdin) - All commands support
-o jsonfor structured output and-p <profile>for profile selection cx parsing-rules updateandcx recording-rules updaterequire both--from-fileand the rule group IDcx enrichments custom searchrequires--id <table-id>and--query <text>cx parsing-rules bulk-deleterequires--ids <id1> <id2> ...
---
Working with JSON Payloads
These commands use complex JSON structures. Always template from an existing resource to avoid format errors:
# 1. Get an existing resource as a template
cx parsing-rules get <rule-group-id> -o json > template.json
# 2. Modify the template (change fields, remove the ID for create operations)
# 3. Create or update
cx parsing-rules create --from-file template.json
cx parsing-rules update --from-file template.json <rule-group-id>This pattern applies to all create/update operations across all 4 commands. It prevents payload format errors that are the #1 cause of failed attempts.
---
Parsing Rules Workflow
1. List Existing Rules
cx parsing-rules list -o json
cx parsing-rules list -o json | jq '[.[] | {id, name, enabled, rule_count: (.rules | length)}]'2. Get a Template
cx parsing-rules get <existing-rule-group-id> -o json > rule-template.json3. Create New Rule Group
Edit the template for your new service, then:
cx parsing-rules create --from-file rule-template.json4. Verify Parsing
Query recent logs to confirm fields are extracted (load cx-telemetry-querying for log querying):
cx logs 'source logs | filter $d.subsystem == "my-service" | limit 10' -o json5. Check Usage Limits
cx parsing-rules usage-limits -o json---
Enrichment Workflow
1. List Enrichment Rules
cx enrichments list -o json
cx enrichments settings -o json
cx enrichments limit -o json2. Create Custom Enrichment Table (if needed)
cx enrichments custom list -o json
cx enrichments custom create --from-file table-definition.jsontable-definition.json must use the v5 JSON shape (inline file content, not multipart file=@...):
{
"name": "IP Lookup",
"description": "Maps IPs to locations",
"file": {
"textual": "ip,city\n1.2.3.4,London",
"extension": "csv",
"name": "lookup.csv",
"size": 24
}
}For updates, include customEnrichmentId (number) plus the same fields.
3. Add Enrichment Rules
cx enrichments add --from-file enrichment-rules.jsonenrichment-rules.json must use requestEnrichments (not enrichments from list output). Each enrichmentType is an object, not a string:
{
"requestEnrichments": [
{
"fieldName": "sourceIPs",
"enrichmentType": { "geoIp": { "withAsn": true } }
}
]
}Other types: {"aws": {"resourceType": "ec2"}}, {"suspiciousIp": {}}, {"customEnrichment": {"id": 1}}.
4. Search Custom Table Data
cx enrichments custom search --id <table-id> --query "search term"5. Verify Enriched Fields
Query logs on hot storage (FrequentSearch tier) to confirm enriched fields appear. Avoid querying archive for verification - ingestion delays can cause false negatives.
cx logs 'source logs | filter $d.enriched_field != null | limit 5' -o json---
Events2Metrics Workflow
E2M derives Prometheus metrics from log/span events. See [`references/e2m-schemas.md`](references/e2m-schemas.md) for the full JSON wire format, enums, and cardinality rules.
How E2M is computed (read this first)
E2M aggregates events as they stream through the real-time ingestion pipeline into metric series (~1-min resolution). It is forward-only — metrics start from the moment the E2M is created; there is no backfill.
All ingested data flows through the pipeline; a TCO policy routes each stream into a tier, and the tier decides what's possible:
| TCO tier | Storage | E2M / alerts / dashboards |
|---|---|---|
| High | Frequent Search (hot, OpenSearch) | ✅ available |
| Medium | S3 archive (not hot storage) | ✅ available — still processed by the pipeline |
| Low | Compliance only | ❌ no aggregation features |
| Blocked | dropped | ❌ |
The axis is tier / processing level — NOT "Frequent Search vs archive" (Medium is archive and E2M works on it). Do not tell users to "point E2M at archive instead of Frequent Search" — that is incorrect.
1. Design the metric
Choose logs2metrics vs spans2metrics, the source field(s) + aggregations, and labels (with cardinality in mind — see references/e2m-schemas.md). To scope the E2M to a dataset, set the optional dataSource field to "<dataspace>/<dataset>"; this requires the account feature e2m_dataset_source_enabled (otherwise the API rejects it with "dataSource is not enabled for this company"). Omit it for the standard logs/spans stream.
2. Size it: check limits & cardinality
cx e2m limits -o json # account E2M count limit + used
cx e2m labels-cardinality -o json # see caveat belowThe labels-cardinality endpoint is a draft forecast — given proposed labels + query it returns the per-day distinct-permutation count over the last 7 days, so you can size a design before creating it. But `cx e2m labels-cardinality` currently takes no arguments, so it sends no draft and returns an empty list (a CLI gap — it can't forecast yet). Until that's wired up, forecast via the UI or estimate permutations manually (product of distinct label values) and set permutationsLimit. Never use high-cardinality fields (IDs, raw URLs, IPs) as labels. Note the forecast only sees Frequent-Search (High-tier) data.
3. Template from an existing definition
Only cx e2m get returns the full payload ({"e2m": {...}}); list prints a summary. Extract .e2m and drop read-only fields:
cx e2m get <existing-e2m-id> -o json | jq '.e2m | del(.id, .permutations, .createTime, .updateTime, .metricName)' > e2m.json4. Create the E2M
cx e2m create --from-file e2m.json5. Verify the metric
Confirm series are being produced (load cx-telemetry-querying for metrics querying):
cx metrics search --name "<targetBaseMetricName>"
cx metrics query "<target_metric_name>" --time nowTroubleshooting: E2M produces no metric series
1. Check the source data's TCO tier — if it's routed to Low/compliance (or blocked), E2M cannot run. Fix with a TCO change (cx tco list / cx-cost-optimization), not an E2M change. 2. Verify the query matches streaming data — run the E2M's lucene filter as a live cx logs/cx spans query and confirm it returns recent results. Note cx logs queries Frequent-Search (High-tier) by default; for a Medium-tier (archive) source add --tier archive, since the data won't appear in a default Frequent-Search query even though E2M still produces series. 3. Remember it's forward-only — no series exist for data ingested before the E2M was created.
Cost optimization: convert High-tier logs to metrics
When the aggregated/metric view is what the customer most cares about, convert High-tier logs → metrics, then downgrade the raw logs High → Medium. Medium still supports E2M/alerts/dashboards and costs less (S3 archive, no hot storage) — you keep cheap, detailed metrics while dropping expensive Frequent-Search retention.
1. Find high-volume High-tier sources: cx usage summary / cx tco list (see cx-cost-optimization). 2. Confirm which fields drive dashboards/alerts (see cx-telemetry-querying). 3. Build + verify the E2M first (steps above). 4. Then change the TCO policy to move the raw logs High → Medium. Keep data on High or Medium (both support E2M); do not drop it to Low/compliance if metrics or alerts are still needed.
---
Recording Rules Workflow
1. List Existing Recording Rules
cx recording-rules list -o json
cx recording-rules list -o json | jq '[.[] | {id, name, rules: [.rules[]?.record]}]'2. Get a Template
cx recording-rules get <existing-id> -o json > recording-rule-template.json3. Create Recording Rule Group
cx recording-rules create --from-file recording-rule-group.json4. Verify with PromQL
Confirm the precomputed metric is available (load cx-telemetry-querying for metrics querying):
cx metrics query "new_precomputed_metric" --time now---
Key Principles
- Always template from existing -
cx <command> get <id> -o json > template.jsonbefore any create - Verify after create - query logs/metrics to confirm the pipeline change took effect
- Use `-o json` - all payload inspection and creation should use JSON output
- Check limits first -
cx parsing-rules usage-limitsandcx e2m limitsbefore creating to avoid hitting caps - Bulk operations - use
cx parsing-rules bulk-delete --idsfor cleanup, not individual deletes
---
Additional Resources
Reference Files
- [`references/e2m-schemas.md`](references/e2m-schemas.md) - Complete Events2Metrics JSON wire format:
type/aggTypeenum values,logsQuery/spansQueryfilters, metric labels & fields, the TCO-tier compute model, cardinality/permutations sizing, and gotchas
---
Related Skills
- `cx-telemetry-querying` - discover what data is available before configuring pipeline, and verify parsing results, enriched fields, and E2M metric series via log/metrics queries
- `cx-cost-optimization` - find high-volume High-tier sources worth converting to metrics, and move the raw logs High→Medium (TCO) after the E2M is verified
Events2Metrics (E2M) Schema Reference
Complete JSON schema reference for Coralogix Events2Metrics definitions, using the actual REST API wire format that cx e2m reads and writes. Use this when constructing payloads for cx e2m create / cx e2m update.
Tip: The most reliable way to build an E2M is to fetch an existing one withcx e2m get <id> -o json, strip the read-only fields, modify, and pipe it intocx e2m create --from-file -. Note thatcx e2m listandcx e2m createprint a simplified view (id/name/type/metric_name) — only `cx e2m get` returns the full definition you can template from.
How E2M is computed (read this first)
E2M is not a stored query — it aggregates events as they stream through the real-time ingestion pipeline into metric series (~1-minute resolution). It is forward-only: metrics start accumulating from the moment the E2M is created; there is no backfill.
- All ingested data flows through the ingestion pipeline; a TCO policy routes each stream into a tier.
- E2M works on data in High tier (Frequent Search / hot storage) and Medium tier (lands in S3 archive, but still processed by the pipeline).
- E2M does NOT work on Low / compliance tier (compliance storage only, no aggregation features) or blocked data.
- The axis is tier / processing level — not "Frequent Search vs archive" (Medium is archive and E2M works on it).
If an E2M produces zero metric series, the usual cause is that its source data is routed to Low/compliance (or the query matches nothing) — the fix is a TCO change, not an E2M change. See the SKILL workflow's troubleshooting section.
---
Source types
The type field + query oneof select what events are aggregated:
type (string enum) | query field | Source |
|---|---|---|
E2M_TYPE_LOGS2METRICS | logsQuery | Logs |
E2M_TYPE_SPANS2METRICS | spansQuery | Spans |
E2M_TYPE_UNSPECIFIED (0) is never used in a real definition.
Datasets (`dataSource`): an optional top-level dataSource string in "<dataspace>/<dataset>" format (e.g. "my_dataspace/my_dataset") scopes the E2M to a specific dataset instead of the standard logs/spans stream. It is supported via the API/CLI — add it to the create body. If omitted, the E2M defaults to the standard logs/spans stream for the chosen type.
Requires an account feature flag.dataSourceis gated behinde2m_dataset_source_enabledper company. If the feature isn't enabled, the API rejects the definition with"dataSource is not enabled for this company". If you hit that error, the account needs the feature turned on — it's not a payload problem.
{ "type": "E2M_TYPE_LOGS2METRICS", "dataSource": "my_dataspace/my_dataset", "logsQuery": { ... } }---
Top-level structure
cx e2m create and cx e2m update post the bare definition object (the HTTP body maps to the e2m field). A cx e2m get response wraps the same object as {"e2m": { ... }}, so when templating, extract .e2m.
Creating a new E2M — drop id (and other read-only fields); the server assigns a fresh id:
cx e2m get <id> -o json | jq '.e2m | del(.id, .permutations, .createTime, .updateTime, .metricName)' > e2m.json
cx e2m create --from-file e2m.jsonUpdating an existing E2M — cx e2m update is a PUT with no id in the path, so the body must keep `id` (it's the only identifier the API uses). Drop only the server-derived fields:
cx e2m get <id> -o json | jq '.e2m | del(.permutations, .createTime, .updateTime, .metricName)' > e2m.json
# edit e2m.json (keep "id"), then:
cx e2m update --from-file e2m.jsonCreate payload (E2MCreateParams)
{
"name": "service_catalog_latency",
"description": "avg + sum latency for catalog service",
"permutationsLimit": 30000,
"type": "E2M_TYPE_LOGS2METRICS",
"logsQuery": {
"lucene": "coralogix.metadata.applicationName:catalog",
"applicationnameFilters": [],
"subsystemnameFilters": [],
"severityFilters": ["SEVERITY_ERROR", "SEVERITY_CRITICAL"]
},
"metricLabels": [
{ "targetLabel": "app", "sourceField": "coralogix.metadata.applicationName" },
{ "targetLabel": "subsystem", "sourceField": "coralogix.metadata.subsystemName" }
],
"metricFields": [
{
"targetBaseMetricName": "latency_ms",
"sourceField": "log_obj.latency_ms",
"aggregations": [
{ "enabled": true, "aggType": "AGG_TYPE_COUNT", "targetMetricName": "latency_ms_count" },
{ "enabled": true, "aggType": "AGG_TYPE_AVG", "targetMetricName": "latency_ms_avg" },
{ "enabled": true, "aggType": "AGG_TYPE_SUM", "targetMetricName": "latency_ms_sum" }
]
}
]
}Field reference
| Field | Type | Notes |
|---|---|---|
name | string | Required. |
description | string | Optional. |
permutationsLimit | int | Create-only. Caps the label permutation cardinality (e.g. 30000). |
type | enum string | E2M_TYPE_LOGS2METRICS or E2M_TYPE_SPANS2METRICS. Required. |
dataSource | string | Optional. "<dataspace>/<dataset>" to scope to a dataset; omit for the standard logs/spans stream. |
logsQuery / spansQuery | object | The query oneof — exactly one, matching type. |
metricLabels[] | array | Each label becomes a Prometheus label. Each distinct value set multiplies permutations. |
metricFields[] | array | Max 10. Each holds a source field + its aggregations. |
`id` — UUID. Omit on `create` (server assigns it); required in the body on `update` (the PUT has no path id). Present in get responses.
Server-derived fields (present in get responses; drop from create/update bodies): permutations ({limit, hasExceededLimit}), createTime, updateTime, metricName, isInternal.
logsQuery
| Field | Type |
|---|---|
lucene | string (Lucene filter) |
alias | string (optional) |
applicationnameFilters[] | string[] |
subsystemnameFilters[] | string[] |
severityFilters[] | enum string[] — see below |
Severity enum values: SEVERITY_DEBUG, SEVERITY_VERBOSE, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR, SEVERITY_CRITICAL.
spansQuery
| Field | Type |
|---|---|
lucene | string (Lucene filter) |
applicationnameFilters[] | string[] |
subsystemnameFilters[] | string[] |
actionFilters[] | string[] |
serviceFilters[] | string[] |
metricLabels[]
{ "targetLabel": "app", "sourceField": "coralogix.metadata.applicationName" }targetLabel— the output Prometheus label name. Pattern^[\w/-]+$.sourceField— the event field to read the value from (e.g.coralogix.metadata.applicationName,log_obj.region).
metricFields[] and aggregations[]
{
"targetBaseMetricName": "latency_ms",
"sourceField": "log_obj.latency_ms",
"aggregations": [
{ "enabled": true, "aggType": "AGG_TYPE_HISTOGRAM", "targetMetricName": "latency_ms_histogram",
"histogram": { "buckets": [10, 50, 100, 500, 1000] } },
{ "enabled": true, "aggType": "AGG_TYPE_SAMPLES", "targetMetricName": "latency_ms_max",
"samples": { "sampleType": "SAMPLE_TYPE_MAX" } }
]
}targetBaseMetricName— base name; each aggregation gets its owntargetMetricName. Pattern^[\w/-]+$.sourceField— numeric event field to aggregate. (ForAGG_TYPE_COUNTthe value is irrelevant — it counts matching events.)
`aggType` values:
aggType (string enum) | Meaning | Extra metadata |
|---|---|---|
AGG_TYPE_MIN | minimum | - |
AGG_TYPE_MAX | maximum | - |
AGG_TYPE_COUNT | event count | - |
AGG_TYPE_AVG | average | - |
AGG_TYPE_SUM | sum | - |
AGG_TYPE_HISTOGRAM | bucketed distribution | histogram.buckets: float[] (bucket boundaries; ≥1 bucket) |
AGG_TYPE_SAMPLES | sampled min/max | samples.sampleType: SAMPLE_TYPE_MIN or SAMPLE_TYPE_MAX |
Each aggregation: enabled (bool), aggType (string enum), targetMetricName (string), plus the agg_metadata oneof (histogram or samples) only for those two types.
---
Cardinality & Limits
Permutations = the product of the number of distinct values across all `metricLabels`. A label on app (20 values) × subsystem (15) × status_code (40) = 12,000 permutations. Add one high-cardinality label and it explodes.
- Never use high-cardinality fields as labels: user IDs, request/trace IDs, session IDs, raw URLs, full paths, IPs, timestamps. These multiply permutations without bound and will breach the limit.
- Keep labels to bounded, low-cardinality dimensions (app, subsystem, region, status class, severity, endpoint group).
permutationsLimitcaps the design; if exceeded, the read-backpermutations.hasExceededLimitistrueand new permutations stop being produced.
Checking limits and forecasting cardinality:
cx e2m limits -o json # account E2M count limit + used
cx e2m labels-cardinality -o json # see caveat belowcx e2m limitsreports the E2M count limit and how many are used (the underlying API also tracks labels/permutations/metrics caps).- The labels-cardinality endpoint is a draft forecast tool. Given a proposed query +
metricLabels, the backend runs a cardinality aggregation over the last 7 days of the company's logs/spans and returns the distinct label-permutation count per day for exactly that draft design — so you can size a design before creating it. With no labels supplied it returns an empty result. - CLI limitation:
cx e2m labels-cardinalitycurrently takes no arguments, so it sends no draft and returns an empty list — it does not expose the forecast yet (it would need--metric-labels/--query). Until then, forecast a draft via the Coralogix UI (the create flow calls this endpoint with your labels+query), or estimate manually (below) as a rough check. - The forecast only sees Frequent-Search (High-tier) data — it queries the hot
*_newlogs*index. For a Medium-tier (archive) source it will undercount, so treat manual estimates as the floor.
Manual estimate (rough fallback) — sizing a 2-label design:
- Labels:
app(~12 distinct),severity(6 distinct). - Estimated permutations = 12 × 6 = 72 — comfortably under any limit.
- Adding
endpoint(~300 distinct) → 12 × 6 × 300 = 21,600. Closer to limits; prefer grouping endpoints into a boundedroutefield, or drop the label and filter inluceneinstead.
---
Gotchas
- Enums are strings, not integers. Use
"type": "E2M_TYPE_LOGS2METRICS"and"aggType": "AGG_TYPE_AVG"— not1/4. (Some internal/legacy exports use integers and a$casediscriminator; thecxCLI uses the OpenAPI string form.) - Template from `get`, not `list`.
cx e2m list/createprint a simplified summary; onlycx e2m get <id> -o jsonreturns the full definition ({"e2m": {...}}). - Create/update body is the bare object, not wrapped in
{"e2m": ...}. Extract.e2mfrom agetresponse first. - `update` (replace) requires `id` in the body — the PUT has no path id, so dropping
idmakes the update fail to find the rule.createmust omitid. - Simple aggregations (MIN/MAX/COUNT/AVG/SUM) need no `agg_metadata` — only
histogramandsamplescarry metadata. (The proto models the empty case as anonemarker; in JSON, just omit the metadata.) - Max 10 metric fields per E2M.
- `targetMetricName` must be unique within the definition; collisions silently clobber series.
- Forward-only. Creating an E2M never backfills historical data — only events ingested after creation produce series.
- Verify with metrics, not logs:
cx metrics search --name "<targetBaseMetricName>"then a PromQL query.
Related skills
How it compares
Use cx-data-pipeline over generic CLI help when you need Coralogix-specific E2M, enrichment, and parsing workflows with JSON templating patterns.
FAQ
Which cx CLI commands does cx-data-pipeline cover?
cx-data-pipeline documents four command families: cx parsing-rules, cx enrichments (plus custom tables), cx e2m for Events2Metrics, and cx recording-rules for PromQL precomputation. Create and update operations use --from-file JSON payloads.
How should you avoid Coralogix rule payload errors?
cx-data-pipeline recommends templating from an existing resource with get -o json, editing the export, then running create or update --from-file. The skill notes malformed JSON payloads as the primary cause of failed rule attempts.