@jambonz/time-series 0.2.20 → 0.2.22

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/index.js CHANGED
@@ -22,7 +22,9 @@ const AlertType = {
22
22
  ACCOUNT_INACTIVE: 'account is inactive or suspended',
23
23
  PLAY_FILENOTFOUND: 'play-url-notfound',
24
24
  TTS_STREAMING_CONNECTION_FAILURE: 'tts-streaming-connection-failure',
25
- APPLICATION: 'alert-from-application'
25
+ KRISP_NOT_PROVISIONED: 'no-krisp',
26
+ APPLICATION: 'alert-from-application',
27
+ ERROR_UPDATING_CALL: 'error-updating-call'
26
28
  };
27
29
 
28
30
  const schemas = {
@@ -734,11 +736,19 @@ const writeAlerts = async(client, alerts) => {
734
736
  case AlertType.TTS_STREAMING_CONNECTION_FAILURE:
735
737
  message = `Failed to connect to tts streaming service at ${vendor}`;
736
738
  break;
739
+ case AlertType.ERROR_UPDATING_CALL:
740
+ message = `error updating call${detail ? `: ${detail}` : ''}`;
741
+ break;
737
742
  default:
738
743
  break;
739
744
  }
740
745
  }
741
- let fields = { message };
746
+ /* Never write an undefined/empty (or non-string) message field. In line
747
+ * protocol an undefined value serializes to the bare token `undefined`,
748
+ * which InfluxDB rejects ("invalid boolean") and fails the entire batch
749
+ * write — taking down every alert in the same flush. */
750
+ if (!message) message = alert_type || 'unknown alert';
751
+ let fields = { message: String(message) };
742
752
  if (target_sid) fields = Object.assign(fields, {target_sid});
743
753
  const obj = {measurement: 'alerts', fields: fields, tags: { alert_type, service_provider_sid, account_sid,
744
754
  ...(vendor && {vendor})}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/time-series",
3
- "version": "0.2.20",
3
+ "version": "0.2.22",
4
4
  "description": "write and query data to time series daetabase",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -214,6 +214,41 @@ test('write timeseries data', async(t) => {
214
214
  //console.log(result);
215
215
  t.ok(result.data.length === 15, 'queried alerts by service_provider_sid');
216
216
 
217
+ /* regression: an alert with no resolvable message must not poison the write.
218
+ * Previously `message: undefined` serialized to the bare token `undefined`
219
+ * in line protocol and InfluxDB rejected the whole batch ("invalid boolean").
220
+ * Distinct account_sids (a tag) so each is its own series and a shared
221
+ * service_provider_sid that doesn't collide with the counts above. */
222
+ await writeAlerts([
223
+ {
224
+ // ERROR_UPDATING_CALL with an undefined message + detail (the prod shape)
225
+ alert_type: AlertType.ERROR_UPDATING_CALL,
226
+ service_provider_sid: 'sp-guard',
227
+ account_sid: 'acct-guard-1',
228
+ message: undefined,
229
+ detail: 'cannot read property foo of undefined',
230
+ target_sid: 'call-guard'
231
+ },
232
+ {
233
+ // ERROR_UPDATING_CALL with neither message nor detail (bare default)
234
+ alert_type: AlertType.ERROR_UPDATING_CALL,
235
+ service_provider_sid: 'sp-guard',
236
+ account_sid: 'acct-guard-2'
237
+ },
238
+ {
239
+ // an unknown alert_type with no message must still produce a valid write
240
+ alert_type: 'some-unknown-alert-type',
241
+ service_provider_sid: 'sp-guard',
242
+ account_sid: 'acct-guard-3'
243
+ }
244
+ ]);
245
+ t.pass('wrote alerts with undefined/missing message without poisoning the batch');
246
+
247
+ result = await queryAlertsSP({service_provider_sid: 'sp-guard', page: 1, page_size: 25, days: 7});
248
+ t.ok(result.data.length === 3, 'all three guard alerts were stored (write was not rejected)');
249
+ t.ok(result.data.every((a) => typeof a.message === 'string' && a.message.length > 0),
250
+ 'every stored alert has a non-empty string message');
251
+
217
252
  result = await writeCallCount(
218
253
  {
219
254
  calls_in_progress: 49,