@jambonz/time-series 0.2.21 → 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
@@ -23,7 +23,8 @@ const AlertType = {
23
23
  PLAY_FILENOTFOUND: 'play-url-notfound',
24
24
  TTS_STREAMING_CONNECTION_FAILURE: 'tts-streaming-connection-failure',
25
25
  KRISP_NOT_PROVISIONED: 'no-krisp',
26
- APPLICATION: 'alert-from-application'
26
+ APPLICATION: 'alert-from-application',
27
+ ERROR_UPDATING_CALL: 'error-updating-call'
27
28
  };
28
29
 
29
30
  const schemas = {
@@ -735,11 +736,19 @@ const writeAlerts = async(client, alerts) => {
735
736
  case AlertType.TTS_STREAMING_CONNECTION_FAILURE:
736
737
  message = `Failed to connect to tts streaming service at ${vendor}`;
737
738
  break;
739
+ case AlertType.ERROR_UPDATING_CALL:
740
+ message = `error updating call${detail ? `: ${detail}` : ''}`;
741
+ break;
738
742
  default:
739
743
  break;
740
744
  }
741
745
  }
742
- 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) };
743
752
  if (target_sid) fields = Object.assign(fields, {target_sid});
744
753
  const obj = {measurement: 'alerts', fields: fields, tags: { alert_type, service_provider_sid, account_sid,
745
754
  ...(vendor && {vendor})}};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jambonz/time-series",
3
- "version": "0.2.21",
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,