airbyte-faros-destination 0.18.0 → 0.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import { AirbyteRecord } from 'faros-airbyte-cdk';
2
+ import { DestinationModel, DestinationRecord, StreamContext } from '../converter';
3
+ import { CircleCIConverter } from './common';
4
+ export declare class Usage extends CircleCIConverter {
5
+ readonly destinationModels: ReadonlyArray<DestinationModel>;
6
+ private static readonly METRIC_DEFINITION_UID;
7
+ private static metricDefinitionWritten;
8
+ private readonly axios;
9
+ convert(record: AirbyteRecord, ctx: StreamContext): Promise<ReadonlyArray<DestinationRecord>>;
10
+ private downloadAndParseCsv;
11
+ private convertCsvToMetricValues;
12
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Usage = void 0;
37
+ const sync_1 = require("csv-parse/sync");
38
+ const faros_airbyte_cdk_1 = require("faros-airbyte-cdk");
39
+ const faros_js_client_1 = require("faros-js-client");
40
+ const zlib = __importStar(require("zlib"));
41
+ const common_1 = require("./common");
42
+ // Credit types from CircleCI usage CSV
43
+ const CREDIT_TYPES = [
44
+ 'COMPUTE_CREDITS',
45
+ 'DLC_CREDITS',
46
+ 'USER_CREDITS',
47
+ 'STORAGE_CREDITS',
48
+ 'NETWORK_CREDITS',
49
+ 'LEASE_CREDITS',
50
+ 'LEASE_OVERAGE_CREDITS',
51
+ 'IPRANGES_CREDITS',
52
+ 'TOTAL_CREDITS',
53
+ ];
54
+ class Usage extends common_1.CircleCIConverter {
55
+ constructor() {
56
+ super(...arguments);
57
+ this.destinationModels = [
58
+ 'faros_MetricDefinition',
59
+ 'faros_MetricValue',
60
+ ];
61
+ this.axios = (0, faros_js_client_1.makeAxiosInstanceWithRetry)();
62
+ }
63
+ async convert(record, ctx) {
64
+ var _a;
65
+ const usage = record.record.data;
66
+ let res = [];
67
+ // Write metric definition once
68
+ if (!Usage.metricDefinitionWritten) {
69
+ res.push({
70
+ model: 'faros_MetricDefinition',
71
+ record: {
72
+ uid: Usage.METRIC_DEFINITION_UID,
73
+ name: 'CircleCI Job Usage',
74
+ description: 'Credit usage metrics by CircleCI jobs',
75
+ valueType: {
76
+ category: 'Numeric',
77
+ detail: 'Credits used per job, by type',
78
+ },
79
+ scorecardCompatible: false,
80
+ },
81
+ });
82
+ Usage.metricDefinitionWritten = true;
83
+ }
84
+ // Only process completed exports with download URLs
85
+ if (usage.state !== 'completed' || !((_a = usage.download_urls) === null || _a === void 0 ? void 0 : _a.length)) {
86
+ ctx.logger.info(`Skipping usage export job ${usage.usage_export_job_id} because it is not completed or has no download URLs`);
87
+ return res;
88
+ }
89
+ // Process each download URL (CSV file)
90
+ for (const downloadUrl of usage.download_urls) {
91
+ ctx.logger.info(`Processing CSV from job ${usage.usage_export_job_id}`);
92
+ try {
93
+ const csvData = await this.downloadAndParseCsv(downloadUrl, ctx);
94
+ const metricValues = this.convertCsvToMetricValues(csvData);
95
+ res = res.concat(metricValues);
96
+ }
97
+ catch (error) {
98
+ ctx.logger.error(`Failed to process CSV from job ${usage.usage_export_job_id} at ${downloadUrl}: ${error.message}`);
99
+ }
100
+ }
101
+ return res;
102
+ }
103
+ async downloadAndParseCsv(url, ctx) {
104
+ try {
105
+ // Download the CSV.gz file
106
+ const response = await this.axios.get(url, {
107
+ responseType: 'arraybuffer',
108
+ });
109
+ const buffer = Buffer.from(response.data);
110
+ // Decompress the gzipped CSV
111
+ const csvContent = zlib.gunzipSync(buffer).toString('utf8');
112
+ // Parse the CSV
113
+ const records = (0, sync_1.parse)(csvContent, {
114
+ columns: true,
115
+ skip_empty_lines: true,
116
+ trim: true,
117
+ });
118
+ ctx.logger.debug(`Parsed ${records.length} usage records from CSV`);
119
+ return records;
120
+ }
121
+ catch (error) {
122
+ throw new Error(`Failed to download/parse CSV: ${error.message}`);
123
+ }
124
+ }
125
+ convertCsvToMetricValues(records) {
126
+ const metricValues = [];
127
+ for (const record of records) {
128
+ const computedAt = (0, faros_airbyte_cdk_1.toDate)(record.JOB_RUN_DATE);
129
+ if (!computedAt) {
130
+ continue; // Skip records with invalid dates
131
+ }
132
+ // Create a metric value for each credit type
133
+ for (const creditType of CREDIT_TYPES) {
134
+ const value = record[creditType];
135
+ if (value && !isNaN(parseFloat(value)) && isFinite(parseFloat(value))) {
136
+ metricValues.push({
137
+ model: 'faros_MetricValue',
138
+ record: {
139
+ uid: `${record.JOB_ID}_${creditType.toLowerCase()}`,
140
+ value: value,
141
+ computedAt: computedAt.toISOString(),
142
+ definition: { uid: Usage.METRIC_DEFINITION_UID },
143
+ },
144
+ });
145
+ }
146
+ }
147
+ }
148
+ return metricValues;
149
+ }
150
+ }
151
+ exports.Usage = Usage;
152
+ Usage.METRIC_DEFINITION_UID = 'circleci_job_usage';
153
+ Usage.metricDefinitionWritten = false;
154
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/converters/circleci/usage.ts"],"names":[],"mappings":"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"}