( source: PluginFetchSource, urlOrSpec: string | undefined, outcome: PluginFetchOutcome, durationMs: number, errorKind?: string, )
| 77 | } |
| 78 | |
| 79 | export function logPluginFetch( |
| 80 | source: PluginFetchSource, |
| 81 | urlOrSpec: string | undefined, |
| 82 | outcome: PluginFetchOutcome, |
| 83 | durationMs: number, |
| 84 | errorKind?: string, |
| 85 | ): void { |
| 86 | // String values are bounded enums / hostname-only — no code, no paths, |
| 87 | // no raw error messages. Same privacy envelope as tengu_web_fetch_host. |
| 88 | logEvent('tengu_plugin_remote_fetch', { |
| 89 | source: source as SafeString, |
| 90 | host: (urlOrSpec ? extractHost(urlOrSpec) : 'unknown') as SafeString, |
| 91 | is_official: urlOrSpec ? isOfficialRepo(urlOrSpec) : false, |
| 92 | outcome: outcome as SafeString, |
| 93 | duration_ms: Math.round(durationMs), |
| 94 | ...(errorKind && { error_kind: errorKind as SafeString }), |
| 95 | }) |
| 96 | } |
| 97 | |
| 98 | /** |
| 99 | * Classify an error into a stable bucket for the error_kind field. Keeps |
no test coverage detected