Skip to content

Commit 63e69a0

Browse files
EbonsignoriCopilot
andauthored
better analytics error logging (#57138)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 4b7c1c3 commit 63e69a0

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

src/events/lib/hydro.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { isNil } from 'lodash-es'
55
import statsd from '@/observability/lib/statsd'
66
import { report } from '@/observability/lib/failbot'
77
import { MAX_REQUEST_TIMEOUT } from '@/frame/lib/constants'
8+
import { createLogger } from '@/observability/logger'
9+
10+
const logger = createLogger(import.meta.url)
811

912
const TIME_OUT_TEXT = 'ms has passed since batch creation'
1013
const SERVER_DISCONNECT_TEXT = 'The server disconnected before a response was received'
@@ -70,6 +73,13 @@ async function _publish(
7073
) {
7174
const error = new Error(`Failed to send event to Hydro (${statusCode})`)
7275
if (inProd) {
76+
logger.error('Failed to send event to Hydro', {
77+
error,
78+
statusCode,
79+
body,
80+
requestBody,
81+
})
82+
// Report the error to Failbot
7383
report(error, { statusCode, body, requestBody })
7484
} else {
7585
throw error

src/search/lib/helpers/external-search-analytics.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ExtendedRequest } from '@/types'
12
import { publish } from '@/events/lib/hydro'
23
import { hydroNames } from '@/events/lib/schema'
34
import { createLogger } from '@/observability/logger'
@@ -9,7 +10,7 @@ const logger = createLogger(import.meta.url)
910
* Returns null if the request should continue, or an error response object if validation failed
1011
*/
1112
export async function handleExternalSearchAnalytics(
12-
req: any,
13+
req: ExtendedRequest,
1314
searchContext: string,
1415
): Promise<{ error: string; status: number } | null> {
1516
const host = req.headers['x-host'] || req.headers.host
@@ -73,12 +74,12 @@ export async function handleExternalSearchAnalytics(
7374
version: '1.0.0',
7475
created: new Date().toISOString(),
7576
hostname: normalizedHost,
76-
path: '',
77-
search: '',
77+
path: req?.context?.path || '',
78+
search: 'REDACTED',
7879
hash: '',
79-
path_language: 'en',
80-
path_version: '',
81-
path_product: '',
80+
path_language: req?.context?.language || 'en',
81+
path_version: req?.context?.version || '',
82+
path_product: req?.context?.product || '',
8283
path_article: '',
8384
},
8485
search_query: 'REDACTED',
@@ -90,7 +91,7 @@ export async function handleExternalSearchAnalytics(
9091
await publish(analyticsPayload)
9192
} catch (error) {
9293
// Don't fail the request if analytics fails
93-
console.error('Failed to send search analytics:', error)
94+
logger.error('Failed to send search analytics:', { error })
9495
}
9596

9697
return null
@@ -146,16 +147,12 @@ function stripPort(host: string): string {
146147
return hostname
147148
}
148149

149-
interface ExternalAPIRequestLike {
150-
headers: Record<string, string | undefined>
151-
}
152-
153150
/**
154151
* Determines if a request is likely from an external API client rather than a browser
155152
* Uses multiple heuristics to detect programmatic vs browser requests
156153
*/
157154
const userAgentRegex = /^(curl|wget|python-requests|axios|node-fetch|Go-http-client|okhttp)/i
158-
function isExternalAPIRequest(req: ExternalAPIRequestLike): boolean {
155+
function isExternalAPIRequest(req: ExtendedRequest): boolean {
159156
const headers = req.headers
160157

161158
// Browser security headers that APIs typically don't send

0 commit comments

Comments
 (0)