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.
Files changed (3) hide show
  1. package/appit.js +87 -124
  2. package/package.json +1 -1
  3. 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 { trace, SpanStatusCode } = require('@opentelemetry/api');
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
- return await tracer.startActiveSpan('appit-sync', async (parentSpan) => {
93
- try {
94
- this.log('info', 'Starting sync process');
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
- await tracer.startActiveSpan('appit-login', async (span) => {
99
- try {
100
- span.addEvent('Start login');
94
+ await this.performLogin();
95
+ if (!this.token) return false;
101
96
 
102
- if(!await this.login()) {
103
- this.log('info', 'Login failed');
104
- span.setStatus({ code: SpanStatusCode.ERROR, message: 'Login failed' });
105
- return false;
106
- } else {
107
- this.log('info', 'Login successful');
108
- span.addEvent('Login successful');
109
- span.setStatus({ code: SpanStatusCode.OK });
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
- span.addEvent('Profile fetched successfully');
128
- span.setStatus({ code: SpanStatusCode.OK });
129
- } catch(error) {
130
- span.recordException(error);
131
- span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
132
- } finally {
133
- span.end();
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
- this.history.updatedAt = new Date().getTime();
191
- this.history.status = (!this.history.errors || this.history.errors.length === 0) ? 'completed' : 'completed_with_errors';
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
- fs.writeFileSync(this.historyPath, JSON.stringify(this.history, null, 2));
155
+ fs.writeFileSync(this.historyPath, JSON.stringify(this.history, null, 2));
194
156
 
195
- if(errors.length === 0) {
196
- this.log('info', 'Sync completed successfully');
197
- parentSpan.addEvent('Sync completed successfully');
198
- parentSpan.setStatus({ code: SpanStatusCode.OK });
199
- return true;
200
- } else {
201
- this.log('warn', `Sync completed with ${errors.length} errors`, errors);
202
- parentSpan.addEvent(`Sync completed with ${errors.length} errors`);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vtb-appit",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {},
@@ -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 };