Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1import _ from 'lodash';
2import { type ReadonlyDeep } from 'type-fest';
3
4import { type Dependencies } from '../../iocContainer/index.js';
5import { inject } from '../../iocContainer/utils.js';
6import { type ConditionSetWithResult } from '../../models/rules/RuleModel.js';
7import { type RuleEnvironment } from '../../rule_engine/RuleEngine.js';
8import { fromCorrelationId } from '../../utils/correlationIds.js';
9import { jsonStringifyUnstable } from '../../utils/encoding.js';
10
11import '../../utils/errors.js';
12
13import {
14 isFullSubmission,
15 type RuleInput,
16} from '../../rule_engine/RuleEvaluator.js';
17import { getUtcDateOnlyString } from '../../utils/time.js';
18import {
19 pickConditionPropsToLog,
20 type RuleExecutionCorrelationId,
21} from './ruleExecutionLoggingUtils.js';
22
23type RuleExecutionData = ReadonlyDeep<{
24 orgId: string;
25 rule: {
26 id: string;
27 name: string;
28 version: string;
29 tags: string[];
30 };
31 ruleInput: RuleInput;
32 policies: { id: string; name: string }[];
33 environment: RuleEnvironment;
34 result: ConditionSetWithResult;
35 passed: boolean;
36 correlationId: RuleExecutionCorrelationId;
37}>;
38
39class RuleExecutionLogger {
40 constructor(
41 private readonly analytics: Dependencies['DataWarehouseAnalytics'],
42 ) {}
43 async logRuleExecutions(
44 executions: readonly RuleExecutionData[],
45 sync?: boolean,
46 ) {
47 const now = new Date();
48 await this.analytics.bulkWrite(
49 'RULE_EXECUTIONS',
50 executions.map((data) => ({
51 ds: getUtcDateOnlyString(now),
52 ts: now.valueOf(),
53 org_id: data.orgId,
54 item_id: data.ruleInput.itemId,
55 item_type_id: data.ruleInput.itemType.id,
56 item_type_kind: data.ruleInput.itemType.kind,
57 ...(isFullSubmission(data.ruleInput)
58 ? {
59 item_submission_id: data.ruleInput.submissionId,
60 item_data: jsonStringifyUnstable(data.ruleInput.data),
61 item_type_name: data.ruleInput.itemType.name,
62 item_creator_id: data.ruleInput.creator?.id,
63 item_creator_type_id: data.ruleInput.creator?.typeId,
64 item_type_schema: jsonStringifyUnstable(
65 data.ruleInput.itemType.schema,
66 ),
67 item_type_schema_field_roles:
68 data.ruleInput.itemType.schemaFieldRoles,
69 item_type_schema_variant: data.ruleInput.itemType.schemaVariant,
70 item_type_version: data.ruleInput.itemType.version,
71 }
72 : {}),
73 rule: data.rule.name,
74 rule_id: data.rule.id,
75 rule_version: data.rule.version,
76 tags: data.rule.tags,
77 policy_ids: data.policies.map((it) => it.id),
78 policy_names: data.policies.map((it) => it.name),
79 environment: data.environment,
80 correlation_id: fromCorrelationId(data.correlationId),
81 result: jsonStringifyUnstable(pickConditionPropsToLog(data.result)),
82 passed: data.passed,
83 })) as any,
84 { batchTimeout: sync ? 0 : undefined },
85 );
86 }
87}
88
89export default inject(['DataWarehouseAnalytics'], RuleExecutionLogger);
90export { type RuleExecutionLogger };