Retain Custom Headers¶
This guide explains how to retain custom span headers in the Traceable Platform using span ingestion rules from the Traceable Operator (TI) GraphQL console.
Overview¶
Span ingestion rules control which span attributes are persisted or discarded when spans are written to backend stores such as Pinot. To retain custom headers, create request header rules with retentionAction: RETAIN.
Rules are ranked and evaluated in order. The highest-ranked rule is evaluated first, and the action from the first matching rule is applied. If no rule matches, the default action for the category is applied.
Default rules exist for each category. These default rules have the lowest rank and cannot be updated, deleted, or ranked.
Prerequisites¶
Before proceeding, ensure you have:
- Admin user access to the Traceable Platform
- Access to the Traceable Operator (TI)
- The DNS name for the deployment
- The custom request header names that must be retained
Access the GraphQL Console¶
Step 1: Login to the Platform¶
Open the Traceable Platform in a new browser tab:
Login with an admin user.
Step 2: Login to the Traceable Operator¶
Open the Traceable Operator (TI):
Login with your TI credentials.
Step 3: Open GraphQL¶
In the TI, click GraphQL.
Step 4: Run the Query¶
Paste the required GraphQL query or mutation into the editor, then click the Run button.
Rule Template¶
Span ingestion rules use the following structure:
id
predicate {
targetKeyPredicate {
value
operator
anyOfValues
}
}
retentionAction
expiration
scope {
environmentIds
}
| Field | Description |
|---|---|
id |
Rule ID. The ID is auto-generated when the rule is created. |
predicate.targetKeyPredicate.operator |
Key matching operator. Supported values are EQUALS, STARTS_WITH, ENDS_WITH, and CONTAINS. |
predicate.targetKeyPredicate.value |
Single header name to match. |
predicate.targetKeyPredicate.anyOfValues |
Multiple header names to match. A match occurs if the header matches any value in the list. |
retentionAction |
Action to apply when the rule matches. Use RETAIN to keep custom headers. |
expiration |
Optional expiration time for the rule. After this time, the rule is no longer applied. |
scope.environmentIds |
Optional list of environment IDs where the rule applies. If scope is not set, the rule applies to all environments. |
Important: Use either value or anyOfValues in a single rule. Do not provide both.
Get Existing Request Header Rules¶
Use the following query to list existing request header rules:
{
spanIngestionRules(
input: { ingestionStage: INGESTION_STAGE_QUERY_STORE_PERSISTENCE }
) {
requestHeaderRules {
defaultRuleAction
rules {
id
expiration
predicate {
targetKeyPredicate {
value
operator
anyOfValues
}
}
retentionAction
scope {
environmentIds
}
}
}
}
}
Expected response:
{
"data": {
"spanIngestionRules": {
"requestHeaderRules": {
"defaultRuleAction": "RETAIN",
"rules": [
{
"id": "1c28a809-9de5-4d57-869f-156582145238",
"expiration": null,
"predicate": {
"targetKeyPredicate": {
"value": "my-header",
"operator": "EQUALS",
"anyOfValues": null
}
},
"retentionAction": "RETAIN",
"scope": null
}
]
}
}
}
}
Retain a Single Custom Header¶
Use this mutation to retain one custom request header:
mutation {
createSpanIngestionRule(
input: {
ingestionStage: INGESTION_STAGE_QUERY_STORE_PERSISTENCE
requestHeaderRuleData: {
predicate: {
targetKeyPredicate: { operator: EQUALS, value: "my-header" }
}
retentionAction: RETAIN
expiration: "2026-12-31T23:59:59.000Z"
}
}
) {
id
expiration
predicate {
targetKeyPredicate {
operator
value
anyOfValues
}
}
retentionAction
scope {
environmentIds
}
}
}
Expected response:
{
"data": {
"createSpanIngestionRule": {
"id": "8d9ab022-f6a8-47a6-b507-dbdde5f638e7",
"expiration": "2026-12-31T23:59:59Z",
"predicate": {
"targetKeyPredicate": {
"operator": "EQUALS",
"value": "my-header",
"anyOfValues": null
}
},
"retentionAction": "RETAIN",
"scope": null
}
}
}
Retain Multiple Custom Headers¶
Use anyOfValues to retain multiple custom request headers:
mutation {
createSpanIngestionRule(
input: {
ingestionStage: INGESTION_STAGE_QUERY_STORE_PERSISTENCE
requestHeaderRuleData: {
predicate: {
targetKeyPredicate: {
operator: EQUALS
anyOfValues: ["my-header-1", "my-header-2"]
}
}
retentionAction: RETAIN
scope: { environmentIds: ["<environment-id>"] }
}
}
) {
id
expiration
predicate {
targetKeyPredicate {
operator
value
anyOfValues
}
}
retentionAction
scope {
environmentIds
}
}
}
Update Retained Headers¶
Use the rule ID returned by the create or list operation:
mutation {
updateSpanIngestionRule(
input: {
id: "<rule-id>"
predicate: {
targetKeyPredicate: {
operator: EQUALS
anyOfValues: ["my-header-1", "my-header-2", "my-header-3"]
}
}
retentionAction: RETAIN
scope: { environmentIds: ["<environment-id>"] }
}
) {
id
expiration
predicate {
targetKeyPredicate {
operator
value
anyOfValues
}
}
retentionAction
scope {
environmentIds
}
}
}
Rank a Rule¶
Use this mutation to move a rule after another rule:
mutation {
rankSpanIngestionRule(
input: {
id: "<rule-id>"
precedingRuleId: "<preceding-rule-id>"
}
) {
success
}
}
Expected response:
Delete a Rule¶
Use this mutation to delete a user-defined rule:
Expected response:
Validation¶
After creating, updating, ranking, or deleting a rule:
- Run the Get Existing Request Header Rules query again.
- Confirm the rule appears with the expected
retentionAction,predicate,scope, andexpiration. - Confirm rule order is correct if ranking was changed.
- Verify the custom headers are retained in downstream span data.
Troubleshooting¶
GraphQL Mutation Fails¶
Symptoms: The GraphQL response contains an error and the rule is not created or updated.
Solutions:
- Verify
retentionActionis set toRETAIN. - Verify the operator is one of
EQUALS,STARTS_WITH,ENDS_WITH, orCONTAINS. - Ensure only one of
valueoranyOfValuesis set. - Confirm
expirationuses a valid timestamp format, such as2026-12-31T23:59:59.000Z.
Header Is Not Retained¶
Symptoms: The custom request header is not available in downstream span data.
Solutions:
- Check whether a higher-ranked rule matches before this rule.
- Confirm the rule is configured under
requestHeaderRules. - Verify
scope.environmentIdsincludes the relevant environment, or remove the scope to apply the rule globally. - Check whether the rule has expired.
Cannot Update or Delete a Rule¶
Symptoms: Update, delete, or rank operations fail for a rule.
Solutions:
- Confirm the rule ID is correct.
- Verify the rule is user-defined. Default rules cannot be updated, deleted, or ranked.
- Run the list query again to confirm the rule still exists.
Security Considerations¶
- Avoid retaining sensitive headers unless there is a clear operational need.
- Do not retain authentication tokens, cookies, secrets, or personally identifiable information unless approved by your security team.
- Scope rules to specific environments when testing changes.
- Review retained request headers periodically.
Support¶
For assistance with retaining custom headers, contact: support@harness.io