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