@digitraffic/common 2023.3.17-1 → 2023.3.21-2

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. This will not be forwarded to centralized logging system!.
45
+ *
46
+ * @param message anything
47
+ * @see log
48
+ */
49
+ debug(message: unknown): void;
50
+ /**
51
+ * Log given message with level INFO
52
+ *
53
+ * @param message Json-object to log
54
+ * @see log
55
+ */
24
56
  info(message: LoggableType): void;
57
+ /**
58
+ * Log given message with level WARN
59
+ *
60
+ * @param message Json-object to log
61
+ * @see log
62
+ */
63
+ warn(message: LoggableType): void;
64
+ /**
65
+ * Log given message with level INFO
66
+ *
67
+ * @param message Json-object to log
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,66 @@ 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. This will not be forwarded to centralized logging system!.
21
+ *
22
+ * @param message anything
23
+ * @see log
24
+ */
25
+ debug(message) {
26
+ const logMessage = {
27
+ message,
28
+ level: "DEBUG",
29
+ fileName: this.fileName,
30
+ lambdaName: this.lambdaName,
31
+ runtime: this.runtime,
32
+ };
33
+ this.writeStream.write(JSON.stringify(logMessage) + "\n");
34
+ }
35
+ /**
36
+ * Log given message with level INFO
37
+ *
38
+ * @param message Json-object to log
39
+ * @see log
40
+ */
19
41
  info(message) {
20
42
  this.log("INFO", message);
21
43
  }
44
+ /**
45
+ * Log given message with level WARN
46
+ *
47
+ * @param message Json-object to log
48
+ * @see log
49
+ */
50
+ warn(message) {
51
+ this.log("WARN", message);
52
+ }
53
+ /**
54
+ * Log given message with level INFO
55
+ *
56
+ * @param message Json-object to log
57
+ * @see log
58
+ */
22
59
  error(message) {
23
60
  this.log("ERROR", message);
24
61
  }
62
+ /**
63
+ * 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".
64
+ * Some metadata is also added to the message:
65
+ * * runtime - can be configured with constructor or inferred from environment
66
+ * * lambdaName - can be configured with constructor or inferred from environment
67
+ * * fileName - can be configured with constructor
68
+ *
69
+ * @param level "DEBUG", "INFO" or "ERROR"
70
+ * @param message Either a string or json-object
71
+ */
25
72
  log(level, message) {
26
- // put string/number messages into message object
27
- const actualMessage = typeof message == "object" ? message : { message: message };
28
73
  const logMessage = {
29
- ...actualMessage,
30
- ...{
31
- level,
32
- fileName: this.fileName,
33
- lambdaName: this.lambdaName,
34
- runtime: this.runtime,
35
- },
74
+ ...message,
75
+ level,
76
+ fileName: message.fileName ?? this.fileName,
77
+ lambdaName: this.lambdaName,
78
+ runtime: this.runtime,
36
79
  };
37
80
  this.writeStream.write(JSON.stringify(logMessage) + "\n");
38
81
  }
@@ -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-2",
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,70 @@ 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. This will not be forwarded to centralized logging system!.
57
+ *
58
+ * @param message anything
59
+ * @see log
60
+ */
61
+ debug(message: unknown): void {
62
+ const logMessage = {
63
+ message,
64
+ level: "DEBUG",
65
+ fileName: this.fileName,
66
+ lambdaName: this.lambdaName,
67
+ runtime: this.runtime,
68
+ };
69
+
70
+ this.writeStream.write(JSON.stringify(logMessage) + "\n");
71
+ }
72
+
73
+ /**
74
+ * Log given message with level INFO
75
+ *
76
+ * @param message Json-object to log
77
+ * @see log
78
+ */
79
+ info(message: LoggableType): void {
37
80
  this.log("INFO", message);
38
81
  }
39
82
 
40
- error(message: LoggableType) {
83
+ /**
84
+ * Log given message with level WARN
85
+ *
86
+ * @param message Json-object to log
87
+ * @see log
88
+ */
89
+ warn(message: LoggableType): void {
90
+ this.log("WARN", message);
91
+ }
92
+ /**
93
+ * Log given message with level INFO
94
+ *
95
+ * @param message Json-object to log
96
+ * @see log
97
+ */
98
+ error(message: LoggableType): void {
41
99
  this.log("ERROR", message);
42
100
  }
43
101
 
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
-
102
+ /**
103
+ * 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".
104
+ * Some metadata is also added to the message:
105
+ * * runtime - can be configured with constructor or inferred from environment
106
+ * * lambdaName - can be configured with constructor or inferred from environment
107
+ * * fileName - can be configured with constructor
108
+ *
109
+ * @param level "DEBUG", "INFO" or "ERROR"
110
+ * @param message Either a string or json-object
111
+ */
112
+ log(level: LOG_LEVEL, message: LoggableType): void {
49
113
  const logMessage = {
50
- ...actualMessage,
51
- ...{
52
- level,
53
- fileName: this.fileName,
54
- lambdaName: this.lambdaName,
55
- runtime: this.runtime,
56
- },
114
+ ...message,
115
+ level,
116
+ fileName: message.fileName ?? this.fileName,
117
+ lambdaName: this.lambdaName,
118
+ runtime: this.runtime,
57
119
  };
58
120
 
59
121
  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
+ }