Skip to content
Merged
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
84 changes: 84 additions & 0 deletions javascript/sentry-conventions/src/attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2120,6 +2120,11 @@ export type BROWSER_WEB_VITAL_CLS_REPORT_EVENT_TYPE = string;
*/
export const BROWSER_WEB_VITAL_CLS_SOURCE_KEY = 'browser.web_vital.cls.source.<key>';

/**
* Base key for {@link BROWSER_WEB_VITAL_CLS_SOURCE_KEY}. Use with a dynamic suffix, e.g. `${BROWSER_WEB_VITAL_CLS_SOURCE_KEY_BASE}.${key}`.
*/
export const BROWSER_WEB_VITAL_CLS_SOURCE_KEY_BASE = 'browser.web_vital.cls.source';

/**
* Type for {@link BROWSER_WEB_VITAL_CLS_SOURCE_KEY} browser.web_vital.cls.source.<key>
*/
Expand Down Expand Up @@ -3190,6 +3195,13 @@ export type CLS_TYPE = number;
*/
export const CLS_SOURCE_KEY = 'cls.source.<key>';

/**
* Base key for {@link CLS_SOURCE_KEY}. Use with a dynamic suffix, e.g. `${CLS_SOURCE_KEY_BASE}.${key}`.
*
* @deprecated Use {@link BROWSER_WEB_VITAL_CLS_SOURCE_KEY_BASE} (browser.web_vital.cls.source) instead - The CLS source is now recorded as a browser.web_vital.cls.source.<key> attribute.
*/
export const CLS_SOURCE_KEY_BASE = 'cls.source';

/**
* Type for {@link CLS_SOURCE_KEY} cls.source.<key>
*/
Expand Down Expand Up @@ -3684,6 +3696,11 @@ export type DB_OPERATION_NAME_TYPE = string;
*/
export const DB_QUERY_PARAMETER_KEY = 'db.query.parameter.<key>';

/**
* Base key for {@link DB_QUERY_PARAMETER_KEY}. Use with a dynamic suffix, e.g. `${DB_QUERY_PARAMETER_KEY_BASE}.${key}`.
*/
export const DB_QUERY_PARAMETER_KEY_BASE = 'db.query.parameter';

/**
* Type for {@link DB_QUERY_PARAMETER_KEY} db.query.parameter.<key>
*/
Expand Down Expand Up @@ -5282,6 +5299,11 @@ export type FCP_TYPE = number;
*/
export const FLAG_EVALUATION_KEY = 'flag.evaluation.<key>';

/**
* Base key for {@link FLAG_EVALUATION_KEY}. Use with a dynamic suffix, e.g. `${FLAG_EVALUATION_KEY_BASE}.${key}`.
*/
export const FLAG_EVALUATION_KEY_BASE = 'flag.evaluation';

/**
* Type for {@link FLAG_EVALUATION_KEY} flag.evaluation.<key>
*/
Expand Down Expand Up @@ -7481,6 +7503,11 @@ export type HTTP_REQUEST_FETCH_START_TYPE = number;
*/
export const HTTP_REQUEST_HEADER_KEY = 'http.request.header.<key>';

/**
* Base key for {@link HTTP_REQUEST_HEADER_KEY}. Use with a dynamic suffix, e.g. `${HTTP_REQUEST_HEADER_KEY_BASE}.${key}`.
*/
export const HTTP_REQUEST_HEADER_KEY_BASE = 'http.request.header';

/**
* Type for {@link HTTP_REQUEST_HEADER_KEY} http.request.header.<key>
*/
Expand Down Expand Up @@ -7833,6 +7860,11 @@ export type HTTP_RESPONSE_HEADER_CONTENT_LENGTH_TYPE = string;
*/
export const HTTP_RESPONSE_HEADER_KEY = 'http.response.header.<key>';

/**
* Base key for {@link HTTP_RESPONSE_HEADER_KEY}. Use with a dynamic suffix, e.g. `${HTTP_RESPONSE_HEADER_KEY_BASE}.${key}`.
*/
export const HTTP_RESPONSE_HEADER_KEY_BASE = 'http.response.header';

/**
* Type for {@link HTTP_RESPONSE_HEADER_KEY} http.response.header.<key>
*/
Expand Down Expand Up @@ -9002,6 +9034,11 @@ export type MCP_PROTOCOL_VERSION_TYPE = string;
*/
export const MCP_REQUEST_ARGUMENT_KEY = 'mcp.request.argument.<key>';

/**
* Base key for {@link MCP_REQUEST_ARGUMENT_KEY}. Use with a dynamic suffix, e.g. `${MCP_REQUEST_ARGUMENT_KEY_BASE}.${key}`.
*/
export const MCP_REQUEST_ARGUMENT_KEY_BASE = 'mcp.request.argument';

/**
* Type for {@link MCP_REQUEST_ARGUMENT_KEY} mcp.request.argument.<key>
*/
Expand Down Expand Up @@ -9335,6 +9372,11 @@ export type MCP_TRANSPORT_TYPE = string;
*/
export const MDC_KEY = 'mdc.<key>';

/**
* Base key for {@link MDC_KEY}. Use with a dynamic suffix, e.g. `${MDC_KEY_BASE}.${key}`.
*/
export const MDC_KEY_BASE = 'mdc';

/**
* Type for {@link MDC_KEY} mdc.<key>
*/
Expand Down Expand Up @@ -10726,6 +10768,11 @@ export type OTEL_STATUS_DESCRIPTION_TYPE = string;
*/
export const PARAMS_KEY = 'params.<key>';

/**
* Base key for {@link PARAMS_KEY}. Use with a dynamic suffix, e.g. `${PARAMS_KEY_BASE}.${key}`.
*/
export const PARAMS_KEY_BASE = 'params';

/**
* Type for {@link PARAMS_KEY} params.<key>
*/
Expand Down Expand Up @@ -10993,6 +11040,13 @@ export type PROCESS_RUNTIME_VERSION_TYPE = string;
*/
export const QUERY_KEY = 'query.<key>';

/**
* Base key for {@link QUERY_KEY}. Use with a dynamic suffix, e.g. `${QUERY_KEY_BASE}.${key}`.
*
* @deprecated Use {@link URL_QUERY} (url.query) instead - Instead of sending items individually in query.<key>, they should be sent all together with url.query.
*/
export const QUERY_KEY_BASE = 'query';

/**
* Type for {@link QUERY_KEY} query.<key>
*/
Expand Down Expand Up @@ -11061,6 +11115,11 @@ export type RELEASE_TYPE = string;
*/
export const REMIX_ACTION_FORM_DATA_KEY = 'remix.action_form_data.<key>';

/**
* Base key for {@link REMIX_ACTION_FORM_DATA_KEY}. Use with a dynamic suffix, e.g. `${REMIX_ACTION_FORM_DATA_KEY_BASE}.${key}`.
*/
export const REMIX_ACTION_FORM_DATA_KEY_BASE = 'remix.action_form_data';

/**
* Type for {@link REMIX_ACTION_FORM_DATA_KEY} remix.action_form_data.<key>
*/
Expand Down Expand Up @@ -11375,6 +11434,11 @@ export type RUNTIME_VERSION_TYPE = string;
*/
export const SCORE_KEY = 'score.<key>';

/**
* Base key for {@link SCORE_KEY}. Use with a dynamic suffix, e.g. `${SCORE_KEY_BASE}.${key}`.
*/
export const SCORE_KEY_BASE = 'score';

/**
* Type for {@link SCORE_KEY} score.<key>
*/
Expand All @@ -11398,6 +11462,11 @@ export type SCORE_KEY_TYPE = number;
*/
export const SCORE_RATIO_KEY = 'score.ratio.<key>';

/**
* Base key for {@link SCORE_RATIO_KEY}. Use with a dynamic suffix, e.g. `${SCORE_RATIO_KEY_BASE}.${key}`.
*/
export const SCORE_RATIO_KEY_BASE = 'score.ratio';

/**
* Type for {@link SCORE_RATIO_KEY} score.ratio.<key>
*/
Expand Down Expand Up @@ -11440,6 +11509,11 @@ export type SCORE_TOTAL_TYPE = number;
*/
export const SCORE_WEIGHT_KEY = 'score.weight.<key>';

/**
* Base key for {@link SCORE_WEIGHT_KEY}. Use with a dynamic suffix, e.g. `${SCORE_WEIGHT_KEY_BASE}.${key}`.
*/
export const SCORE_WEIGHT_KEY_BASE = 'score.weight';

/**
* Type for {@link SCORE_WEIGHT_KEY} score.weight.<key>
*/
Expand Down Expand Up @@ -12101,6 +12175,11 @@ export type SENTRY_MOBILE_TYPE = boolean;
*/
export const SENTRY_MODULE_KEY = 'sentry.module.<key>';

/**
* Base key for {@link SENTRY_MODULE_KEY}. Use with a dynamic suffix, e.g. `${SENTRY_MODULE_KEY_BASE}.${key}`.
*/
export const SENTRY_MODULE_KEY_BASE = 'sentry.module';

/**
* Type for {@link SENTRY_MODULE_KEY} sentry.module.<key>
*/
Expand Down Expand Up @@ -13797,6 +13876,11 @@ export type URL_PATH_TYPE = string;
*/
export const URL_PATH_PARAMETER_KEY = 'url.path.parameter.<key>';

/**
* Base key for {@link URL_PATH_PARAMETER_KEY}. Use with a dynamic suffix, e.g. `${URL_PATH_PARAMETER_KEY_BASE}.${key}`.
*/
export const URL_PATH_PARAMETER_KEY_BASE = 'url.path.parameter';

/**
* Type for {@link URL_PATH_PARAMETER_KEY} url.path.parameter.<key>
*/
Expand Down
46 changes: 40 additions & 6 deletions scripts/generate_attributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
let individualConstants = '';

// Generate individual attribute constants with documentation AND build the explicit type map
for (const { file, key, constantName, attributeJson, isDeprecated } of allAttributes) {

Check warning on line 113 in scripts/generate_attributes.ts

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

eslint(no-unused-vars)

Variable 'isDeprecated' is declared but never used. Unused variables should start with a '_'.

Check warning on line 113 in scripts/generate_attributes.ts

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

eslint(no-unused-vars)

Variable 'isDeprecated' is declared but never used. Unused variables should start with a '_'.
const { brief, type, apply_scrubbing, is_in_otel, example, has_dynamic_suffix, deprecation, alias } = attributeJson;
const visibility = getVisibility(attributeJson);

Expand Down Expand Up @@ -156,12 +156,7 @@

// Deprecation
if (deprecation) {
individualConstants += ' *\n';
let replacement = '';
if (deprecation.replacement) {
replacement = `Use {@link ${getConstantName(deprecation.replacement, false)}} (${deprecation.replacement}) instead`;
}
individualConstants += ` * @deprecated ${replacement}${deprecation.reason ? ` - ${deprecation.reason}` : ''}\n`;
individualConstants += formatDeprecationJsdoc(deprecation, allAttributes, false);
}

// Example
Expand All @@ -175,6 +170,18 @@
individualConstants += ' */\n';
individualConstants += `export const ${constantName} = '${key}';\n\n`;

if (has_dynamic_suffix) {
const keyBase = getDynamicSuffixBase(key);
const constantNameBase = `${constantName}_BASE`;
individualConstants += '/**\n';
individualConstants += ` * Base key for {@link ${constantName}}. Use with a dynamic suffix, e.g. \`\${${constantNameBase}}.\${key}\`.\n`;
if (deprecation) {
individualConstants += formatDeprecationJsdoc(deprecation, allAttributes, true);
}
individualConstants += ' */\n';
individualConstants += `export const ${constantNameBase} = '${keyBase}';\n\n`;
}

// Generate type constant
individualConstants += '/**\n';
individualConstants += ` * Type for {@link ${constantName}} ${key}\n`;
Expand Down Expand Up @@ -208,6 +215,33 @@
const constantNameInnerMemo = new Map<string, string>();
const usedConstantNames = new Set<string>();

function getDynamicSuffixBase(key: string): string {
const suffix = '.<key>';
if (!key.endsWith(suffix)) {
throw new Error(`Expected dynamic suffix attribute key to end with "${suffix}", got "${key}"`);
}
return key.slice(0, -suffix.length);
}

function formatDeprecationJsdoc(
deprecation: NonNullable<AttributeJson['deprecation']>,
allAttributes: Array<{ key: string; attributeJson: AttributeJson }>,
isBase: boolean,
): string {
let replacement = '';
if (deprecation.replacement) {
const replacementAttr = allAttributes.find((attr) => attr.key === deprecation.replacement);
const replacementConstantName = getConstantName(deprecation.replacement, false);
const replacementHasDynamicSuffix = !!replacementAttr?.attributeJson.has_dynamic_suffix;
const replacementLink =
isBase && replacementHasDynamicSuffix ? `${replacementConstantName}_BASE` : replacementConstantName;
const replacementDisplay =
isBase && replacementHasDynamicSuffix ? getDynamicSuffixBase(deprecation.replacement) : deprecation.replacement;
replacement = `Use {@link ${replacementLink}} (${replacementDisplay}) instead`;
}
return ` *\n * @deprecated ${replacement}${deprecation.reason ? ` - ${deprecation.reason}` : ''}\n`;
}

// Computes a constant name for an attribute without regard for deprecation status.
function getConstantNameInner(key: string): string {
if (constantNameInnerMemo.has(key)) {
Expand Down
Loading