Skip to content

Promoting fields

Custom log fields are stored together in one JSON column, so filtering on one means parsing every log’s fields. Promoting a field copies it into its own typed column at ingest. Searches, filters and group-bys on that field then skip the JSON parsing, and number fields gain range filters (>, >=, <, <=).

Each project can promote up to 12 fields: 8 text and 4 number fields.

Promote fields you filter or group by often, such as http_status_code, duration_ms, customer_id or tenant. You don’t need to promote these, because they already have their own columns:

id, project_id, timestamp, level, message, client_ip, trace_id, span_id, service_name, service_version, k8s_namespace_name, k8s_pod_name, k8s_container_name, k8s_node_name, k8s_cluster_name, cloud_provider, cloud_region, fields

You need to be a project owner or admin. Any member can see the list.

  1. Open the project’s Project settings and find Promoted log fields.
  2. Enter the field name, for example http.status_code.
  3. Choose Text or Number.
  4. Select Promote.

Field names are normalized the same way as at ingest, so http.status_code is promoted as http_status_code (see Attribute names).

The promotion applies to logs received from then on, within about 30 seconds. Logs stored before it keep being read from the fields JSON, so queries over older data still work, just without the speed-up.

To stop promoting a field, use the delete button next to it. The field is read from the fields JSON again.

Promoted fields are queried by name, exactly like any other field. Nothing changes in your searches except speed, and range filters on number fields.

In the search bar:

duration_ms>=250 service_name:checkout
http_status_code>=500 http_status_code<600

In the Log query API, use the comparison operators on a promoted number field:

{
"type": "condition",
"condition": { "field": "duration_ms", "operator": "greater_or_equal", "value": 250 }
}
Field Operators
Promoted text field, and any other custom field equals, not_equals, contains, not_contains, exists, not_exists
Promoted number field The above plus greater_than, greater_or_equal, less_than, less_or_equal

The settings page uses these routes, under /api/v1 with a user session token (see Authentication):

Method and path Purpose Who
GET /projects/{id}/promoted-fields List active promotions Any member
POST /projects/{id}/promoted-fields Promote a field Owners and admins
DELETE /projects/{id}/promoted-fields/{field} Stop promoting a field Owners and admins

Promote a field:

Terminal window
curl -X POST "https://obzly.harborline.example/api/v1/projects/YOUR_PROJECT_ID/promoted-fields" \
-H "Authorization: Bearer YOUR_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"field": "duration_ms", "type": "number"}'

type is string or number. The response is the promotion:

{
"projectId": "YOUR_PROJECT_ID",
"slot": "n1",
"field": "duration_ms",
"createdAt": "2026-10-01T12:00:00Z"
}

Text promotions use slots s1 to s8 and number promotions n1 to n4. A request fails with 400 when the field is reserved, already promoted, or no column of that type is left, and with 403 when you can’t manage the project. Promotions and removals are written to the project’s audit log.