Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions javascript/sentry-conventions/src/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16115,6 +16115,39 @@ export interface ChangelogEntry {
description?: string;
}

export type AttributeSearchType =
| 'string'
| 'boolean'
| 'integer'
| 'number'
| 'byte'
| 'currency'
| 'millisecond'
| 'percentage'
| 'second';

export interface AttributeSearchDatasetMappings {
/** The column expression in the indexed spans dataset */
spans?: string;
/** The column expression in the Events Analytics Platform dataset */
eap?: string;
}

export interface AttributeSearchAlias {
/** The public name exposed in Sentry search */
publicAlias: string;
/** The internal attribute name used by the EAP search resolver */
internalName: string;
/** The type exposed by Sentry search, including unit-aware types */
searchType: AttributeSearchType;
/** Exact query column mappings for Sentry span datasets */
datasetMappings: AttributeSearchDatasetMappings;
/** Whether the alias is accepted for queries but omitted from autocomplete suggestions */
secondaryAlias?: boolean;
/** Whether the internal attribute should be hidden from public search results */
private?: boolean;
}

export interface AttributeMetadata {
/** A description of the attribute */
brief: string;
Expand All @@ -16138,6 +16171,8 @@ export interface AttributeMetadata {
changelog?: ChangelogEntry[];
/** A list of freeform notes providing additional context about how this attribute behaves, common pitfalls, or query-time nuances */
additionalContext?: string[];
/** Public search aliases and their mappings to Sentry span datasets */
searchAliases?: AttributeSearchAlias[];
}

export const ATTRIBUTE_TYPE: Record<string, AttributeType> = {
Expand Down Expand Up @@ -25691,6 +25726,17 @@ export const ATTRIBUTE_METADATA: Record<AttributeName, AttributeMetadata> = {
visibility: 'public',
example: 'http.client',
changelog: [{ version: '0.0.0' }],
searchAliases: [
{
publicAlias: 'span.op',
internalName: 'sentry.op',
searchType: 'string',
datasetMappings: {
spans: 'op',
eap: 'attr_str[sentry.op]',
},
},
],
},
'sentry.origin': {
brief: 'The origin of the instrumentation (e.g. span, log, etc.)',
Expand Down
11 changes: 11 additions & 0 deletions model/attributes/sentry/sentry__op.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@
"is_in_otel": false,
"example": "http.client",
"visibility": "public",
"search_aliases": [
{
"public_alias": "span.op",
"internal_name": "sentry.op",
"search_type": "string",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can likely make string the default, so not required.

"dataset_mappings": {
"spans": "op",
"eap": "attr_str[sentry.op]"
}
}
],
"changelog": [
{
"version": "0.0.0"
Expand Down
61 changes: 61 additions & 0 deletions python/src/sentry_conventions/attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ class Visibility(Enum):
INTERNAL = "internal"


AttributeSearchType = Literal[
"string",
"boolean",
"integer",
"number",
"byte",
"currency",
"millisecond",
"percentage",
"second",
]


@dataclass
class ApplyScrubbingInfo:
"""Holds information about how PII scrubbing should be applied to an attribute's values."""
Expand Down Expand Up @@ -71,6 +84,40 @@ class ChangelogEntry:
"""Optional description of what changed"""


@dataclass
class AttributeSearchDatasetMappings:
"""Query column mappings for Sentry span datasets."""

spans: Optional[str] = None
"""The column expression in the indexed spans dataset"""

eap: Optional[str] = None
"""The column expression in the Events Analytics Platform dataset"""


@dataclass
class AttributeSearchAlias:
"""A public search alias for an attribute."""

public_alias: str
"""The public name exposed in Sentry search"""

internal_name: str
"""The internal attribute name used by the EAP search resolver"""

search_type: AttributeSearchType
"""The type exposed by Sentry search, including unit-aware types"""

dataset_mappings: AttributeSearchDatasetMappings
"""Exact query column mappings for Sentry span datasets"""

secondary_alias: bool = False
"""Whether the alias is omitted from autocomplete suggestions"""

private: bool = False
"""Whether the internal attribute is hidden from public search results"""


@dataclass
class AttributeMetadata:
"""The metadata for an attribute."""
Expand Down Expand Up @@ -108,6 +155,9 @@ class AttributeMetadata:
additional_context: Optional[List[str]] = None
"""A list of freeform notes providing additional context about how this attribute behaves, common pitfalls, or query-time nuances"""

search_aliases: Optional[List[AttributeSearchAlias]] = None
"""Public search aliases and their mappings to Sentry span datasets"""


class _AttributeNamesMeta(type):
_deprecated_names = {
Expand Down Expand Up @@ -18002,6 +18052,17 @@ class ATTRIBUTE_NAMES(metaclass=_AttributeNamesMeta):
changelog=[
ChangelogEntry(version="0.0.0"),
],
search_aliases=[
AttributeSearchAlias(
public_alias="span.op",
internal_name="sentry.op",
search_type="string",
dataset_mappings=AttributeSearchDatasetMappings(
spans="op",
eap="attr_str[sentry.op]",
),
),
],
),
"sentry.origin": AttributeMetadata(
brief="The origin of the instrumentation (e.g. span, log, etc.)",
Expand Down
15 changes: 15 additions & 0 deletions python/tests/test_smoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import pytest

from sentry_conventions.attributes import (
ATTRIBUTE_METADATA,
ATTRIBUTE_NAMES,
Attributes,
)
Expand Down Expand Up @@ -40,3 +41,17 @@ def test_full_attributes_typeddict() -> None:

tokens_used = attributes.get(ATTRIBUTE_NAMES.AI_COMPLETION_TOKENS_USED)
assert tokens_used == 10


def test_attribute_search_alias_metadata() -> None:
aliases = ATTRIBUTE_METADATA[ATTRIBUTE_NAMES.SENTRY_OP].search_aliases

assert aliases is not None
assert len(aliases) == 1

alias = aliases[0]
assert alias.public_alias == "span.op"
assert alias.internal_name == "sentry.op"
assert alias.search_type == "string"
assert alias.dataset_mappings.spans == "op"
assert alias.dataset_mappings.eap == "attr_str[sentry.op]"
57 changes: 57 additions & 0 deletions schemas/attribute.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,63 @@
"type": "string"
}
},
"search_aliases": {
"description": "Public search aliases and their mappings to Sentry span datasets",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"public_alias": {
"description": "The public name exposed in Sentry search",
"type": "string"
},
"internal_name": {
"description": "The internal attribute name used by the EAP search resolver",
"type": "string"
},
Comment on lines +113 to +116

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this always duplicate the attribute's key? It feels like it ought to, in which case I'd prefer we make mismatches impossible by removing this property.

"search_type": {
"description": "The type exposed by Sentry search, including unit-aware types",
"enum": [
"string",
"boolean",
"integer",
"number",
"byte",
"currency",
"millisecond",
"percentage",
"second"
]
},
"secondary_alias": {
"description": "Whether the alias is accepted for queries but omitted from autocomplete suggestions",
"type": "boolean"
},
"private": {
"description": "Whether the internal attribute should be hidden from public search results",
"type": "boolean"
},
Comment on lines +135 to +138

@mjq mjq Jul 13, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this already covered by visibility? cc @nsdeschenes

"dataset_mappings": {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the two other two comments re: spans and eap I think the whole dataset_mappings can be removed.

"description": "Exact query column mappings for Sentry's span datasets",
"type": "object",
"additionalProperties": false,
"minProperties": 1,
"properties": {
"spans": {
"description": "The column expression in the indexed spans dataset",
"type": "string"
},
Comment on lines +145 to +148

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dataset has been removed. Only EAP exists now.

"eap": {
"description": "The column expression in the Events Analytics Platform dataset",
"type": "string"
}
Comment on lines +149 to +152

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems better left to the Sentry backend to compute. (What's sent to EAP isn't a string either, so I don't think this is helpful here anyway). We do need a way to record when the search types and internal types of an attribute mismatch, though. I'd rather expose an (optional) internal_type property for this (one of string, boolean, double, integer, or array) so that the backend can construct the correct RPC proto.

}
}
},
"required": ["public_alias", "internal_name", "search_type", "dataset_mappings"]
}
},
"additional_context": {
"description": "A list of freeform notes providing additional context about how this attribute behaves, common pitfalls, or query-time nuances",
"type": "array",
Expand Down
Loading
Loading