vtb-appit 0.1.13 → 0.1.14
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.
- package/appit.js +87 -124
- package/package.json +1 -1
- package/tracing-utils.js +46 -0
package/appit.js
CHANGED
|
@@ -4,9 +4,7 @@ const https = require('https');
|
|
|
4
4
|
const FormData = require('form-data');
|
|
5
5
|
const axios = require('axios');
|
|
6
6
|
require('./tracing');
|
|
7
|
-
const {
|
|
8
|
-
|
|
9
|
-
const tracer = trace.getTracer('vtb-appit', '1.0.0');
|
|
7
|
+
const { withTracing, addEvent } = require('./tracing-utils');
|
|
10
8
|
//
|
|
11
9
|
// async function simulateWork() {
|
|
12
10
|
// return tracer.startActiveSpan('simulate-work', async (span) => {
|
|
@@ -87,139 +85,104 @@ class Appit {
|
|
|
87
85
|
}
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
async exec()
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
parentSpan.addEvent('Sync process started');
|
|
96
|
-
const errors = [];
|
|
88
|
+
async exec() {
|
|
89
|
+
return await withTracing('appit-sync', async () => {
|
|
90
|
+
this.log('info', 'Starting sync process');
|
|
91
|
+
addEvent('Sync process started');
|
|
92
|
+
const errors = [];
|
|
97
93
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
span.addEvent('Start login');
|
|
94
|
+
await this.performLogin();
|
|
95
|
+
if (!this.token) return false;
|
|
101
96
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
this.log('info', '
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
await this.fetchProfile();
|
|
98
|
+
|
|
99
|
+
if(this.options && this.options.tsData) {
|
|
100
|
+
try {
|
|
101
|
+
this.transformer.tsData = await this.transformer.tsGetData();
|
|
102
|
+
this.log('info', 'TS data loaded successfully');
|
|
103
|
+
} catch(e) {
|
|
104
|
+
this.log('error', 'Failed to load TS data', e.message);
|
|
105
|
+
errors.push({ step: 'tsData', error: e.message });
|
|
110
106
|
}
|
|
111
|
-
} catch (error) {
|
|
112
|
-
span.recordException(error);
|
|
113
|
-
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
114
|
-
} finally{
|
|
115
|
-
span.end();
|
|
116
107
|
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if(!this.token) return;
|
|
120
|
-
|
|
121
|
-
await tracer.startActiveSpan('appit-profile', async (span) => {
|
|
122
|
-
try {
|
|
123
|
-
this.transformer.profile = await this.fetchProfile();
|
|
124
|
-
console.log(this.transformer.profile);
|
|
125
|
-
this.log('info', 'Profile fetched successfully');
|
|
126
108
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
109
|
+
if(this.options && this.options.tsDocuments) {
|
|
110
|
+
try {
|
|
111
|
+
this.transformer.tsDocuments = await this.transformer.tsGetDocuments();
|
|
112
|
+
this.log('info', 'TS documents loaded successfully');
|
|
113
|
+
} catch(e) {
|
|
114
|
+
this.log('error', 'Failed to load TS documents', e.message);
|
|
115
|
+
errors.push({ step: 'tsDocuments', error: e.message });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const steps = [
|
|
120
|
+
{ name: 'excursion', fn: () => this.excursion() },
|
|
121
|
+
{ name: 'labels', fn: () => this.labels() },
|
|
122
|
+
{ name: 'ships', fn: () => this.ships() },
|
|
123
|
+
{ name: 'places', fn: () => this.places() },
|
|
124
|
+
{ name: 'organizations', fn: () => this.organizations() },
|
|
125
|
+
{ name: 'members', fn: () => this.members() },
|
|
126
|
+
{ name: 'travelInfo', fn: () => this.travelInfo() },
|
|
127
|
+
{ name: 'accommodations', fn: () => this.accommodations() },
|
|
128
|
+
{ name: 'destinations', fn: () => this.destinations() },
|
|
129
|
+
{ name: 'schemes', fn: () => this.schemes() },
|
|
130
|
+
{ name: 'flights', fn: () => this.flights() },
|
|
131
|
+
{ name: 'flightImages', fn: () => this.flightImages() },
|
|
132
|
+
{ name: 'contacts', fn: () => this.contacts() },
|
|
133
|
+
{ name: 'documents', fn: () => this.documents() },
|
|
134
|
+
{ name: 'homescreen', fn: () => this.homescreen() },
|
|
135
|
+
{ name: 'menu', fn: () => this.menu() },
|
|
136
|
+
{ name: 'settings', fn: () => this.settings() },
|
|
137
|
+
{ name: 'notifications', fn: () => this.notifications() }
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
for(const step of steps) {
|
|
141
|
+
try {
|
|
142
|
+
this.log('info', `Processing ${step.name}...`);
|
|
143
|
+
await step.fn();
|
|
144
|
+
this.log('info', `✓ ${step.name} completed successfully`);
|
|
145
|
+
} catch(error) {
|
|
146
|
+
this.log('error', `✗ ${step.name} failed`, error.message);
|
|
147
|
+
this.saveErrorToHistory(`Step ${step.name} failed`, '', error.message);
|
|
148
|
+
// Continue with next step instead of failing entirely
|
|
149
|
+
}
|
|
134
150
|
}
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
if(this.options && this.options.tsData) {
|
|
138
|
-
try {
|
|
139
|
-
this.transformer.tsData = await this.transformer.tsGetData();
|
|
140
|
-
this.log('info', 'TS data loaded successfully');
|
|
141
|
-
} catch(e) {
|
|
142
|
-
this.log('error', 'Failed to load TS data', e.message);
|
|
143
|
-
errors.push({ step: 'tsData', error: e.message });
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if(this.options && this.options.tsDocuments) {
|
|
148
|
-
try {
|
|
149
|
-
this.transformer.tsDocuments = await this.transformer.tsGetDocuments();
|
|
150
|
-
this.log('info', 'TS documents loaded successfully');
|
|
151
|
-
} catch(e) {
|
|
152
|
-
this.log('error', 'Failed to load TS documents', e.message);
|
|
153
|
-
errors.push({ step: 'tsDocuments', error: e.message });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const steps = [
|
|
158
|
-
{ name: 'excursion', fn: () => this.excursion() },
|
|
159
|
-
{ name: 'labels', fn: () => this.labels() },
|
|
160
|
-
{ name: 'ships', fn: () => this.ships() },
|
|
161
|
-
{ name: 'places', fn: () => this.places() },
|
|
162
|
-
{ name: 'organizations', fn: () => this.organizations() },
|
|
163
|
-
{ name: 'members', fn: () => this.members() },
|
|
164
|
-
{ name: 'travelInfo', fn: () => this.travelInfo() },
|
|
165
|
-
{ name: 'accommodations', fn: () => this.accommodations() },
|
|
166
|
-
{ name: 'destinations', fn: () => this.destinations() },
|
|
167
|
-
{ name: 'schemes', fn: () => this.schemes() },
|
|
168
|
-
{ name: 'flights', fn: () => this.flights() },
|
|
169
|
-
{ name: 'flightImages', fn: () => this.flightImages() },
|
|
170
|
-
{ name: 'contacts', fn: () => this.contacts() },
|
|
171
|
-
{ name: 'documents', fn: () => this.documents() },
|
|
172
|
-
{ name: 'homescreen', fn: () => this.homescreen() },
|
|
173
|
-
{ name: 'menu', fn: () => this.menu() },
|
|
174
|
-
{ name: 'settings', fn: () => this.settings() },
|
|
175
|
-
{ name: 'notifications', fn: () => this.notifications() }
|
|
176
|
-
];
|
|
177
|
-
|
|
178
|
-
for(const step of steps) {
|
|
179
|
-
try {
|
|
180
|
-
this.log('info', `Processing ${step.name}...`);
|
|
181
|
-
await step.fn();
|
|
182
|
-
this.log('info', `✓ ${step.name} completed successfully`);
|
|
183
|
-
} catch(error) {
|
|
184
|
-
this.log('error', `✗ ${step.name} failed`, error.message);
|
|
185
|
-
this.saveErrorToHistory(`Step ${step.name} failed`, '', error.message);
|
|
186
|
-
// Continue with next step instead of failing entirely
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
151
|
|
|
190
|
-
|
|
191
|
-
|
|
152
|
+
this.history.updatedAt = new Date().getTime();
|
|
153
|
+
this.history.status = (!this.history.errors || this.history.errors.length === 0) ? 'completed' : 'completed_with_errors';
|
|
192
154
|
|
|
193
|
-
|
|
155
|
+
fs.writeFileSync(this.historyPath, JSON.stringify(this.history, null, 2));
|
|
194
156
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
parentSpan.setAttributes({ 'sync.errors.count': errors.length });
|
|
204
|
-
parentSpan.setStatus({ code: SpanStatusCode.OK });
|
|
205
|
-
return true; // Still return true as we completed what we could
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
} catch(error) {
|
|
209
|
-
this.log('error', 'Critical error during sync', error);
|
|
210
|
-
this.history.status = 'failed';
|
|
211
|
-
this.history.criticalError = error.message;
|
|
212
|
-
this.history.updatedAt = new Date().getTime();
|
|
213
|
-
this.saveHistoryIncremental();
|
|
214
|
-
parentSpan.recordException(error);
|
|
215
|
-
parentSpan.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
216
|
-
return false;
|
|
217
|
-
} finally {
|
|
218
|
-
parentSpan.end();
|
|
157
|
+
if(errors.length === 0) {
|
|
158
|
+
this.log('info', 'Sync completed successfully');
|
|
159
|
+
addEvent('Sync completed successfully');
|
|
160
|
+
return true;
|
|
161
|
+
} else {
|
|
162
|
+
this.log('warn', `Sync completed with ${errors.length} errors`, errors);
|
|
163
|
+
addEvent(`Sync completed with ${errors.length} errors`);
|
|
164
|
+
return true; // Still return true as we completed what we could
|
|
219
165
|
}
|
|
220
|
-
});
|
|
166
|
+
})();
|
|
221
167
|
}
|
|
222
168
|
|
|
169
|
+
performLogin = withTracing('appit-login', async () => {
|
|
170
|
+
addEvent('Start login');
|
|
171
|
+
if (!await this.login()) {
|
|
172
|
+
this.log('info', 'Login failed');
|
|
173
|
+
throw new Error('Login failed');
|
|
174
|
+
}
|
|
175
|
+
this.log('info', 'Login successful');
|
|
176
|
+
addEvent('Login successful');
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
fetchProfile = withTracing('appit-profile', async () => {
|
|
180
|
+
this.transformer.profile = await this.fetchProfile();
|
|
181
|
+
console.log(this.transformer.profile);
|
|
182
|
+
this.log('info', 'Profile fetched successfully');
|
|
183
|
+
addEvent('Profile fetched successfully');
|
|
184
|
+
});
|
|
185
|
+
|
|
223
186
|
async labels()
|
|
224
187
|
{
|
|
225
188
|
const labels = this.transformer.labels();
|
package/package.json
CHANGED
package/tracing-utils.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const { trace, SpanStatusCode } = require('@opentelemetry/api');
|
|
2
|
+
|
|
3
|
+
const tracer = trace.getTracer('vtb-appit', '1.0.0');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Wraps an async function with tracing
|
|
7
|
+
* @param {string} spanName - Name of the span
|
|
8
|
+
* @param {Function} fn - Async function to wrap
|
|
9
|
+
* @param {Object} attributes - Optional attributes to add to span
|
|
10
|
+
* @returns {Function} Wrapped function
|
|
11
|
+
*/
|
|
12
|
+
function withTracing(spanName, fn, attributes = {}) {
|
|
13
|
+
return async (...args) => {
|
|
14
|
+
return await tracer.startActiveSpan(spanName, async (span) => {
|
|
15
|
+
try {
|
|
16
|
+
if (Object.keys(attributes).length > 0) {
|
|
17
|
+
span.setAttributes(attributes);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const result = await fn(...args);
|
|
21
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
22
|
+
return result;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
span.recordException(error);
|
|
25
|
+
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
|
|
26
|
+
throw error;
|
|
27
|
+
} finally {
|
|
28
|
+
span.end();
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Adds an event to the current active span
|
|
36
|
+
* @param {string} message - Event message
|
|
37
|
+
* @param {Object} attributes - Optional attributes
|
|
38
|
+
*/
|
|
39
|
+
function addEvent(message, attributes = {}) {
|
|
40
|
+
const span = trace.getActiveSpan();
|
|
41
|
+
if (span) {
|
|
42
|
+
span.addEvent(message, attributes);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = { withTracing, addEvent, tracer };
|