diff --git a/scripts/translations/.translation_state.json b/scripts/translations/.translation_state.json index 852d97b1d0..9e528430ed 100644 --- a/scripts/translations/.translation_state.json +++ b/scripts/translations/.translation_state.json @@ -1184,6 +1184,8 @@ "select_only_two": "5085a33d498742f4", "select_two": "7761b6516e1ec2c8" }, + "costAtLeast": "817fa98cd15714a5", + "costUnknown": "d05144e2f67105ef", "create": "4759498ac2a719c6", "createError": "64f9e995370afc25", "createSuccess": "ab1d1b5741d5c2df", @@ -1195,6 +1197,7 @@ "by": "ae2134ba7e6456d5", "columns": { "dispersion": "752831e1cce1dc39", + "error": "54a0e8c17ebb21a1", "input": "36ecb4f8669133ce", "latency": "e0e7d293043c8cf6", "output": "b2439bcb8dee14b6", @@ -1216,6 +1219,24 @@ }, "costBreakdown": "49e18434853d9944", "datasetVersion": "7126d5d7ea42c517", + "failureBanner": { + "cause": "b72c30d5e0d85795", + "moreCauses": "9c946e2f07c43859", + "noMessage": "4fd9ba9822fae31a", + "openProviders": "3cb5a8c0534b6274", + "title": "87644ee8185a3f26" + }, + "failureKinds": { + "execution_error": "c1a629c0151dd33f", + "mapping_error": "9d3297a7ff61cca1", + "parse_error": "329c253b42598245", + "provider_5xx": "a87bbaf989452598", + "provider_auth": "40b272121c9a17c9", + "rate_limited": "1e11b846d9a91ce1", + "scorer_missing": "95cfae6d15eca2e8", + "timeout": "e35155bc1aa15123", + "unknown": "c1a629c0151dd33f" + }, "highDispersion": "0beb185ae4bd7009", "highDispersionBadge": "c4ebc6d4a5832cd9", "highDispersionHint": "82b84276c5c1c946", @@ -1280,6 +1301,7 @@ "descriptionPlaceholder": "dc1e7db58b2d8e76", "expectedOutputScorersOnly": "a758ba9ab3e54c96", "identitySection": "999f23fcd7bec707", + "judgeProviderFailed": "4d7a3a8c23b33790", "managedPromptLabel": "39f780053bf3874c", "managedPromptPlaceholder": "1e841b12d6e50a5c", "modelHelp": "0017404e73bb5f67", @@ -1338,6 +1360,7 @@ "tabTask": "4bc74b21357c6cf5", "taskConcurrencyLabel": "f5d40eea8e3ff761", "taskOverrideHelp": "3ff10923500ee249", + "taskProviderFailed": "42a3f56235268fe2", "taskTimeoutLabel": "1f966032d11151c8", "taskTypeInline": "2abdd5ee9b043082", "taskTypeInlineHelp": "de18d05478a65bd9", @@ -2348,7 +2371,11 @@ }, "scope": { "agent": "11b39c93777e8f1f", + "agentIdHint": "577c9d7ca5c4f39d", "env": "494d9aa0c0684432", + "noAgentIdentity": "4045f5a7d8e05d63", + "noAgentIdentityAction": "153a2dd7ec485532", + "noAgentIdentityDescription": "f3f70a28febe536c", "version": "dd167905de0defca" }, "sections": { @@ -5084,6 +5111,7 @@ "subtitle": "5fcb81394285a5a9", "systemUser": "6725e7bbcd28f3a8", "timeline": { + "ackEndedByPageResolve": "36cb1acf13c91edb", "aiFinished": "2ba863b687e16de2", "aiStarted": "707d9a19d37cdeea", "alertTriggered": "9eb862ab087e4afa", @@ -5093,6 +5121,7 @@ "analysisNeedsInputNoNeed": "d86e2fe3d7e84cf7", "assignedTo": "d6569993158f9c9c", "assignmentRemoved": "65635b6dfe0a289f", + "badgeAckEnded": "e5e6936ea3700ef6", "badgeAcknowledged": "d87cdf8aa30447b1", "badgeAiAnalysis": "c8438a13b9dd6620", "badgeAiCancelled": "1fb4d48b5386d8cd", @@ -5415,6 +5444,13 @@ "rumfunnel": { "label": "4c75600fe5d78bc8", "toast": "64d93a2540ca331b" + }, + "traces": { + "errorCount": "a6c450f7752c3b1f", + "errorRate": "33a224722fc7b1e4", + "label": "a7aa98743fde8426", + "noStream": "89cf2ea082e012d3", + "toast": "57572c39a306fa6d" } }, "warnings": { @@ -5447,6 +5483,20 @@ "textFilterDropped": "1af3560e95f9e483", "thresholdColumnGuessed": "4595598009f195f5", "thresholdNotCarried": "386d5f1dc39548e0", + "tracesErrorRatioMinSpans": "2b5eb9d30ce5f182", + "tracesErrorRatioMinTraces": "0a48e91a68610396", + "tracesNoMatches": "a3a883fe8d51faaa", + "tracesNotRun": "153a5867ff5b6841", + "tracesPeriodCapped": "d85febb31cf3f13d", + "tracesSeedDuration": "86a5310dd9829c69", + "tracesSeedErrorRatio": "6482c9b0e280236f", + "tracesSeedErrorSpans": "b7223652d982387b", + "tracesSeedErrorTraces": "6b6a2da0f49cbf2a", + "tracesSeedMatches": "6d5f6bf70a261bfe", + "tracesSeedSpans": "b0c7da48cb7e6be0", + "tracesSeedTraces": "65efc9318192f33e", + "tracesSeedUnavailable": "0eeb0bb9b1a96b48", + "tracesStoredSpans": "76b5019e760436d4", "unresolvedQuery": "4cd999a9b4222ad7", "unsupportedPanelType": "1f9928c4b86b85bb" } @@ -9355,6 +9405,15 @@ "queryFields": "bedff62661a6f43b", "titleRequired": "7c15e7448e6f4d1c" }, + "date": "99c40ab405926cb5", + "dateFormat": "16b1ff0fd29e0b60", + "dateFormatDmy": "0c6ff1231a8aa208", + "dateFormatEpoch": "53660b5bc2209228", + "dateFormatEpochms": "5389bb9f6f36e8ac", + "dateFormatEpochus": "9044784c02e163ff", + "dateFormatHelp": "9a3857e3a591b7c7", + "dateFormatIso": "bd203cdfbc050d8f", + "dateFormatMdy": "497319b9a2f9bdb6", "days": "e08c0aa8f558f39f", "decimals": "74672912045e226a", "decimalsMustBeBetween": "7fea01108f16d056", @@ -9960,6 +10019,8 @@ "addAnnotations": "cef84932bd0f98d2", "dependentAdhocVariableWarning": "a49d6008392505a5", "exitAnnotationsMode": "f7926a15fd7336d3", + "exploreAddToDashboard": "81c5e9c7bb53cc85", + "exploreCreateAlert": "a7aa98743fde8426", "pleaseWait": "2dfd888fdd5e8018", "redirectingToLogs": "11687f03a8f7d474", "refreshCacheReload": "2ac4f8a9601ba6c7", @@ -11387,6 +11448,7 @@ "lineCountedToBehind": "fda756c37a0ee644", "lineExact": "22fc00c3268448a7", "lineExactEstimated": "3abdcfd5183d925a", + "lineExactSlowestSchema": "ef3365493b226924", "lineGap": "71db3c726692dd2f", "lineHealthy": "ad6f89d68992ae3f", "lineHealthyAll": "9724ad1e593159ca", @@ -11439,6 +11501,7 @@ "failedChip": "cd8f5051cba3686a", "moreServices": "ecadd87ff0e5d0aa", "openQueries": "1cc7003257a55ac4", + "schemaCount": "af8b06d8319b5766", "searchPlaceholder": "5b5e4ae9bc9f4827", "summary": { "calls": "b73a5e2ca6458665", @@ -12597,9 +12660,14 @@ "title": "275814da8d3d0fc0" }, "noLLMInsights": { - "action": "bbefb1e0d359b886", - "actionDesc": "10143ef7e46421e8", + "action": "077f797f300db0bd", + "actionDesc": "500ad6f2550cb2fe", + "codingAgent": "a0187dc59f83a81b", + "codingAgentDesc": "a9f892db0b444d97", "description": "19ec2da72c6b2477", + "startFrom": "5f3285e4fbdb83f5", + "suggested": "7b89ba0bd02cea17", + "suggestedDesc": "450da62ec7cef9f1", "title": "c390a136b67c5c2a" }, "noLLMSessions": { @@ -12995,7 +13063,6 @@ "addCollector": "6d30a69cb01ed55a", "audit": { "allObjects": "77b8112ecb4eb493", - "assignedFleetConfig": "f2edb905b6ae3905", "autoRollback": "759dfb52f2d180e8", "createdConfig": "4f7f1ee2671cb679", "createdFleet": "b68cda33862cfd6c", @@ -13039,7 +13106,8 @@ "progressive": "c21bea0c6d590524", "rolledBack": "71592236d852c8a3", "scheduled": "4724f344c1c0e4a1", - "superseded": "e5830d265452f1ed" + "superseded": "e5830d265452f1ed", + "waiting": "6e293a8c009e0011" }, "collectorMetrics": { "chartFailures": "216322e91817a15f", @@ -13401,6 +13469,7 @@ "receiverRefused": "edcf8cddc0293bee", "rollingOut": "1034b2f3c8519a6e", "rolloutHalted": "8a2afc80498adcd1", + "rolloutWaiting": "4eb9605c57a8efaf", "throughput": "286c8abb332b94d1", "viewCollectors": "09362e686190000d" }, @@ -13468,7 +13537,7 @@ "confirmRollbackNoStable": "76cba5181ffc44a2", "confirmSkip": "fbf2627372d3e0cc", "confirmed": "fe00b67b6dd1143f", - "emptyFleet": "c83174a9b6a438d5", + "emptyFleet": "40e87c8e8e200c76", "eventConverged": "496a7f78a878cf75", "eventDeployingAll": "bc466962bfa87a7e", "eventDeployingPhase": "48b3a2550d7da3be", @@ -13483,6 +13552,7 @@ "eventStarted": "ecbc89cd37a03734", "eventSuperseded": "52ef7e19237d3ce6", "eventTimedOut": "c47d17f78f06c3c5", + "eventWaiting": "e4264c0e69310006", "excluded": "bef1fd9e5caea8b5", "exitDone": "e1094f3cf7f677e3", "exitFixForward": "470104b45177a3ae", @@ -13507,11 +13577,13 @@ "noneTargeted": "ff39f3ad54f4fc2d", "notFound": "860e2a125f52a2c9", "notFoundDescription": "86178a756a81856d", + "notStarted": "ba35f0c47d862763", "oneBatch": "c19b328d9c33d82c", "outcomeCompleted": "ecbca3631908722a", - "outcomeNoneTargeted": "46fc62713b771684", + "outcomeNoneTargeted": "962415e5e360c27e", "outcomeRolledBack": "b87a2b40dc59b1f9", "outcomeSuperseded": "2b19b3756928b29e", + "outcomeWaiting": "33b4615fa201ed60", "phase": "46342ec1eec9d78d", "phaseConverging": "5d83a1cdbc3ece78", "phaseDeploying": "4338bdb0808bff1b", @@ -13528,8 +13600,9 @@ "pickConfig": "90ea303d63b6e1b9", "pickFleet": "198dc9fab289dce0", "pickVersion": "63615c1367bcaffc", - "planEmpty": "e2d85223a4128d4a", + "planEmpty": "abc88f694f3d0380", "planOne": "a383f777ba3f4045", + "planStable": "5ce689ffe91deeb2", "planText": "1f056a0132545164", "planUnavailable": "59be1a0417cc69d6", "progress": "4664827f8e890192", @@ -13561,7 +13634,8 @@ "version": "dd167905de0defca", "versionChange": "d3f8f2614d634511", "versionFailedBefore": "9239d93df9ca801f", - "versionTo": "9dfbfacb677a4b76" + "versionTo": "9dfbfacb677a4b76", + "waitingForCollector": "6ade5abc8ce0ffc9" }, "settings": { "action": "64cff1319d2fd2cb", @@ -15155,6 +15229,18 @@ "adminRegion": "0ffda4cfc0650beb", "aerospike": "ce7999e71cdee64f", "ai": { + "codingAgent": { + "envButton": "8594d2ee749572c4", + "envHelp": "a674c8b69df5e79c", + "envTitle": "08d3da57e11a658c", + "promptCopied": "c55394776b1492cf", + "promptLabel": "5c39123805ffb4e2", + "promptTitle": "c36d206528dfdcd8", + "streamHelp": "83f9edcc4f1358f3", + "streamLabel": "cdb84491f9d46fdd", + "tabAgent": "790f1f1068bb1941", + "tabSteps": "e8d00a9b9ef410c6" + }, "selectIntegrationPrompt": "a0ce42f3b966249c", "viewDocsLinkLabel": "fcec91509759ad99", "viewDocsPrefix": "95ba4ed9329f4a25", @@ -16350,6 +16436,78 @@ "tabLabel": "4fc52a3c4c558b51", "title": "2a932f90172e99ea" }, + "llmDataTrust": { + "chart": { + "addPrice": "a569afba541a4546", + "costMissing": "15719aeadc9a4433", + "costMissingPricedSince": "ccbcc443db252b66", + "pricedSinceModels": "4b41efe0a1b586bf", + "unpricedModels": "9d02ff6116a21199" + }, + "cost": { + "addPrice": "a569afba541a4546", + "atLeast": "817fa98cd15714a5", + "partial": "9834a14ab9bcaa0f", + "partialTooltip": "7eb940bd52a38991", + "scopeSession": "3f3af1ecebbd1410", + "scopeTrace": "eafe895eb8119e6e", + "unknown": "d05144e2f67105ef", + "unknownModel": "b38aca5bdef50e36", + "unknownTooltip": "37d532fec09f7454" + }, + "health": { + "checkedAgo": "a969a64149949bb1", + "checks": { + "missing_agent_identity": { + "detail": "56be6f448f66fc25", + "fix": "153a2dd7ec485532", + "label": "534909c4fe3161d5", + "pass": "f7ac036ebd3d13c4" + }, + "missing_session_id": { + "detail": "71a7176e6a2d8e37", + "fix": "02a0a9e2c23ddca5", + "label": "7a2ac980813d4490", + "pass": "0e6992464dd45463" + }, + "unpriced_models": { + "detail": "720a8d0a56bda95a", + "fix": "a458f3394499824e", + "label": "09fe601e257b445a", + "pass": "6c7db283854bf953", + "truncated": "6803449513cad9e7" + }, + "zero_duration_spans": { + "detail": "fc8b55118ef803ef", + "fix": "a039dd154df91827", + "label": "08016c2977c1d921", + "pass": "e5fd7080ffeafe48" + } + }, + "close": "7d9eb7acb13e2462", + "copyLink": "4d3369b8d181aa30", + "drawerSubtitle": "a540f007210cda31", + "drawerTitle": "f918ce9614900771", + "linkCopied": "d12860c21e78baa5", + "loadError": "112e1f96291d4d42", + "passing": "e32467f0609830f4", + "rerun": "9df526d3b6303b71", + "samples": "9d7b125807dd8026", + "status": { + "error": "54a0e8c17ebb21a1", + "pass": "83e6fbaec303ef43", + "warning": "e981ddae45d8f4ca" + }, + "title": "6e5625b8c13013a0" + }, + "noModelName": "6e2cf4b2b853869d", + "tile": { + "pricedSinceTooltip": "057c2112c955e970", + "unpricedTokens": "12d5d476475b2caa", + "unpricedTooltip": "20b54d2be1ea235f" + }, + "topModels": "49c7abc42e15a381" + }, "llmProviders": { "columns": { "defaultModel": "8b4e8774ddf69ec7", @@ -16944,6 +17102,7 @@ "errorAddingPanel": "6f1badcb000b2865", "panelAdded": "5f65a956a6f6ad9c", "panelsAdded": "95b99ef8ae8d477d", + "panelsToAdd": "d4b7e809147d7eca", "selectDashboard": "f82c269f36cec57f", "selectTab": "096913133b1c0d72" }, @@ -17203,6 +17362,8 @@ "noMatch": "8fd65271addeef96", "noMatchHint": "f7270f66f0f6e1ad", "noMatchHintFavorites": "7d314816dbd9af58", + "noMatchYet": "4f985b77f0ddbf74", + "noMatchYetHint": "a58d01523b497cbc", "noMetrics": "9c1aac7f7110a396", "queryFailed": "222d8657e6ce5036", "railsAriaLabel": "e1fceb2e0a1984cf", @@ -17407,6 +17568,11 @@ "attributeRules": "e4bd97e927d96924", "attributeRulesDesc": "cf5a248e89b24c2b", "builtInPricesSynced": "eb9885c889598521", + "builtInStatus": { + "lastSynced": "66b7f514840b3ffc", + "neverSynced": "4d28bcc9c238aeac", + "seed": "0d9fee9d2de7a134" + }, "cancel": "19766ed6ccb2f4a3", "capturedModelsEmpty": "b97acb252c89e6fa", "capturedModelsMore": "ecccea94c62457a7", @@ -17573,6 +17739,45 @@ "tooManyRules": "1560079ec4011946", "tooManyTiers": "8c5f8e5ab314ee15", "troubleshootingTitle": "c59293ca3a3db64c", + "unpriced": { + "approximate": "78b9b22ebb6f5156", + "banner": "f5a8b26344e5eba3", + "bannerTruncated": "04c63fac69c125a8", + "colActions": "ff8059dc6752afdd", + "colCost": "7dee9df582ec20aa", + "colModel": "748fb9ab8099b3d6", + "colPricedAs": "181e4ae9e35a2002", + "colTokens": "a039dfb9628b53dd", + "createPrice": "5834e581200ba482", + "defaultTierPrices": "fc52b31ebbf086cc", + "emptyTitle": "5d5ae6accdf9641a", + "errLoad": "368bb48f479cb76c", + "errSave": "6d5ce40b8951af75", + "historicalGap": "0a1d1b0597440254", + "instrumentationDocs": "6f50e36585535ffc", + "keepPrices": "ae8f1c1c6ac489da", + "keptNotif": "cb1793b3a662a59b", + "moreAgents": "ecccea94c62457a7", + "mute": "8dd6857baf026850", + "muteConfirmMessage": "84367224ba1d13ae", + "muteConfirmTitle": "fa1be2ff9025507c", + "mutedNotif": "b75f8f814bcec848", + "noActionNeeded": "6a6527dda190a006", + "noMatch": "cd8d844d2c3dedc1", + "noModelHint": "da5b59a35e5d5ed9", + "noModelName": "6e2cf4b2b853869d", + "noStreamsDesc": "8cf4bf6441c1549a", + "noStreamsTitle": "e4c51dcda2093282", + "notPriced": "5805ffba6946917c", + "pricedNow": "763cb445aed37244", + "recordedCostNote": "76837cb622d7118d", + "spans": "7c048203171e0876", + "streamLabel": "1eec3071dd26e224", + "subtitle": "08f38ded20b5a9a2", + "title": "2a0a598ff51711b5", + "window": "5c37cf8f018b4ac5", + "windowRange": "603aaefffcd2060b" + }, "urlImportTab": "c4402d38a92d1c09", "usageKeyCol": "5e046807c81ec9dc", "usageKeyContainsSpaces": "eafd75e5ea847a68", @@ -17960,6 +18165,7 @@ "escalationEditing": "27e39fff96e0b4e8", "escalationHeld": "6eb2dc1844144383", "escalationLoading": "d441577128d7f2a1", + "escalationNobodyPaged": "cd1fc03ae9d071e5", "escalationNotStarted": "e626cc87c1c4a26c", "escalationPagesNobody": "760137c721470566", "escalationPagingStep": "1a1a433a79fa9dc9", @@ -18509,6 +18715,7 @@ "removeMemberFailed": "af28d51aed3a83d8", "removeMemberHandsOver": "4a9c9cda70d29445", "removeMemberLeavesGap": "656a7ac9de0c7886", + "removeMemberReorders": "8744a543b4facebb", "removeMemberTitleNamed": "13a85193691c916c", "removeMemberTitlePerson": "01c1f0250884f593", "removeRotationBlocked": "bbc3c91dfe484667", @@ -18613,13 +18820,14 @@ "rotationOpenMembers": "6e5e1e137765681a", "rotationOrderHint": "fe09e9fc139c1309", "rotationPreviewEmpty": "e9da2a6f8981aa03", + "rotationPreviewNow": "00174097054e8787", "rotationPreviewPairLegend": "7f1739c73bac3a77", "rotationRestrictionAdd": "b7283e2a89b85b34", "rotationRestrictionDays": "e08c0aa8f558f39f", "rotationRestrictionFrom": "218197693424e015", "rotationRestrictionRemove": "c3812fc4acb861d5", "rotationRestrictionTo": "f4b06ef6d3c81436", - "rotationRestrictionZeroLength": "62df11bf4852e883", + "rotationRestrictionZeroLength": "f9b1b36b936f9a5a", "rotationRetiredTag": "a9f71bc2404c9193", "rotationRuleCount": "ff07023b114bde98", "rotationSectionRules": "9cb43d33ba6744d4", @@ -18704,7 +18912,7 @@ "ruleEditorConflictKeptBy": "74be5c72b7d753aa", "ruleEditorConflictSameTeam": "884d0e10ac781669", "ruleEditorConflictTakesOver": "16ac75b9b76a18fc", - "ruleEditorConflictUnclaimed": "27d5e24d428ffc85", + "ruleEditorConflictUnclaimed": "bff6bd6c7ad32bd3", "ruleEditorDiscardCondition": "eb1a70e39274bb76", "ruleEditorEmpty": "b4099d03179c1240", "ruleEditorFieldPlaceholder": "e867f9b7c5ea6bf9", @@ -18799,6 +19007,7 @@ "scopePathEmpty": "db4fd2a829db4309", "scopeServiceHelp": "177357ac04c01152", "scopeValuePlaceholder": "0b24aed53ab654ea", + "scopeValuesSeen": "d9b779ee40d035ed", "searchResponses": "9b56eff16ec33c42", "searchTeams": "3ad7e221faf10419", "searchTeamsPeople": "84bc7b36a4e6ff5f", @@ -18808,6 +19017,7 @@ "sectionHint_resolved": "7ccc927dd026552c", "sectionHint_ringing": "267e1c559487547e", "sectionHint_ringingRouted": "eed6237eeccd471c", + "sectionHint_ringingStopped": "8ca9ade8957410db", "sectionHint_ringingUnrouted": "5fd68e3f69e31c51", "sectionHint_snoozed": "632057805efe13d1", "section_handled": "1e7536d56c45d9cd", @@ -19107,6 +19317,10 @@ "unroutedSignal": "1e9806e4227ba3b9", "unroutedTitle": "c0f5487da1e37214", "unroutedWriteRule": "75f7e48ed0927929", + "unsnooze": "94798842ac921e31", + "unsnoozeFailed": "a9e896a723df69d0", + "unsnoozeHint": "0f39fce573e74e53", + "unsnoozed": "ba964e0ca1d094b3", "upcoming": "cd41bc1383278f4a", "upcomingFrom": "51449acb1f33eb7e", "upcomingNoChange": "c3e7c9ebaf11435d", @@ -19145,6 +19359,10 @@ "deleteError": "4e1252dd62c17a4b", "deleteTitle": "0f81c0d86606f518", "deleted": "053cce198e4c5f50", + "disabled": { + "description": "81eee881644382fd", + "title": "91aea42163f5c2c6" + }, "failedToDeriveSchema": "7c0920d61024a096", "failedToFetchCatalog": "3d180cc1e30ede2e", "failedToImportScoreConfig": "cea17a4a8ef74d36", @@ -19172,7 +19390,7 @@ "importTypeRequired": "69bc45f13263fda6", "invalidJsonFormat": "70410685471d0577", "job": { - "backTo": "c27068e179c5a5a9", + "backTo": "b9f4405cc53cea2c", "columns": { "actions": "ff8059dc6752afdd", "created": "d70b9e24bca26b40", @@ -19291,6 +19509,7 @@ "checked": "d5963b914e843b1f", "degraded": "a8494c12f2243903", "healthy": "7f1e323b6272c620", + "lastScored": "0409ebe70cb2950b", "noRecentRuns": "060b3875c66ccf92", "since": "8dbe1c0bde15c300", "summary": "d308c48030d712ba", @@ -19519,7 +19738,7 @@ "authEditNote": "e8fff442aa27b600", "authSection": "66880d2d8216260d", "availableModelsLabel": "9dbfd0478bd51235", - "backTo": "9f73d5ebe9024c6b", + "backTo": "996c32b35f2182a9", "cannotRename": "1219ec44a131d522", "createTitle": "917817050bd786f8", "defaultModelLabel": "3840d9d29421c46c", @@ -19800,7 +20019,7 @@ "authConfigured": "20158224750041d6", "authLabel": "e3b389c6838e46ca", "authSection": "66880d2d8216260d", - "backTo": "ec7bdbca67479176", + "backTo": "d8598427499abb65", "badgeLlm": "c7b08a64bb5189e8", "badgeRemote": "ffa98e02f7ce33fc", "columns": { @@ -19991,6 +20210,9 @@ "saveError": "20354bc384081c3f", "searchPlaceholder": "b73c243999e70f74", "selectedPrefix": "bef9d85df8ea13fe", + "temperatureHelp": "159b6f26f887d3e5", + "temperatureLabel": "b958ce8b871ab36b", + "temperaturePlaceholder": "5feceb66ffc86f38", "testPanel": { "disabledHint": "af9dfbb4c32b55f3", "emptyPrefix": "5244a9d3af4c95c3", @@ -20023,6 +20245,7 @@ "nameRequired": "0e277315963f1277", "providerRequired": "caa0c95d885aab0c", "retriesInvalid": "12b3bb4259e8ce7d", + "temperatureInvalid": "1ad25a87a7426b05", "timeoutInvalid": "1a85eee09fd39cf2" }, "versionsLoadError": "211bf839fb3e9353" @@ -20332,6 +20555,13 @@ "constant": "8ab253e4aab66e2a", "csv": "90afcf937330e97f", "custom": "494ca78f7374e46f", + "date": "99c40ab405926cb5", + "dateDmy": "9c7d6e0f947c2cdc", + "dateEpoch": "595572802984f2ff", + "dateEpochms": "65720c8b01f4753f", + "dateEpochus": "0caeb49eaed902cf", + "dateIso": "3b3dd31839bb4468", + "dateMdy": "ec48d7101d123086", "doublequote": "0e1af56126edd381", "list": "e547bf4f1b91ebb8", "pipe": "b2114e05a8ef3080", @@ -24623,6 +24853,7 @@ "outboundEmpty": "322ad255e684c217", "outboundQueue": "164d6d484caf393a", "refreshTokenKept": "bb4cab940d1dea50", + "refusedPosts": "95b8e76abaf0d6bb", "reinstall": "c630a782a9eb8569", "reinstalled": "cffd0c1d3780790e", "sockets": "9ed979d196a60475", @@ -27821,6 +28052,7 @@ }, "workflows": { "chooseATriggerNodeToStart": "7904798bda88e090", + "endpointUrlCopied": "2f9b25cbd02e98a8", "onlyOneIncomingConnectionToA": "b2624193ef7b83f2", "thisBranchAlreadyEndsInA": "2c04309c6063252a", "thisConnectionWouldCreateALoop": "1bfe0227517d5d1d" @@ -27836,6 +28068,13 @@ "applyAndSearchEquals": "0957a5c642435266", "applyAndSearchNotEquals": "f27e9d0b738f3717", "applyPendingFilters": "ce1202e0d05abe3b", + "askAi": { + "askAboutSpan": "0c4630fa1207852b", + "explainTrace": "e70067d9b76c657b", + "explainTraceHint": "0ddeb2fc8e242088", + "spanChip": "1e19b7d756495f48", + "traceChip": "f52267dc28d9470a" + }, "backToLogs": "ed627b7ddd4e0cca", "backToResults": "c7ef0e278b1e08c0", "backToTraces": "f03da00bbeb8113f", @@ -28038,6 +28277,7 @@ "tool": "783d36e81261aee8" }, "lLMErrorTable": { + "loadFailed": "938bec8eff1825c7", "noData": "3b41ba9c7cb8c5d6", "noErrorsInRange": "fbbc2eb15f5981f1", "operation": "0f044feb6ca7d676", @@ -28103,6 +28343,7 @@ } }, "nextMatch": "825e5abd0762be6e", + "nlNeedsSql": "effe40b58861fd76", "noCorrelatedLogsFound": "643231c56fd2784d", "noData": { "askAi": "0dd9b2668db5d2c3", @@ -28147,6 +28388,23 @@ "operation": "0f044feb6ca7d676", "p50Median": "76661f0c8ac6ce54", "previousMatch": "daa2f8c3fc897cc7", + "redActions": { + "addRedToDashboard": "f9995c951ada8920", + "bucketNotice": { + "days": "4dbd138c5b05a855", + "hours": "7e91f22901a70179", + "minutes": "d429f1479eca3f89", + "seconds": "65cac4f4920546e5" + }, + "bucketNoticeSingle": { + "days": "e941f1e462b76056", + "hours": "b9ff968eedf27ef7", + "minutes": "e3290078adb23ed8", + "seconds": "f72027031f9cacbd" + }, + "durationActions": "604c22760aaacfb3", + "menuGroupDashboards": "a53bcafb67d960df" + }, "redMetrics": "a9d1ab9a2d6d4dac", "results": { "errorColumn": "54a0e8c17ebb21a1", @@ -28374,7 +28632,7 @@ "estimatedWithoutCache": "bcd4cd46920456b4", "filterErrors": "4eac71524e3ed530", "grossCacheReadSavings": "e39d337acfe8718d", - "latencyLead": "bff1c3d5d14f51ce", + "latencyLead": "3fb271649a2b7693", "netCacheImpact": "4bdd0ac6e0dadd9c", "resetFilters": "660f3d76f4f2802d", "tokens": "e7d163813b8a11d0", @@ -28760,6 +29018,10 @@ "folder": "74ccd43303847f26", "header": "e2073645cb0dbbdd", "history": { + "alertFiredEmptyTitle": "817e727c68262cf8", + "allTriggers": "93b7f47d48675fef", + "detailsNoKey": "07b1ae92b6fde2e4", + "detailsWithKey": "86d2daf01b268871", "duration": "4fc52a3c4c558b51", "durationHoursMinutes": "425dc6c72de6fdc5", "durationMinutesSeconds": "c4521614d0a2513f", @@ -28768,25 +29030,327 @@ "ended": "7cdc804e6996997d", "error": "54a0e8c17ebb21a1", "failed": "031a8f0f659df890", + "filterEmptyDimmed": "9b00c21e02ed1ae1", + "filterEmptyTitle": "c7a5be937e62a70f", "hideTestRuns": "39ef1b67cd8d8c06", + "incidentEventEmptyTitle": "d736cf98147a0ceb", "loadError": "762d0146abbad86f", "loadRunError": "a6300f95d9e4e4aa", "open": "0e76960093379060", "openFullView": "fd43711ac463dacb", + "openRun": "95fe7393c85ec788", + "reasonExpired": "555b5a57d6f0ab77", + "reasonRunTimeout": "86f367a202f28c1c", + "reasonWorkerLost": "00698d7c48b1fafe", + "reasonWorkflowDisabled": "8715207062f345f0", "retry": "942087cc2d41e013", "retryError": "1ff77ecb8550b8f3", "retryMessage": "abcfc90ca7b23fa9", + "retryOf": "f1dc656b1bd5c5d4", "retryStarted": "ca21bfeee92fdf35", "retryTitle": "e3399695e101743e", "retryTooltip": "ce203c4a3bbbe229", + "run": "00d60e31a4e6b834", "runType": "baaddf70fb5d432b", + "searchEmptyAction": "3b7ea51793e9d906", + "searchEmptyTitle": "813c63791d953182", + "searchRuns": "f93a3e32be86c829", "showTestRuns": "5261cabacd0dba01", + "source": "0e570ca6fabe24f9", + "sourceAlertFired": "4a2b79784a7b2c42", + "sourceDetails": "95de492834d708ef", + "sourceHttp": "f1ee1152c8b29ea2", + "sourceIncidentEvent": "a7b1ea3b90935a8c", + "sourceManual": "84a2e40670df461b", + "sourceOther": "f97e9da0e3b879f0", + "sourceRetry": "2f9c439b3b7e705c", "started": "ecbc89cd37a03734", "status": "920e413c7d411b61", + "statusExpired": "424a2551d356754c", + "statusQueued": "661ff40a07e037bb", + "statusRunning": "f4ccae29e1bb0c20", "success": "c88a0b907419a70c", "testRun": "fe9e2fc32433289d", "testRunTooltip": "a350cfc8353cff85", - "title": "74c90dadee1b9dff" + "timelineAgoDays": "02ee8a8b0b7869f7", + "timelineAgoHours": "a852514c755e2aa0", + "timelineAgoMinutes": "1695a4da57d5776d", + "timelineNow": "ed5eb9a37e2d8231", + "title": "74c90dadee1b9dff", + "triggerFilter": "8b9c643731c94119" + }, + "http": { + "acceptRequests": "3cc264203f3e1279", + "active": "92340695899bd2d8", + "advanced": "9f088dbebd6c3c70", + "advancedSummary": "9a2f2b2aa43ce830", + "authAbout": "3220ba9a4dd64473", + "authInfo": "732a42bf45eceac6", + "authLabel": "80ee37242dc6e62d", + "authSigned": "b6cc80d300c385f7", + "authToken": "d2089be672953d11", + "bodySizeBytes": "7b315b762548b35b", + "bodySizeKiB": "e6d5832839cceed2", + "bodySizeMiB": "fcebbf180a73d0ff", + "changeFailed": "912a8e5f6a6dbe10", + "colActions": "ff8059dc6752afdd", + "colCreated": "d70b9e24bca26b40", + "colLastUsed": "830ec7f812f9d862", + "colSecret": "7e32a729b1226ed1", + "colStatus": "920e413c7d411b61", + "colToken": "d2089be672953d11", + "commandCopied": "e5c02424e511e1ef", + "copyCommandFailed": "7a820eb530322b2d", + "copyCredentialChanged": "8fa5d36afff4a1c4", + "copySecret": "9b80d4b38e70c8c5", + "copyToken": "d35b4ef7c618415a", + "copyUrl": "fa26011bf19e1198", + "copyUrlDraftHint": "156f2342d5347b2b", + "copyUrlFailed": "c4858d355d69b7da", + "createForbidden": "945cad3763fad357", + "creatorGone": "a20f7dd7ec9e5c62", + "deleteBody": "34687f0a6c2d1e71", + "deleteButton": "6772d678942a3f79", + "deleteFailed": "746079e0af29c480", + "deleteMeta": "864130edac832e4e", + "deleteTitle": "77a7901069cca1d0", + "disableBody": "704424a23fa25a47", + "disableConfirm": "06f0e210b27d4d62", + "disableTitle": "51d730dcadce4a68", + "disabledBanner": "da203b3cb4b1c44d", + "done": "11a6767d5674c7e4", + "draftBanner": "de322c663fcaefee", + "dryRunAccepted": "b47d43594a5ceade", + "dryRunFailed": "6a09aecdacb8cd19", + "dryRunInput": "1e1aec27e370bdc6", + "dryRunMeta": "c68f730740081514", + "dryRunRateLimited": "9456b05c8d09541a", + "dryRunRefused": "29dff3e9aecda49c", + "dryRunRefusedPaused": "1221589dfc7065fc", + "dryRunStatus": "cb609f2cb8bd987a", + "editorButton": "9175da02d25c7b55", + "editorButtonOff": "ca7981b46ecf2c17", + "editorButtonOn": "130011756125313c", + "editorButtonRefusedDraft": "82ef1aad083c253c", + "editorButtonRefusedPaused": "bfb25e742fb6c00f", + "editorButtonTooltip": "3469d34ee7dcb761", + "endpointExistsHint": "ea4b1b3981c729a7", + "endpointExistsHintSigned": "ab98fd4d3b859b94", + "endpointUrl": "2578179d177903e1", + "errorNoLiveCredential": "87f27efdc67df9cb", + "errorNotAllowed": "7db15c5ce04c9b80", + "errorNotConfigured": "e86bbf9c69347b02", + "exampleActiveSecret": "5632f0f02fb77a6d", + "exampleActiveToken": "8e9746411032ddc5", + "exampleHintSigned": "2981e1413d06f5a0", + "exampleHintSignedPlaceholder": "2e4b4f0a0b5fd31b", + "exampleHintToken": "e03506daef6440d1", + "exampleHintTokenPlaceholder": "e6d0b3bf9749bd74", + "exampleRequest": "ba15af9e002393bc", + "expired": "424a2551d356754c", + "expiresInDays": "da3b526ec02bb68c", + "expiresInHours": "cf5e5e97f6a66453", + "fieldGroup": "f1ee1152c8b29ea2", + "fieldGroupBodyHint": "b6f6cb95ff15cdc6", + "fieldGroupQueryHint": "088f9b97cb821261", + "headerName": "dcd1d5223f73b3a9", + "headerValue": "8e37953d23daca5f", + "headers": "194e9fe656a1bcab", + "headersKept": "5b48d0229dcb6ff6", + "kindNote": "79b46f794b73b152", + "kindNotePayload": "3ae28c7412d6a4ee", + "kindNotePayloadHide": "0db5f0cba18f2d02", + "lastCall": "216689da1c52bf4f", + "lastCallNone": "97838d7724882b07", + "lastCallNoneRefused": "e0fc67bb703564fc", + "lastCallStatus": { + "expired": "fa64ea1e82e1206f", + "failed": "5d28a90f4498a814", + "queued": "d36be6494248ee06", + "running": "c071cf5f5ed6f884", + "succeeded": "5dceaeceb6d8a49d" + }, + "listMenuItem": "3cc0f1ee2da02e48", + "listTag": "56d6f32151ad8474", + "listTagTooltip": "037f01286a33aab5", + "loadError": "361318790da4cf42", + "maxBody": "198c607c2fcd6e5c", + "maxBodyHint": "5d4ded1f1ec22b8c", + "maxBodyRange": "e3549f9f86858835", + "needsAdmin": "b4d4fce3546efbdd", + "needsEdit": "a000127857e9a71f", + "never": "6300ef800bb88429", + "newSecretLabel": "c08c84dbb0cb4fc7", + "newTokenLabel": "fe46cb83ad1c5a35", + "nodeBadge": "cc5eaa11c684a30b", + "offBody": "e540546366294c8d", + "offExistingBody": "b2dcc2dacb5e1082", + "onMeta": "fed6287a4b973884", + "openStep": "463ad0ca73f8f4f4", + "outputCaption": "1e98c9dc3f8b5fbe", + "overlapDay": "f0514e8df84107f4", + "overlapHour": "f8b8883f0c9d8d82", + "overlapNow": "24a5d1cd7649d755", + "overlapWeek": "7f920bb639c93075", + "panelSubtitle": "3b1fec9ffcfc9e63", + "panelTitle": "9175da02d25c7b55", + "payloadFrom": "e64a6482125e8f6f", + "payloadHttp": "f1ee1152c8b29ea2", + "pickerCue": "0bf4a26c86ee6816", + "raiseLimit": "3bdea189a52695ed", + "rateLimit": "aa6d477fff29576b", + "rateLimitHint": "852659db035dc921", + "rateLimitRange": "748b3466f6b8cc93", + "readOnlyOnMeta": "f0ea7fe4f448fb28", + "reason": { + "credential_in_url": { + "fix": "fde4cf14cc9be644", + "title": "41805d7e323055c7" + }, + "endpoint_disabled": { + "fix": "957a2133fa4c1163", + "title": "310f36c6306d4469" + }, + "idempotency_key_reused": { + "fix": "3bfd0c548277cca9", + "title": "f6a5f27cbcba7be5" + }, + "invalid_idempotency_key": { + "fix": "96709b3d11df60ba", + "title": "a3d2a892413b9971" + }, + "invalid_signature": { + "fix": "5512fc3bcdbd7e2a", + "title": "97b096319f1c128b" + }, + "invalid_token": { + "fix": "f8e8eed7b229ca08", + "title": "086efea7640e6806" + }, + "payload_too_large": { + "fix": "0eefeb2f57a45ab2", + "title": "c3123ec25291b935" + }, + "queue_full": { + "fix": "8ee9cadfe4b71ea8", + "title": "4ad672a94c1af12d" + }, + "rate_limited": { + "fix": "559bb643b0911245", + "title": "a06130a5a2818ae5" + }, + "stale_timestamp": { + "fix": "de9286cb2791bc18", + "title": "526d8400134898e3" + }, + "worker_unavailable": { + "fix": "69cd89d5d1f8c516", + "title": "be65838a2c9df8a9" + }, + "workflow_disabled": { + "fix": "c5a3b8eee8f425df", + "title": "533631053f3864bf" + }, + "workflow_not_published": { + "fix": "0b9ae7f66b3ada69", + "title": "7f626c86b88eb6ac" + } + }, + "regionBanner": "94cbb3b56a79bc8c", + "regionTag": "9c516d4563be01e4", + "rejectionMeta": "665bb7a6e1028e75", + "rejectionsCaption": "92af1abe4eb8c381", + "rejectionsHide": "ac20a57bfde0bbc4", + "rejectionsLine": "5b35ad1e9a78b17a", + "rejectionsLoadError": "0571e6b78444c5ce", + "rejectionsShow": "0df6f1cad36c49da", + "rejectionsTitle": "3486ecce0d1ddc1a", + "request": "59f03d642b41e22f", + "requestBodySize": "895fec844e359f4c", + "requestCallerIp": "cc8f4f4a308c78bf", + "requestContentType": "6f51cb0403204b19", + "requestIdempotencyKey": "e904f4599aa01bf8", + "requestReceived": "49f19beeecf442ef", + "requestToken": "d2089be672953d11", + "retiring": "fd2b42810f6b4d83", + "revealBannerBody": "53d7d500858d0e9c", + "revealBannerBodySigned": "1d7803265dc1e4f5", + "revealBannerTitle": "a6f921fabd574f78", + "revealDenied": "b126c72b919fba7d", + "revealFailed": "6efd01b4c3d5ac96", + "revealFailedSigned": "98866207d6a91bad", + "revoke": "87e6d00bbf53ec5a", + "revokeFailed": "b7e634223402ed50", + "revokeNow": "581e15bd3fcf5a3a", + "revokeTitle": "b840925a7ecddfa5", + "rotate": "c3613b1704f54c8b", + "rotateBannerBody": "da801b4fee507396", + "rotateBannerBodyFresh": "7eb873184b6208ba", + "rotateBannerBodyFreshSigned": "ee624a55ecab5eab", + "rotateBannerBodyRevoked": "ecab40fb07e4cb33", + "rotateBannerBodyRevokedSigned": "98ba812645669ee5", + "rotateBannerBodySigned": "2aa63c54f2aa7a65", + "rotateBannerTitle": "499360406bcbd4a2", + "rotateBannerTitleSigned": "ae2310454ff61733", + "rotateBlocked": "cd6525a96b01bd5d", + "rotateBlockedSigned": "a49e5568af5fdf92", + "rotateConfirm": "4ade788283fe9a33", + "rotateConfirmSigned": "ca38c242319770f6", + "rotateConsequence": "73a9612eaae73a20", + "rotateConsequenceNow": "cf03588511c5f9ab", + "rotateConsequenceNowSigned": "25e077ce94930d8d", + "rotateConsequenceSigned": "a059892362ef0b40", + "rotateFailed": "1ed1e49a57c647f7", + "rotateLead": "b9f7594e1c806386", + "rotateLeadNone": "8a8a18bb31fa2981", + "rotateLeadNoneSigned": "bfd5eca9e538d7a9", + "rotateLeadSigned": "a32df55035f99b20", + "rotateLeadUnused": "c17f8983e70ef5ef", + "rotateLeadUnusedSigned": "3c142807e208c876", + "rotateLink": "c3613b1704f54c8b", + "rotateTitle": "4ade788283fe9a33", + "rotateTitleSigned": "ca38c242319770f6", + "runExpiredBanner": "29b5e42c19354b80", + "runFailedAt": "9fa3375cdfb43ac7", + "runGuardHint": "1dcad435ba54bae6", + "runTest": "e031e0df30c9898f", + "runTestHint": "608d160dcbb88dfb", + "runTestHintList": "b9d55d8957013535", + "runTestInstead": "c2f14a4b48e42849", + "runWorkerLostBanner": "c6bece3713bb606a", + "runsEmptyAction": "c6f6e25fc8a4902a", + "runsEmptyBody": "f2cb2f033bbf7d7e", + "runsEmptyTitle": "7cef77a71d7dd563", + "saveAndCreate": "5f5d85b59343b9a7", + "saveLimitsFailed": "17a15ea8a14e487d", + "secretCopied": "704aed35a6feded1", + "secretHint": "1ebbb4569e65cf09", + "secretLabel": "e7ee22e117a12ad8", + "secretStorageWarning": "26443323470d640b", + "secretsTitle": "37364fc41ded5401", + "sendTest": "5d2372e63ec25729", + "sendTestHint": "aaf9e310393d92b4", + "sendTestHintPaused": "192b439940d2f64d", + "sendTestSigned": "7861ceb0624b45cb", + "snippetsLabel": "ba15af9e002393bc", + "switchToSignedBody": "a0882a162191a445", + "switchToSignedTitle": "094adfc152298a2d", + "switchToTokenBody": "c35928b6d2c2105b", + "switchToTokenTitle": "1e28c9f6e0346c24", + "switchedBannerTitle": "96993ffc5037d390", + "switchedBannerTitleSigned": "5b31071a6b92c710", + "tokenCopied": "c9feac7acc32ee92", + "tokenHint": "c48da8cbbe1a2614", + "tokenLabel": "d2089be672953d11", + "tokensTitle": "a039dfb9628b53dd", + "triggerLinkOff": "5ca56d9aca5f5e51", + "triggerLinkOffAction": "bb9c27d72fa44e74", + "triggerLinkOn": "e3dd331f610bb066", + "triggerLinkOnAction": "695ff3927de6f267", + "turnOnFailed": "fcd76bcbf00c543a", + "unsavedBody": "066ff1cac3a503d8", + "useAsTestInput": "1a478a159532c84a", + "viewRun": "aaf7fccc7d1315f2" }, "linkAlerts": { "alertsLabel": "f62e9267d196c761", @@ -29008,6 +29572,8 @@ "lastTestRun": "585b1ab789dddea8", "notConfigured": "c5418aa5e0f85e5b", "notVerified": "ec3edb8410037a74", + "payloadFrom": "e64a6482125e8f6f", + "payloadFromHint": "c50945a0b865fc7c", "recordedFailure": "d4f33864645e20c9", "recordsUnavailable": "9d86d83b1749c16f", "rehearsalOnly": "fa849ce09502071d", diff --git a/src/core/src/alerts/alert.rs b/src/core/src/alerts/alert.rs index 687c1a1899..04b9f9f923 100644 --- a/src/core/src/alerts/alert.rs +++ b/src/core/src/alerts/alert.rs @@ -3868,6 +3868,33 @@ async fn send_discord_with_attachment( send_outcome(resp_status, &resp_body, hide_body) } +/// A destination's non-2xx reply; `body` is `None` when the peer may not show it. +#[derive(Debug)] +pub(crate) struct DestinationStatusError { + pub(crate) status: reqwest::StatusCode, + body: Option, +} + +impl std::fmt::Display for DestinationStatusError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match &self.body { + Some(body) => write!(f, "sent error status: {}, err: {body}", self.status), + None => write!(f, "sent error status: {}", self.status), + } + } +} + +impl std::error::Error for DestinationStatusError {} + +#[cfg(all(test, feature = "enterprise"))] +pub(crate) fn send_outcome_for_test( + status: reqwest::StatusCode, + body: &str, + hide_body: bool, +) -> Result { + send_outcome(status, body, hide_body) +} + /// What the caller of a send sees; a peer only the operator allowlist admits shows its status only. fn send_outcome( status: reqwest::StatusCode, @@ -3877,8 +3904,10 @@ fn send_outcome( match (status.is_success(), hide_body) { (true, false) => Ok(format!("sent status: {status}, body: {body}")), (true, true) => Ok(format!("sent status: {status}")), - (false, false) => Err(anyhow::anyhow!("sent error status: {status}, err: {body}")), - (false, true) => Err(anyhow::anyhow!("sent error status: {status}")), + (false, hide_body) => Err(anyhow::Error::new(DestinationStatusError { + status, + body: (!hide_body).then(|| body.to_string()), + })), } } @@ -4392,16 +4421,7 @@ async fn build_notification_context( None => String::new(), } } else if alert.stream_type == StreamType::Traces { - // The traces page takes a filter expression in `query`, not SQL, so the query is left out. - format!( - "{}{}/web/traces?stream={}&from={}&to={}&org_identifier={}&tab=spans", - cfg.common.web_url, - cfg.common.base_uri, - alert.stream_name, - alert_start_time, - alert_end_time, - alert.org_id - ) + traces_alert_url(&cfg, alert, alert_start_time, alert_end_time) } else { match alert.query_condition.query_type { QueryType::SQL => { @@ -4538,6 +4558,29 @@ async fn build_notification_context( chart_png: None, } } + +fn traces_alert_url(cfg: &config::Config, alert: &Alert, start_time: i64, end_time: i64) -> String { + let mut url = format!( + "{}{}/web/traces?stream={}&from={}&to={}&org_identifier={}&tab=spans", + cfg.common.web_url, + cfg.common.base_uri, + alert.stream_name, + start_time, + end_time, + alert.org_id + ); + // The traces page takes a filter expression in `query`, not SQL, so only the WHERE is carried. + if alert.query_condition.query_type == QueryType::SQL + && let Some(sql) = &alert.query_condition.sql + { + let where_clause = config::meta::sql::extract_where(sql).where_clause; + if !where_clause.is_empty() { + url.push_str("&query="); + url.push_str(&base64::encode_url(&where_clause)); + } + } + url +} pub fn get_row_column_map(rows: &[Map]) -> HashMap> { let mut vars = HashMap::with_capacity(rows.len()); for row in rows.iter() { @@ -5518,6 +5561,24 @@ mod tests { use super::*; + #[test] + fn a_failed_send_keeps_its_text_and_hides_the_body_when_asked() { + let status = reqwest::StatusCode::INTERNAL_SERVER_ERROR; + let shown = send_outcome(status, "boom", false).unwrap_err(); + assert_eq!( + shown.to_string(), + "sent error status: 500 Internal Server Error, err: boom" + ); + let hidden = send_outcome(status, "boom", true).unwrap_err(); + assert_eq!( + hidden.to_string(), + "sent error status: 500 Internal Server Error" + ); + let typed = hidden.downcast_ref::().unwrap(); + assert_eq!(typed.status, status); + assert!(typed.body.is_none()); + } + #[tokio::test] async fn a_multi_alert_with_recovery_saves() { let mut alert = Alert::default(); @@ -9592,14 +9653,13 @@ mod rule_notification_tests { assert!(matches!(error, AlertError::PromqlMissingQuery)); } - #[tokio::test] - async fn traces_alert_url_opens_the_traces_page() { + async fn notification_url_for_traces_alert(query_type: QueryType, sql: Option<&str>) -> String { let mut alert = Alert::default(); alert.org_id = "org".into(); alert.stream_type = StreamType::Traces; alert.stream_name = "default".into(); - alert.query_condition.query_type = QueryType::SQL; - alert.query_condition.sql = Some("SELECT span_id FROM \"default\"".into()); + alert.query_condition.query_type = query_type; + alert.query_condition.sql = sql.map(Into::into); let options = ProcessTemplateOptions { rows_end_time: 0, start_time: None, @@ -9611,12 +9671,15 @@ mod rule_notification_tests { resolved: false, }; let context = build_notification_context("org", &alert, &[], &[], options, None).await; - let url = if let Some((_, suffix)) = context.alert_url.split_once("/web/short/") { + if let Some((_, suffix)) = context.alert_url.split_once("/web/short/") { let id = suffix.split('?').next().unwrap(); short_url::retrieve(&alert.org_id, id).await.unwrap() } else { context.alert_url - }; + } + } + + fn assert_plain_traces_url(url: &str) { assert!(url.contains("/web/traces?stream=default&")); assert!(url.contains("&from=") && url.contains("&to=")); assert!(url.contains("&org_identifier=org&")); @@ -9625,4 +9688,53 @@ mod rule_notification_tests { assert!(!url.contains("sql_mode")); assert!(!url.contains("query=")); } + + #[tokio::test] + async fn traces_alert_url_without_where_opens_the_traces_page() { + let url = notification_url_for_traces_alert( + QueryType::SQL, + Some("SELECT span_id FROM \"default\""), + ) + .await; + assert_plain_traces_url(&url); + } + + #[tokio::test] + async fn traces_alert_url_keeps_the_where_filter() { + let url = notification_url_for_traces_alert( + QueryType::SQL, + Some("SELECT count(*) AS cnt FROM \"default\" WHERE service_name = 'api' AND duration > 100"), + ) + .await; + assert!(url.contains("/web/traces?stream=default&")); + assert!(url.contains("&org_identifier=org&")); + assert!(url.contains("&tab=spans")); + assert!(!url.contains("sql_mode")); + let query = url + .split_once("&query=") + .unwrap() + .1 + .split('&') + .next() + .unwrap(); + assert_eq!( + base64::decode_url(query).unwrap(), + "service_name = 'api' AND duration > 100" + ); + } + + #[tokio::test] + async fn traces_alert_url_skips_unparsable_or_non_sql_queries() { + assert_plain_traces_url( + ¬ification_url_for_traces_alert(QueryType::SQL, Some("not sql WHERE")).await, + ); + assert_plain_traces_url(¬ification_url_for_traces_alert(QueryType::SQL, None).await); + assert_plain_traces_url( + ¬ification_url_for_traces_alert( + QueryType::Custom, + Some("SELECT * FROM \"default\" WHERE service_name = 'api'"), + ) + .await, + ); + } } diff --git a/src/core/src/alerts/mute.rs b/src/core/src/alerts/mute.rs index d99b6acaae..d1e8f34cdd 100644 --- a/src/core/src/alerts/mute.rs +++ b/src/core/src/alerts/mute.rs @@ -84,7 +84,8 @@ pub async fn mute( let now = now_micros(); let ends_at = requested_end(req.until_clear, req.minutes, req.ends_at, now)?; let groups = requested_groups(target, req).await?; - let rows = db::downtimes::list_cached(&target.org_id); + // The primary, so a mute made moments ago is seen; two at the same instant can still race. + let rows = downtimes::primary_rows(&target.org_id).await?; if let Some(live) = covering_mute(&rows, &target.alert_id, groups.as_deref(), now) { return Err(MuteError::Conflict(AlertMuteConflict::AlreadyMuted { downtime_id: live.id.clone(), diff --git a/src/core/src/alerts/scheduler/handlers.rs b/src/core/src/alerts/scheduler/handlers.rs index d21d02e868..f01e04c869 100644 --- a/src/core/src/alerts/scheduler/handlers.rs +++ b/src/core/src/alerts/scheduler/handlers.rs @@ -2875,7 +2875,7 @@ fn rows_by_downtime_key( /// The group key of one multi-alert row, the same key [rows_by_downtime_key] files it under. #[cfg(feature = "enterprise")] -fn downtime_row_key( +pub(crate) fn downtime_row_key( alert: &config::meta::alerts::alert::Alert, group_by: &[String], row: &config::utils::json::Map, @@ -2889,7 +2889,7 @@ fn downtime_row_key( } #[cfg(feature = "enterprise")] -fn alert_group_by(alert: &config::meta::alerts::alert::Alert) -> Vec { +pub(crate) fn alert_group_by(alert: &config::meta::alerts::alert::Alert) -> Vec { alert .query_condition .aggregation diff --git a/src/core/src/downtimes.rs b/src/core/src/downtimes.rs index 6f9d52c7f4..1917ecb58f 100644 --- a/src/core/src/downtimes.rs +++ b/src/core/src/downtimes.rs @@ -193,9 +193,8 @@ pub async fn list( pub async fn get(org: &str, user_id: &str, id: &str) -> Result { ensure_enabled()?; - let row = infra::table::downtimes::get(org, id) - .await? - .ok_or(DowntimeError::NotFound)?; + // The primary, so a detail opened right after its create is never a replica-lag 404. + let row = load(org, id).await?; access::authorize_row(org, user_id, &row, "GET").await?; let inventory = inventory::cached(org).await?; let matches = matches_of(&row, &inventory); @@ -378,8 +377,9 @@ pub async fn extend( created_id: None, }); } - let cached = db::downtimes::list_cached(org); - if let Some(follow_up) = live_follow_up(&cached, &before.id, window.end, now) { + // The primary: a follow-up created moments ago may not be in this node's cache yet. + let rows = primary_rows(org).await?; + if let Some(follow_up) = live_follow_up(&rows, &before.id, window.end, now) { let follow_up = load(org, &follow_up.id).await?; access::authorize_row(org, user_id, &follow_up, "PUT").await?; let current_end = follow_up.schedule.ends_at.unwrap_or(window.end); @@ -736,8 +736,18 @@ async fn extend_follow_up( /// A follow-up outlives its parent's cancel unless it is cancelled too; a failure is logged. async fn cancel_follow_ups(org: &str, user_id: &str, parent_id: &str, now: i64) { - let cached = db::downtimes::list_cached(org); - for id in follow_ups_to_cancel(&cached, parent_id, now) { + // The primary: an extend moments ago may have created a follow-up this cache lacks. + let rows = match primary_rows(org).await { + Ok(rows) => Arc::new(rows), + Err(e) => { + // The parent cancel already committed, so the cache beats leaving every follow-up live. + log::warn!( + "[downtimes] primary list of {org} failed, cancelling follow-ups of {parent_id} from the cache: {e}" + ); + db::downtimes::list_cached(org) + } + }; + for id in follow_ups_to_cancel(&rows, parent_id, now) { if let Err(e) = cancel_follow_up(org, user_id, id, now).await { log::warn!( "[downtimes] could not cancel {org}/{id}, the follow-up of {parent_id}: {e}" @@ -851,6 +861,12 @@ async fn load(org: &str, id: &str) -> Result { .ok_or(DowntimeError::NotFound) } +/// Every row of the org as the primary holds it, for a decision a replica lag must not skew. +pub(crate) async fn primary_rows(org: &str) -> Result, DowntimeError> { + let conn = infra::db::get_orm_client_rw().await; + Ok(infra::table::downtimes::list_with(conn, org, None).await?) +} + /// An unknown folder is a 400; the default folder is created on first use. async fn resolve_folder(org: &str, folder_id: &str) -> Result { let folder_id = if folder_id.trim().is_empty() { @@ -3199,7 +3215,7 @@ mod tests { } #[test] - fn writes_load_the_row_from_the_primary_and_the_detail_from_the_replica() { + fn writes_and_the_detail_load_the_row_from_the_primary() { assert!(body_of("async fn load(").contains("downtimes::get_rw(org, id)")); for write in [ "pub async fn update(", @@ -3211,8 +3227,7 @@ mod tests { ] { assert!(body_of(write).contains("load(org, "), "{write}"); } - let detail = body_of("pub async fn get("); - assert!(detail.contains("downtimes::get(org, id)")); - assert!(!detail.contains("load(org, ")); + // A detail opened right after its create must not 404 on replica lag. + assert!(body_of("pub async fn get(").contains("load(org, id)")); } } diff --git a/src/core/src/downtimes/notify.rs b/src/core/src/downtimes/notify.rs index d1e4382407..60dd4cb706 100644 --- a/src/core/src/downtimes/notify.rs +++ b/src/core/src/downtimes/notify.rs @@ -33,6 +33,8 @@ pub const LOG_LIMIT: u64 = 50; /// How often the notifier ticks; a start one tick back is already behind every healthy checkpoint. pub const TICK_INTERVAL_SECS: u64 = 30; pub const RESULT_OK: &str = "ok"; +/// A failed send's stored outcome when it carries no HTTP status. +pub const RESULT_FAILED: &str = "delivery failed"; const DOWNTIME_VARIABLE_PREFIX: &str = "{downtime_"; #[derive(Clone, Debug, PartialEq, Eq)] @@ -174,12 +176,13 @@ fn destinations_of(row: &Downtime) -> Vec { } fn log_entry(row: DowntimeNotification) -> DowntimeNotificationLogEntry { + let destinations: Vec = serde_json::from_value(row.destinations).unwrap_or_default(); DowntimeNotificationLogEntry { window_start: row.window_start, event: row.event, sent_at: row.sent_at, - destinations: serde_json::from_value(row.destinations).unwrap_or_default(), - result: row.result, + result: row.result.map(|r| safe_result(r, &destinations)), + destinations, } } @@ -195,7 +198,14 @@ async fn send(row: &Downtime, due: &DueEvent, destinations: &[String]) -> Result let mut errors = Vec::new(); for name in destinations { if let Err(e) = send_one(&row.org, name, &vars).await { - errors.push(format!("{name}: {e}")); + // The full error stays in the server log; folder readers see only its summary. + log::warn!( + "[DOWNTIMES] {} notification of {}/{} to {name} failed: {e}", + due.event.as_str(), + row.org, + row.id + ); + errors.push(outcome_summary(name, &e)); } } if errors.is_empty() { @@ -205,16 +215,16 @@ async fn send(row: &Downtime, due: &DueEvent, destinations: &[String]) -> Result } } -async fn send_one(org: &str, name: &str, vars: &[(&str, String)]) -> Result<(), String> { +async fn send_one(org: &str, name: &str, vars: &[(&str, String)]) -> Result<(), anyhow::Error> { let dest = crate::alerts::destinations::get(org, name) .await - .map_err(|e| e.to_string())?; + .map_err(|e| anyhow::anyhow!("{e}"))?; let Module::Alert { template, destination_type, } = dest.module else { - return Err("not an alert destination".to_string()); + return Err(anyhow::anyhow!("not an alert destination")); }; let own = match template { Some(template) => db::alerts::templates::get(org, &template).await.ok(), @@ -234,7 +244,33 @@ async fn send_one(org: &str, name: &str, vars: &[(&str, String)]) -> Result<(), crate::alerts::alert::dispatch_notification(org, &destination_type, &subject, body) .await .map(|_| ()) - .map_err(|e| e.to_string()) +} + +/// One destination's stored outcome: its HTTP status, never the reply body. +fn outcome_summary(name: &str, e: &anyhow::Error) -> String { + match e.downcast_ref::() { + Some(status) => format!("{name}: HTTP {}", status.status.as_u16()), + None => format!("{name}: {RESULT_FAILED}"), + } +} + +/// A stored outcome in the status-only format, else [RESULT_FAILED] so an older row never shows a +/// reply body. +fn safe_result(result: String, destinations: &[String]) -> String { + let safe_part = |part: &str| { + part.rsplit_once(": ").is_some_and(|(name, outcome)| { + destinations.iter().any(|d| d == name) + && (outcome == RESULT_FAILED + || outcome.strip_prefix("HTTP ").is_some_and(|code| { + code.len() == 3 && code.bytes().all(|b| b.is_ascii_digit()) + })) + }) + }; + if result == RESULT_OK || result.split("; ").all(safe_part) { + result + } else { + RESULT_FAILED.to_string() + } } fn template_for(own: Option