@mhubcloud/tms_core 3.8.0-beta.6 → 3.8.0-beta.8

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 (2) hide show
  1. package/dist/index.js +102 -72
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -53,6 +53,7 @@ var import_service_bus = require("@azure/service-bus");
53
53
  // src/utils/utils.ts
54
54
  var utils_exports = {};
55
55
  __export(utils_exports, {
56
+ DestinationError: () => DestinationError,
56
57
  EventPublisherBase: () => EventPublisherBase,
57
58
  encodeEmail: () => encodeEmail,
58
59
  extractAdCode: () => extractAdCode,
@@ -78,9 +79,13 @@ var appInsights = __toESM(require("applicationinsights"));
78
79
  var import_redis = require("redis");
79
80
  var client;
80
81
  async function getRedisClient() {
82
+ const redisUrl = process.env["RedisUrl"];
83
+ if (!redisUrl) {
84
+ return null;
85
+ }
81
86
  if (!client) {
82
87
  client = (0, import_redis.createClient)({
83
- url: `rediss://${process.env["RedisUrl"]}`,
88
+ url: `rediss://${redisUrl}`,
84
89
  password: process.env["RedisPassword"],
85
90
  socket: { tls: true }
86
91
  });
@@ -118,14 +123,40 @@ var EventPublisherBase = class {
118
123
  };
119
124
  async function logRedisEvent(key) {
120
125
  const redis = await getRedisClient();
121
- if (!redis) return;
122
- await redis.hIncrBy(key, "count", 1);
123
- await redis.expire(key, 660);
126
+ if (!redis) {
127
+ return;
128
+ }
129
+ await redis.multi().hIncrBy(key, "count", 1).expire(key, 660).exec();
124
130
  }
125
- function logAggregatedMetric({ prefix, name, dimensions }) {
131
+ var DestinationError = class _DestinationError extends Error {
132
+ metricType;
133
+ constructor(message, metricType) {
134
+ super(message);
135
+ this.name = "DestinationError";
136
+ this.metricType = metricType;
137
+ }
138
+ static fromResponse(message, status) {
139
+ const metricType = status === 408 || status === 429 || status >= 500 ? "PlatformError" : "RequestError";
140
+ return new _DestinationError(message, metricType);
141
+ }
142
+ static fromNetworkFailure(error) {
143
+ const message = error instanceof Error ? error.message : String(error);
144
+ return new _DestinationError(message, "PlatformError");
145
+ }
146
+ };
147
+ function logAggregatedMetric({
148
+ prefix,
149
+ name,
150
+ dimensions
151
+ }) {
126
152
  const windowStart = Math.floor(Date.now() / 6e4) * 6e4;
127
- const key = dimensions ? `${prefix}:${windowStart}:${dimensions}:${name}` : `${prefix}:${windowStart}:${name}`;
128
- logRedisEvent(key);
153
+ let key = "tms:";
154
+ key += dimensions ? `${prefix}:${windowStart}:${dimensions}:${name}` : `${prefix}:${windowStart}:${name}`;
155
+ void logRedisEvent(key).catch((error) => {
156
+ if (error instanceof Error) {
157
+ logException(new Error(`Metric log error: ${error.message}`));
158
+ }
159
+ });
129
160
  }
130
161
  function logMetric(name, value, properties) {
131
162
  aiClient?.trackMetric({
@@ -144,13 +175,15 @@ function logMessage(level, message, properties) {
144
175
  });
145
176
  }
146
177
  function logEvent(publisher2, event, region, status, payload, id) {
147
- if (!process.env["DisableMetrics"]) {
148
- const metricRegion = process.env["DisableMetricRegionLogging"] ? "default" : region;
149
- const name = status >= 200 && status < 400 ? "DispatchSuccess" : "DispatchFailure";
150
- logAggregatedMetric({ prefix: "events", dimensions: `${metricRegion}:${publisher2}:${event}`, name });
178
+ if (process.env.DisableMetrics !== "true" && status >= 200 && status < 400) {
179
+ const metricRegion = process.env.DisableMetricRegionLogging === "true" ? "default" : region;
180
+ logAggregatedMetric({
181
+ prefix: "events",
182
+ dimensions: `${metricRegion}:${publisher2}:${event}`,
183
+ name: "Dispatch"
184
+ });
151
185
  }
152
- ;
153
- if (!process.env["DisableTraces"]) {
186
+ if (process.env.DisableTraces !== "true") {
154
187
  let properties = {
155
188
  publisher: publisher2,
156
189
  event,
@@ -163,18 +196,21 @@ function logEvent(publisher2, event, region, status, payload, id) {
163
196
  properties = removeUndefined(properties);
164
197
  logMessage(1, message, properties);
165
198
  }
166
- ;
167
199
  }
168
- function logException(exception, publisher2) {
169
- if (!process.env["DisableMetrics"]) {
170
- const message = exception.message.split(".")[0]?.substring(0, 100)?.replace(/:/g, "") ?? "Error";
171
- logAggregatedMetric({ prefix: "errors", dimensions: `${publisher2 ?? "Other"}:${exception.name}`, name: message });
200
+ function logException(exception, publisher2, errorType = "InternalError") {
201
+ if (process.env.DisableMetrics !== "true") {
202
+ logAggregatedMetric({
203
+ prefix: "errors",
204
+ dimensions: publisher2 ?? "Other",
205
+ name: errorType
206
+ });
172
207
  }
173
- ;
174
- if (!process.env["DisableTraces"]) {
175
- aiClient?.trackException({ exception });
208
+ if (process.env.DisableTraces !== "true") {
209
+ aiClient?.trackException({
210
+ exception,
211
+ properties: { publisher: publisher2, errorType }
212
+ });
176
213
  }
177
- ;
178
214
  }
179
215
  function logMilestone(name) {
180
216
  logAggregatedMetric({ prefix: "milestones", name });
@@ -318,29 +354,21 @@ async function handlePlatformRequest({
318
354
  // eslint-disable-next-line @typescript-eslint/naming-convention
319
355
  headers: { ...requestOptions.headers }
320
356
  };
321
- let rawPlatformResponse;
322
- try {
323
- rawPlatformResponse = await fetch(fullUrl, fetchRequestOptions);
324
- } catch (e) {
325
- logEvent(
326
- source,
327
- event.event,
328
- event.region,
329
- 0,
330
- requestOptions.method === "POST" ? JSON.stringify(requestOptions.body) : query,
331
- event.id
332
- );
333
- throw e;
357
+ const rawPlatformResponse = await fetch(fullUrl, fetchRequestOptions);
358
+ if (process.env.PUBLISHER_TESTURL) {
359
+ await handleTestRequest({
360
+ fetchRequestOptions,
361
+ fullUrl,
362
+ query,
363
+ rawPlatformResponse
364
+ });
334
365
  }
335
- if (rawPlatformResponse) {
336
- if (process.env.PUBLISHER_TESTURL) {
337
- await handleTestRequest({
338
- fetchRequestOptions,
339
- fullUrl,
340
- query,
341
- rawPlatformResponse
342
- });
343
- }
366
+ if (!rawPlatformResponse.ok) {
367
+ throw DestinationError.fromResponse(
368
+ `HTTP Error code: ${rawPlatformResponse.status}, event: ${event.event}, region: ${event.region}, body: ${await rawPlatformResponse.text()}`,
369
+ rawPlatformResponse.status
370
+ );
371
+ } else {
344
372
  logEvent(
345
373
  source,
346
374
  event.event,
@@ -349,11 +377,6 @@ async function handlePlatformRequest({
349
377
  requestOptions.method === "POST" ? JSON.stringify(requestOptions.body) : query,
350
378
  event.id
351
379
  );
352
- if (!rawPlatformResponse.ok) {
353
- throw new Error(
354
- `HTTP Error code: ${rawPlatformResponse.status}, event: ${event.event}, region: ${event.region}, body: ${await rawPlatformResponse.text()}`
355
- );
356
- }
357
380
  }
358
381
  }
359
382
  async function handleTestRequest(params) {
@@ -381,7 +404,7 @@ function formatError(error) {
381
404
  if (error instanceof Error) {
382
405
  formattedError = error;
383
406
  if (error.cause) {
384
- formattedError.message = `${error.message} Cause: ${error.cause.toString()}`;
407
+ formattedError.message = `${error.message} Cause: ${String(error.cause)}`;
385
408
  } else {
386
409
  formattedError.message = error.message;
387
410
  }
@@ -638,13 +661,14 @@ async function defaultPublisher(azureFunctionContext, serviceBusMessage, source,
638
661
  if (result.status === "rejected") {
639
662
  if (result.reason instanceof Error) {
640
663
  const formattedError = formatError(result.reason);
641
- logException(new Error(formattedError.message), source);
664
+ const errorType = result.reason instanceof DestinationError ? result.reason.metricType : "InternalError";
665
+ logException(formattedError, source, errorType);
642
666
  throw formattedError;
643
667
  } else {
644
668
  const formattedError = formatError(
645
669
  typeof result.reason === "object" ? JSON.stringify(result.reason) : result.reason
646
670
  );
647
- logException(new Error(formattedError.message), source);
671
+ logException(formattedError, source, "InternalError");
648
672
  throw formattedError;
649
673
  }
650
674
  }
@@ -900,17 +924,17 @@ var googleAds = {
900
924
  error = responseJson.error.message;
901
925
  } else {
902
926
  status = 200;
927
+ logEvent(
928
+ this.source,
929
+ event.event,
930
+ event.region,
931
+ status,
932
+ requestOptions.body,
933
+ event.id
934
+ );
903
935
  }
904
- logEvent(
905
- this.source,
906
- event.event,
907
- event.region,
908
- status,
909
- requestOptions.body,
910
- event.id
911
- );
912
936
  if (error) {
913
- throw new Error(error);
937
+ throw DestinationError.fromResponse(error, response.status);
914
938
  }
915
939
  },
916
940
  async getToken(config) {
@@ -941,7 +965,10 @@ var googleAds = {
941
965
  }
942
966
  );
943
967
  if (!tokenResponse.ok) {
944
- throw new Error("Access token fetch failed");
968
+ throw DestinationError.fromResponse(
969
+ "Access token fetch failed",
970
+ tokenResponse.status
971
+ );
945
972
  }
946
973
  const parsedTokenResponse = await tokenResponse.json();
947
974
  const createdAt = Date.now();
@@ -1059,17 +1086,17 @@ var microsoftAds = {
1059
1086
  error = message;
1060
1087
  } else {
1061
1088
  status = 200;
1089
+ logEvent(
1090
+ this.source,
1091
+ event.event,
1092
+ event.region,
1093
+ status,
1094
+ requestOptions.body,
1095
+ event.id
1096
+ );
1062
1097
  }
1063
- logEvent(
1064
- this.source,
1065
- event.event,
1066
- event.region,
1067
- status,
1068
- requestOptions.body,
1069
- event.id
1070
- );
1071
1098
  if (error) {
1072
- throw new Error(error);
1099
+ throw DestinationError.fromResponse(error, response.status);
1073
1100
  }
1074
1101
  } else {
1075
1102
  throw new Error("Invalid config for platform " + this.source);
@@ -1100,7 +1127,10 @@ var microsoftAds = {
1100
1127
  }
1101
1128
  );
1102
1129
  if (!tokenResponse.ok) {
1103
- throw new Error("Access token fetch failed");
1130
+ throw DestinationError.fromResponse(
1131
+ "Access token fetch failed",
1132
+ tokenResponse.status
1133
+ );
1104
1134
  }
1105
1135
  const parsedTokenResponse = await tokenResponse.json();
1106
1136
  const createdAt = Date.now();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhubcloud/tms_core",
3
- "version": "3.8.0-beta.6",
3
+ "version": "3.8.0-beta.8",
4
4
  "description": "Core function for mHub Cloud TMS publishers",
5
5
  "homepage": "https://mhubcloud.com/",
6
6
  "license": "Apache 2.0",