(raw json.RawMessage, fileMeta *models.QDevS3FileMeta, identityClient UserDisplayNameResolver, cache *sync.Map)
| 400 | } |
| 401 | |
| 402 | func parseCompletionRecord(raw json.RawMessage, fileMeta *models.QDevS3FileMeta, identityClient UserDisplayNameResolver, cache *sync.Map) (*models.QDevCompletionLog, error) { |
| 403 | var record completionLogRecord |
| 404 | if err := json.Unmarshal(raw, &record); err != nil { |
| 405 | return nil, err |
| 406 | } |
| 407 | |
| 408 | if record.Request == nil || record.Response == nil { |
| 409 | return nil, nil |
| 410 | } |
| 411 | |
| 412 | ts, err := time.Parse(time.RFC3339Nano, record.Request.Timestamp) |
| 413 | if err != nil { |
| 414 | ts = time.Now() |
| 415 | } |
| 416 | |
| 417 | userId := normalizeUserId(record.Request.UserID) |
| 418 | return &models.QDevCompletionLog{ |
| 419 | ConnectionId: fileMeta.ConnectionId, |
| 420 | ScopeId: fileMeta.ScopeId, |
| 421 | RequestId: record.Response.RequestID, |
| 422 | UserId: userId, |
| 423 | DisplayName: cachedResolveDisplayName(userId, identityClient, cache), |
| 424 | Timestamp: ts, |
| 425 | FileName: record.Request.FileName, |
| 426 | FileExtension: filepath.Ext(record.Request.FileName), |
| 427 | HasCustomization: record.Request.CustomizationArn != nil && *record.Request.CustomizationArn != "", |
| 428 | CompletionsCount: len(record.Response.Completions), |
| 429 | LeftContextLength: len(record.Request.LeftContext), |
| 430 | RightContextLength: len(record.Request.RightContext), |
| 431 | }, nil |
| 432 | } |
| 433 | |
| 434 | // normalizeUserId strips the "d-{directoryId}." prefix from Identity Center user IDs |
| 435 | // so that logging user IDs match the short UUID format used in user-report CSVs. |
no test coverage detected