@digitraffic/common 2023.3.17-1 → 2023.3.21-1

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.
@@ -1,7 +1,7 @@
1
1
  import { DtLogger } from "../../runtime/dt-logger";
2
2
  import { LambdaResponse } from "../../types/lambda-response";
3
- export type LoggingHandler = (method: () => Promise<LambdaResponse>, logger: DtLogger) => Promise<LambdaResponse>;
4
- export type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
3
+ export declare type LoggingHandler = (method: () => Promise<LambdaResponse>, logger: DtLogger) => Promise<LambdaResponse>;
4
+ export declare type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
5
5
  /**
6
6
  * Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
7
7
  * with the defaults:
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createJsonLoggingHandler = exports.HandlerFactory = void 0;
4
+ const utils_1 = require("../../../utils/utils");
5
+ const functionName = (0, utils_1.getEnvVariableOrElse)("AWS_LAMBDA_FUNCTION_NAME", "test");
4
6
  /**
5
7
  * Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
6
8
  * with the defaults:
@@ -18,7 +20,7 @@ class HandlerFactory {
18
20
  return await method();
19
21
  }
20
22
  finally {
21
- console.info("method=%s.handler tookMs=%d", process.env.AWS_LAMBDA_FUNCTION_NAME, Date.now() - start);
23
+ console.info("method=%s.handler tookMs=%d", functionName, Date.now() - start);
22
24
  }
23
25
  };
24
26
  this.errorHandler = (error) => {
@@ -54,7 +56,10 @@ function createJsonLoggingHandler() {
54
56
  return await method();
55
57
  }
56
58
  finally {
57
- logger.info({ tookMs: Date.now() - start });
59
+ logger.info({
60
+ method: `${functionName}.handler`,
61
+ tookMs: Date.now() - start,
62
+ });
58
63
  }
59
64
  };
60
65
  }
@@ -1,7 +1,7 @@
1
1
  import { IntegrationResponse, LambdaIntegration } from "aws-cdk-lib/aws-apigateway";
2
2
  import { IFunction } from "aws-cdk-lib/aws-lambda";
3
3
  import { MediaType } from "../../types/mediatypes";
4
- type ParameterType = "path" | "querystring";
4
+ declare type ParameterType = "path" | "querystring";
5
5
  interface ApiParameter {
6
6
  type: ParameterType;
7
7
  name: string;
@@ -1,6 +1,6 @@
1
1
  import { Schedule } from "@aws-cdk/aws-synthetics-alpha";
2
2
  /** Optional env parameters for canary */
3
- type CanaryEnv = Record<string, string>;
3
+ declare type CanaryEnv = Record<string, string>;
4
4
  export interface CanaryParameters {
5
5
  readonly name: string;
6
6
  readonly schedule?: Schedule;
@@ -3,8 +3,8 @@ import { IncomingMessage } from "http";
3
3
  import { MediaType } from "../../types/mediatypes";
4
4
  import { FeatureCollection } from "geojson";
5
5
  export declare const API_KEY_HEADER = "x-api-key";
6
- type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
7
- type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => Promise<void>;
6
+ declare type CheckerFunction = (Res: IncomingMessage) => Promise<void>;
7
+ declare type JsonCheckerFunction<T> = (json: T, body: string, message: IncomingMessage) => Promise<void>;
8
8
  export declare class UrlChecker {
9
9
  private readonly requestOptions;
10
10
  constructor(hostname: string, apiKey?: string);
@@ -3,8 +3,8 @@ import { IVpc, SubnetSelection } from "aws-cdk-lib/aws-ec2";
3
3
  import { Role } from "aws-cdk-lib/aws-iam";
4
4
  import { DigitrafficStack } from "./stack";
5
5
  import { MonitoredFunctionAlarmProps } from "./monitoredfunction";
6
- export type LambdaEnvironment = Record<string, string>;
7
- export type DBLambdaEnvironment = LambdaEnvironment & {
6
+ export declare type LambdaEnvironment = Record<string, string>;
7
+ export declare type DBLambdaEnvironment = LambdaEnvironment & {
8
8
  SECRET_ID?: string;
9
9
  DB_APPLICATION: string;
10
10
  };
@@ -27,7 +27,7 @@ export interface FunctionParameters {
27
27
  architecture?: Architecture;
28
28
  singleLambda?: boolean;
29
29
  }
30
- export type MonitoredFunctionParameters = FunctionParameters & {
30
+ export declare type MonitoredFunctionParameters = FunctionParameters & {
31
31
  readonly durationAlarmProps?: MonitoredFunctionAlarmProps;
32
32
  readonly durationWarningProps?: MonitoredFunctionAlarmProps;
33
33
  readonly errorAlarmProps?: MonitoredFunctionAlarmProps;
@@ -11,39 +11,6 @@ const subscription_1 = require("../stack/subscription");
11
11
  * Creates a Lambda function that monitors default CloudWatch Lambda metrics with CloudWatch Alarms.
12
12
  */
13
13
  class MonitoredFunction extends aws_lambda_1.Function {
14
- /**
15
- * Create new MonitoredFunction. Use topics from given DigitrafficStack.
16
- *
17
- * @param stack DigitrafficStack
18
- * @param id Lambda construct Id
19
- * @param functionProps Lambda function properties
20
- * @param props Monitored function properties
21
- */
22
- static create(stack, id, functionProps, props) {
23
- if (props === MonitoredFunction.DISABLE_ALARMS &&
24
- stack.configuration.production) {
25
- throw new Error(
26
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
27
- `Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
28
- }
29
- return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
30
- }
31
- /**
32
- * Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
33
- *
34
- * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
35
- *
36
- * @param stack DigitrafficStack
37
- * @param name param-case name
38
- * @param environment Lambda environment
39
- * @param functionParameters Lambda function parameters
40
- */
41
- static createV2(stack, name, environment, functionParameters) {
42
- const functionName = functionParameters?.functionName ??
43
- `${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
44
- const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, environment, functionName, name, functionParameters);
45
- return MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
46
- }
47
14
  /**
48
15
  * @param scope Stack
49
16
  * @param id Lambda construct Id
@@ -81,6 +48,39 @@ class MonitoredFunction extends aws_lambda_1.Function {
81
48
  this.createAlarm(scope, this.metricThrottles(), "Throttles", "Throttles alarm", "Has throttled", trafficType, this.getAlarmActionForEnv(alarmSnsAction, warningSnsAction, production), 0, 1, 1, aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD, props?.throttleAlarmProps);
82
49
  }
83
50
  }
51
+ /**
52
+ * Create new MonitoredFunction. Use topics from given DigitrafficStack.
53
+ *
54
+ * @param stack DigitrafficStack
55
+ * @param id Lambda construct Id
56
+ * @param functionProps Lambda function properties
57
+ * @param props Monitored function properties
58
+ */
59
+ static create(stack, id, functionProps, props) {
60
+ if (props === MonitoredFunction.DISABLE_ALARMS &&
61
+ stack.configuration.production) {
62
+ throw new Error(
63
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
64
+ `Function ${functionProps.functionName} has DISABLE_ALARMS. Remove before installing to production or define your own properties!`);
65
+ }
66
+ return new MonitoredFunction(stack, id, functionProps, stack.alarmTopic, stack.warningTopic, stack.configuration.production, stack.configuration.trafficType, props);
67
+ }
68
+ /**
69
+ * Create new MonitoredFunction. Use topics from given DigitrafficStack. Generate names from given name and configuration shortName.
70
+ *
71
+ * For example, shortName FOO and given name update-things will create function FOO-UpdateThings and use code from lambda/update-things/update-things.ts method handler.
72
+ *
73
+ * @param stack DigitrafficStack
74
+ * @param name param-case name
75
+ * @param environment Lambda environment
76
+ * @param functionParameters Lambda function parameters
77
+ */
78
+ static createV2(stack, name, environment, functionParameters) {
79
+ const functionName = functionParameters?.functionName ??
80
+ `${stack.configuration.shortName}-${(0, change_case_1.pascalCase)(name)}`;
81
+ const functionProps = (0, lambda_configs_1.databaseFunctionProps)(stack, environment, functionName, name, functionParameters);
82
+ return MonitoredFunction.create(stack, functionName, functionProps, functionParameters);
83
+ }
84
84
  createAlarm(stack, metric, alarmId, alarmName, alarmDescription, trafficType, alarmSnsAction, threshold, evaluationPeriods, datapointsToAlarm, comparisonOperator, alarmProps) {
85
85
  metric
86
86
  .createAlarm(stack, `${this.node.id}-${alarmId}`, {
@@ -0,0 +1,5 @@
1
+ import { DtLogger } from "./dt-logger";
2
+ /**
3
+ * You can use this for your logging needs or create one locally and configure it as you wish.
4
+ */
5
+ export declare const logger: DtLogger;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ const dt_logger_1 = require("./dt-logger");
5
+ /**
6
+ * You can use this for your logging needs or create one locally and configure it as you wish.
7
+ */
8
+ exports.logger = new dt_logger_1.DtLogger();
9
+ //# sourceMappingURL=dt-logger-default.js.map
@@ -1,16 +1,35 @@
1
1
  /// <reference types="node" />
2
2
  import { Writable } from "stream";
3
- type LOG_LEVEL = "DEBUG" | "INFO" | "ERROR";
3
+ declare type LOG_LEVEL = "DEBUG" | "INFO" | "WARN" | "ERROR";
4
4
  export interface LoggerConfiguration {
5
5
  lambdaName?: string;
6
6
  fileName?: string;
7
7
  runTime?: string;
8
8
  writeStream?: Writable;
9
9
  }
10
- export type LoggableType = string | number | Record<string, unknown>;
10
+ export interface LoggableType {
11
+ /** name of method logging the message */
12
+ method: `${string}.${string}`;
13
+ /** message to log, optional */
14
+ message?: string;
15
+ /** type of message, optional */
16
+ type?: string;
17
+ /** stack trace, optional */
18
+ stack?: string;
19
+ /** amount of time some operation took in milliseconds, optional */
20
+ tookMs?: number;
21
+ /** count of something, optional */
22
+ count?: number;
23
+ /** do not log your apikey! */
24
+ apikey?: never;
25
+ /** do not log your apikey! */
26
+ apiKey?: never;
27
+ /** any other loggable key */
28
+ [key: string]: string | number | boolean | Date | undefined;
29
+ }
11
30
  /**
12
31
  * Helper class for json-logging. Logged line will include
13
- * * log-level (see LOG_LEVEL)
32
+ * * log-level
14
33
  * * lambdaName (taken from process environment)
15
34
  * * runtime (taken from process environment)
16
35
  * * the actual message (as json or as string)
@@ -21,8 +40,44 @@ export declare class DtLogger {
21
40
  readonly runtime?: string;
22
41
  readonly writeStream: Writable;
23
42
  constructor(config?: LoggerConfiguration);
43
+ /**
44
+ * Log given message with level DEBUG
45
+ *
46
+ * @param message Either a string or json-object
47
+ * @see log
48
+ */
49
+ debug(message: LoggableType): void;
50
+ /**
51
+ * Log given message with level INFO
52
+ *
53
+ * @param message Either a string or json-object
54
+ * @see log
55
+ */
24
56
  info(message: LoggableType): void;
57
+ /**
58
+ * Log given message with level WARN
59
+ *
60
+ * @param message Either a string or json-object
61
+ * @see log
62
+ */
63
+ warn(message: LoggableType): void;
64
+ /**
65
+ * Log given message with level INFO
66
+ *
67
+ * @param message Either a string or json-object
68
+ * @see log
69
+ */
25
70
  error(message: LoggableType): void;
71
+ /**
72
+ * Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
73
+ * Some metadata is also added to the message:
74
+ * * runtime - can be configured with constructor or inferred from environment
75
+ * * lambdaName - can be configured with constructor or inferred from environment
76
+ * * fileName - can be configured with constructor
77
+ *
78
+ * @param level "DEBUG", "INFO" or "ERROR"
79
+ * @param message Either a string or json-object
80
+ */
26
81
  log(level: LOG_LEVEL, message: LoggableType): void;
27
82
  }
28
83
  export {};
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DtLogger = void 0;
4
4
  /**
5
5
  * Helper class for json-logging. Logged line will include
6
- * * log-level (see LOG_LEVEL)
6
+ * * log-level
7
7
  * * lambdaName (taken from process environment)
8
8
  * * runtime (taken from process environment)
9
9
  * * the actual message (as json or as string)
@@ -16,23 +16,59 @@ class DtLogger {
16
16
  this.runtime = config?.runTime ?? process.env.AWS_EXECUTION_ENV;
17
17
  this.writeStream = config?.writeStream ?? process.stdout;
18
18
  }
19
+ /**
20
+ * Log given message with level DEBUG
21
+ *
22
+ * @param message Either a string or json-object
23
+ * @see log
24
+ */
25
+ debug(message) {
26
+ this.log("DEBUG", message);
27
+ }
28
+ /**
29
+ * Log given message with level INFO
30
+ *
31
+ * @param message Either a string or json-object
32
+ * @see log
33
+ */
19
34
  info(message) {
20
35
  this.log("INFO", message);
21
36
  }
37
+ /**
38
+ * Log given message with level WARN
39
+ *
40
+ * @param message Either a string or json-object
41
+ * @see log
42
+ */
43
+ warn(message) {
44
+ this.log("WARN", message);
45
+ }
46
+ /**
47
+ * Log given message with level INFO
48
+ *
49
+ * @param message Either a string or json-object
50
+ * @see log
51
+ */
22
52
  error(message) {
23
53
  this.log("ERROR", message);
24
54
  }
55
+ /**
56
+ * Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
57
+ * Some metadata is also added to the message:
58
+ * * runtime - can be configured with constructor or inferred from environment
59
+ * * lambdaName - can be configured with constructor or inferred from environment
60
+ * * fileName - can be configured with constructor
61
+ *
62
+ * @param level "DEBUG", "INFO" or "ERROR"
63
+ * @param message Either a string or json-object
64
+ */
25
65
  log(level, message) {
26
- // put string/number messages into message object
27
- const actualMessage = typeof message == "object" ? message : { message: message };
28
66
  const logMessage = {
29
- ...actualMessage,
30
- ...{
31
- level,
32
- fileName: this.fileName,
33
- lambdaName: this.lambdaName,
34
- runtime: this.runtime,
35
- },
67
+ ...message,
68
+ level,
69
+ fileName: message.fileName ?? this.fileName,
70
+ lambdaName: this.lambdaName,
71
+ runtime: this.runtime,
36
72
  };
37
73
  this.writeStream.write(JSON.stringify(logMessage) + "\n");
38
74
  }
@@ -11,6 +11,6 @@ export declare enum RdsSecretKey {
11
11
  host = "host",
12
12
  ro_host = "ro_host"
13
13
  }
14
- export type RdsProxySecret = Record<RdsProxySecretKey, string>;
15
- export type RdsSecret = Record<RdsSecretKey, string>;
14
+ export declare type RdsProxySecret = Record<RdsProxySecretKey, string>;
15
+ export declare type RdsSecret = Record<RdsSecretKey, string>;
16
16
  export declare function checkExpectedSecretKeys<Secret extends GenericSecret>(keys: string[], secret: Secret): void;
@@ -1,2 +1,2 @@
1
- export type GenericSecret = Record<string, string>;
1
+ export declare type GenericSecret = Record<string, string>;
2
2
  export declare function getSecret<Secret>(secretId: string, prefix?: string): Promise<Secret>;
@@ -6,8 +6,8 @@ export declare enum DatabaseEnvironmentKeys {
6
6
  DB_RO_URI = "DB_RO_URI",
7
7
  DB_APPLICATION = "DB_APPLICATION"
8
8
  }
9
- export type DTDatabase = IDatabase<unknown>;
10
- export type DTTransaction = ITask<unknown>;
9
+ export declare type DTDatabase = IDatabase<unknown>;
10
+ export declare type DTTransaction = ITask<unknown>;
11
11
  /**
12
12
  * Creates a non-pooling database connection primarily used by Lambdas.
13
13
  *
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * A simple asserter-class for writing canaries without dependency to testing-libraries.
3
3
  */
4
- type AssertedValue = string | number;
4
+ declare type AssertedValue = string | number;
5
5
  export declare abstract class Asserter {
6
6
  static assertEquals(value: AssertedValue, expected: AssertedValue): void;
7
7
  static assertTrue(value: boolean): void;
@@ -14,4 +14,4 @@ export declare class TestHttpServer {
14
14
  close(): void;
15
15
  private debuglog;
16
16
  }
17
- export type ListenProperties = Record<string, (url?: string, data?: string) => string>;
17
+ export declare type ListenProperties = Record<string, (url?: string, data?: string) => string>;
@@ -6,4 +6,4 @@ export interface EitherError {
6
6
  result: "error";
7
7
  message: string;
8
8
  }
9
- export type Either<T> = EitherOk<T> | EitherError;
9
+ export declare type Either<T> = EitherOk<T> | EitherError;
@@ -1 +1 @@
1
- export type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
1
+ export declare type URN<Namespace extends string, NamespaceSpecificString extends string = ""> = `urn:${Namespace}:${NamespaceSpecificString}`;
@@ -0,0 +1,4 @@
1
+ import { AxiosError } from "axios";
2
+ import { DtLogger } from "../aws/runtime/dt-logger";
3
+ export declare function logException(logger: DtLogger, error: Error | string, includeStack: boolean): void;
4
+ export declare function logException(logger: DtLogger, error: AxiosError): void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logException = void 0;
4
+ const axios_1 = require("axios");
5
+ const utils_1 = require("./utils");
6
+ const functionName = (0, utils_1.getEnvVariableOrElse)("AWS_LAMBDA_FUNCTION_NAME", "test");
7
+ /**
8
+ * Log given exception with level ERROR to given logger.
9
+ *
10
+ * Supports AxiosError, Error and string
11
+ *
12
+ * @param logger DtLogger to use
13
+ * @param error AxiosError, Error or string to log
14
+ * @param includeStack Include stack in the message, default false
15
+ * @see log
16
+ */
17
+ function logException(logger, error, includeStack = false) {
18
+ const message = error instanceof Error ? error.message : error;
19
+ const stack = error instanceof Error && includeStack ? error.stack : undefined;
20
+ const code = error instanceof axios_1.AxiosError ? error.code : undefined;
21
+ logger.error({
22
+ type: "Error",
23
+ method: `${functionName}.logException`,
24
+ message,
25
+ code,
26
+ stack,
27
+ });
28
+ }
29
+ exports.logException = logException;
30
+ //# sourceMappingURL=logging.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digitraffic/common",
3
- "version": "2023.3.17-1",
3
+ "version": "2023.3.21-1",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -45,7 +45,7 @@
45
45
  "axios": "^1.2.6",
46
46
  "change-case": "^4.1.2",
47
47
  "constructs": "^10.1.222",
48
- "eslint": "^8.34.0",
48
+ "eslint": "~8.34.0",
49
49
  "eslint-config-prettier": "^8.6.0",
50
50
  "eslint-plugin-deprecation": "1.3.3",
51
51
  "geojson-validation": "^1.0.2",
@@ -62,7 +62,7 @@
62
62
  "rimraf": "^4.1.0",
63
63
  "sinon": "^15.0.1",
64
64
  "ts-jest": "^29.0.5",
65
- "typescript": "^4.9.5"
65
+ "typescript": "~4.8.4"
66
66
  },
67
67
  "externals": [
68
68
  "aws-sdk",
@@ -75,6 +75,7 @@
75
75
  "build": "tsc",
76
76
  "lint": "eslint --cache .",
77
77
  "eslint-report": "eslint . --format html",
78
+ "ci:eslint-report": "eslint . --format html -o report.html",
78
79
  "clean": "rimraf dist output",
79
80
  "test": "jest --detectOpenHandles --forceExit --coverage --coverageDirectory=output/coverage/jest"
80
81
  }
@@ -1,3 +1,4 @@
1
+ import { getEnvVariableOrElse } from "../../../utils/utils";
1
2
  import { DtLogger } from "../../runtime/dt-logger";
2
3
  import { LambdaResponse } from "../../types/lambda-response";
3
4
 
@@ -8,6 +9,8 @@ export type LoggingHandler = (
8
9
 
9
10
  export type ErrorHandler = (error: unknown, logger: DtLogger) => LambdaResponse;
10
11
 
12
+ const functionName = getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "test");
13
+
11
14
  /**
12
15
  * Factory class for creating lambda-handler functions. You can set functionality to handle logging and error-handling,
13
16
  * with the defaults:
@@ -30,7 +33,7 @@ export class HandlerFactory {
30
33
  } finally {
31
34
  console.info(
32
35
  "method=%s.handler tookMs=%d",
33
- process.env.AWS_LAMBDA_FUNCTION_NAME,
36
+ functionName,
34
37
  Date.now() - start
35
38
  );
36
39
  }
@@ -74,7 +77,10 @@ export function createJsonLoggingHandler(): LoggingHandler {
74
77
  try {
75
78
  return await method();
76
79
  } finally {
77
- logger.info({ tookMs: Date.now() - start });
80
+ logger.info({
81
+ method: `${functionName}.handler`,
82
+ tookMs: Date.now() - start,
83
+ });
78
84
  }
79
85
  };
80
86
  }
@@ -0,0 +1,6 @@
1
+ import { DtLogger } from "./dt-logger";
2
+
3
+ /**
4
+ * You can use this for your logging needs or create one locally and configure it as you wish.
5
+ */
6
+ export const logger = new DtLogger();
@@ -1,6 +1,6 @@
1
1
  import { Writable } from "stream";
2
2
 
3
- type LOG_LEVEL = "DEBUG" | "INFO" | "ERROR";
3
+ type LOG_LEVEL = "DEBUG" | "INFO" | "WARN" | "ERROR";
4
4
 
5
5
  export interface LoggerConfiguration {
6
6
  lambdaName?: string;
@@ -9,11 +9,30 @@ export interface LoggerConfiguration {
9
9
  writeStream?: Writable;
10
10
  }
11
11
 
12
- export type LoggableType = string | number | Record<string, unknown>;
12
+ export interface LoggableType {
13
+ /** name of method logging the message */
14
+ method: `${string}.${string}`;
15
+ /** message to log, optional */
16
+ message?: string;
17
+ /** type of message, optional */
18
+ type?: string;
19
+ /** stack trace, optional */
20
+ stack?: string;
21
+ /** amount of time some operation took in milliseconds, optional */
22
+ tookMs?: number;
23
+ /** count of something, optional */
24
+ count?: number;
25
+ /** do not log your apikey! */
26
+ apikey?: never;
27
+ /** do not log your apikey! */
28
+ apiKey?: never;
29
+ /** any other loggable key */
30
+ [key: string]: string | number | boolean | Date | undefined;
31
+ }
13
32
 
14
33
  /**
15
34
  * Helper class for json-logging. Logged line will include
16
- * * log-level (see LOG_LEVEL)
35
+ * * log-level
17
36
  * * lambdaName (taken from process environment)
18
37
  * * runtime (taken from process environment)
19
38
  * * the actual message (as json or as string)
@@ -33,27 +52,62 @@ export class DtLogger {
33
52
  this.writeStream = config?.writeStream ?? process.stdout;
34
53
  }
35
54
 
36
- info(message: LoggableType) {
55
+ /**
56
+ * Log given message with level DEBUG
57
+ *
58
+ * @param message Either a string or json-object
59
+ * @see log
60
+ */
61
+ debug(message: LoggableType): void {
62
+ this.log("DEBUG", message);
63
+ }
64
+
65
+ /**
66
+ * Log given message with level INFO
67
+ *
68
+ * @param message Either a string or json-object
69
+ * @see log
70
+ */
71
+ info(message: LoggableType): void {
37
72
  this.log("INFO", message);
38
73
  }
39
74
 
40
- error(message: LoggableType) {
75
+ /**
76
+ * Log given message with level WARN
77
+ *
78
+ * @param message Either a string or json-object
79
+ * @see log
80
+ */
81
+ warn(message: LoggableType): void {
82
+ this.log("WARN", message);
83
+ }
84
+ /**
85
+ * Log given message with level INFO
86
+ *
87
+ * @param message Either a string or json-object
88
+ * @see log
89
+ */
90
+ error(message: LoggableType): void {
41
91
  this.log("ERROR", message);
42
92
  }
43
93
 
44
- log(level: LOG_LEVEL, message: LoggableType) {
45
- // put string/number messages into message object
46
- const actualMessage =
47
- typeof message == "object" ? message : { message: message };
48
-
94
+ /**
95
+ * Log message with given log level. If message is a json object, it will be logged as it is and if it is a string it will be wrapped into json-element with key "message".
96
+ * Some metadata is also added to the message:
97
+ * * runtime - can be configured with constructor or inferred from environment
98
+ * * lambdaName - can be configured with constructor or inferred from environment
99
+ * * fileName - can be configured with constructor
100
+ *
101
+ * @param level "DEBUG", "INFO" or "ERROR"
102
+ * @param message Either a string or json-object
103
+ */
104
+ log(level: LOG_LEVEL, message: LoggableType): void {
49
105
  const logMessage = {
50
- ...actualMessage,
51
- ...{
52
- level,
53
- fileName: this.fileName,
54
- lambdaName: this.lambdaName,
55
- runtime: this.runtime,
56
- },
106
+ ...message,
107
+ level,
108
+ fileName: message.fileName ?? this.fileName,
109
+ lambdaName: this.lambdaName,
110
+ runtime: this.runtime,
57
111
  };
58
112
 
59
113
  this.writeStream.write(JSON.stringify(logMessage) + "\n");
@@ -0,0 +1,41 @@
1
+ import { AxiosError } from "axios";
2
+ import { DtLogger } from "../aws/runtime/dt-logger";
3
+ import { getEnvVariableOrElse } from "./utils";
4
+
5
+ const functionName = getEnvVariableOrElse("AWS_LAMBDA_FUNCTION_NAME", "test");
6
+
7
+ export function logException(
8
+ logger: DtLogger,
9
+ error: Error | string,
10
+ includeStack: boolean
11
+ ): void;
12
+ export function logException(logger: DtLogger, error: AxiosError): void;
13
+
14
+ /**
15
+ * Log given exception with level ERROR to given logger.
16
+ *
17
+ * Supports AxiosError, Error and string
18
+ *
19
+ * @param logger DtLogger to use
20
+ * @param error AxiosError, Error or string to log
21
+ * @param includeStack Include stack in the message, default false
22
+ * @see log
23
+ */
24
+ export function logException(
25
+ logger: DtLogger,
26
+ error: Error | string | AxiosError,
27
+ includeStack = false
28
+ ) {
29
+ const message = error instanceof Error ? error.message : error;
30
+ const stack =
31
+ error instanceof Error && includeStack ? error.stack : undefined;
32
+ const code = error instanceof AxiosError ? error.code : undefined;
33
+
34
+ logger.error({
35
+ type: "Error",
36
+ method: `${functionName}.logException`,
37
+ message,
38
+ code,
39
+ stack,
40
+ });
41
+ }