@uoa/lambda-tracing 2.0.1 → 2.1.0-beta.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.
package/changelog.md ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ ## 2.1.0
4
+ - Unexpected errors are now caught within the library. When this occurs, the request promise will reject with the error.
5
+ - http response promises will now be rejected if the response code is not in the 2xx range
6
+ - The response content-type header is now correctly checked to convert the response body. Previously the response transformation was checking the content-type header of the request. If the content-type header is not present, it will attempt to transform the response to JSON.
7
+ - Added support for XML responses - these will be parsed to an object
8
+ - Added support for Image responses - these will be parsed to a base64 string
9
+
10
+ ## [Deprecated] 2.0.0, 2.0.1, 2.0.2
11
+ - Changes for Zipkin which have since been removed
12
+ - Do not use these versions
13
+
14
+ ## 1.6.0
15
+ - Fix error when logged message was undefined
16
+
17
+ ## 1.5.0
18
+ - Generate a new span ID instead of using that of the incoming request.
19
+ - Use the incoming request's span ID as the current span's parent span ID.
20
+
21
+ ## 1.4.0
22
+ - Add support for 16 and 32 character trace IDs
23
+ - Add function to allow getting and setting the X-B3-Info header
24
+
25
+ ## 1.3.0
26
+ - Add optional port parameter to all functions in uoaHttps module. Defaults to 443 if not specified
27
+
28
+ ## 1.2.0
29
+ - Fix newlines not logging correctly in logging module
30
+
31
+ ## 1.1.1
32
+ - Update readme with information on Kong plugin requirements
33
+
34
+ ## 1.1.0
35
+ - Add uoaHttps module to propagate tracing headers through http requests
36
+
37
+ ## 1.0.1
38
+ - Fix formatting in readme
39
+
40
+ ## 1.0.0
41
+ - Initial release with Lambda tracing & logging functionality
package/dist/tracing.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare function initializeTracing(serviceName: string): void;
1
+ export declare function initializeTracing(): void;
2
2
  export declare function getTraceInfoHeader(): string;
3
3
  export declare function setTraceInfoHeader(info: string): void;
package/dist/tracing.js CHANGED
@@ -7,15 +7,9 @@ const instrumentation_1 = require("@opentelemetry/instrumentation");
7
7
  const UoaB3Propagator_1 = require("./UoaB3Propagator");
8
8
  const api_1 = require("@opentelemetry/api");
9
9
  const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
10
- const zipkin_1 = require("./zipkin/zipkin");
11
10
  const provider = new sdk_trace_node_1.NodeTracerProvider({ sampler: new sdk_trace_base_1.AlwaysOnSampler() });
12
11
  let infoHeader;
13
- function initializeTracing(serviceName) {
14
- const options = {
15
- url: process.env.zipkinUrl ? process.env.zipkinUrl : 'http://internal-zipkin-uoa-its-nonprod-internal-1407434909.ap-southeast-2.elb.amazonaws.com:443/api/v2/spans',
16
- serviceName: serviceName
17
- };
18
- provider.addSpanProcessor(new sdk_trace_node_1.BatchSpanProcessor(new zipkin_1.ZipkinExporter(options)));
12
+ function initializeTracing() {
19
13
  provider.register({
20
14
  propagator: new UoaB3Propagator_1.UoaB3Propagator()
21
15
  });
package/dist/uoaHttps.js CHANGED
@@ -22,18 +22,10 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
34
25
  Object.defineProperty(exports, "__esModule", { value: true });
35
26
  const https = __importStar(require("https"));
36
27
  const api_1 = require("@opentelemetry/api");
28
+ const fast_xml_parser_1 = require("fast-xml-parser");
37
29
  function request(...args) {
38
30
  if (args[2]) {
39
31
  api_1.propagation.inject(api_1.context.active(), args[1].headers);
@@ -44,175 +36,124 @@ function request(...args) {
44
36
  return https.request(args[0], args[1]);
45
37
  }
46
38
  }
47
- function doGetRequest(hostname, path, headers, port = 443) {
48
- return __awaiter(this, void 0, void 0, function* () {
49
- return new Promise(function (resolve, reject) {
50
- const options = {
51
- "method": "GET",
52
- "hostname": hostname,
53
- "path": path,
54
- "headers": headers,
55
- "port": port
56
- };
57
- api_1.propagation.inject(api_1.context.active(), options.headers);
58
- const req = https.request(options, function (response) {
59
- const chunks = [];
60
- response.on("data", function (chunk) {
61
- chunks.push(chunk);
62
- });
63
- response.on("end", function () {
64
- let body = Buffer.concat(chunks);
65
- body = JSON.parse(body.toString());
66
- resolve(body);
67
- });
68
- response.on("error", function (e) {
69
- reject(e);
70
- });
71
- });
72
- req.end();
73
- });
39
+ async function doGetRequest(hostname, path, headers, port = 443) {
40
+ return new Promise(function (resolve, reject) {
41
+ const options = {
42
+ "method": "GET",
43
+ "hostname": hostname,
44
+ "path": path,
45
+ "headers": headers,
46
+ "port": port
47
+ };
48
+ api_1.propagation.inject(api_1.context.active(), options.headers);
49
+ const req = doHttpsRequest(options, resolve, reject);
50
+ req.end();
74
51
  });
75
52
  }
76
- function doPostRequest(hostname, path, headers, data, port = 443) {
77
- return __awaiter(this, void 0, void 0, function* () {
78
- return new Promise(function (resolve, reject) {
79
- const options = {
80
- "method": "POST",
81
- "hostname": hostname,
82
- "path": path,
83
- "headers": headers,
84
- "port": port
85
- };
86
- api_1.propagation.inject(api_1.context.active(), options.headers);
87
- const req = https.request(options, function (response) {
88
- const chunks = [];
89
- response.on("data", function (chunk) {
90
- chunks.push(chunk);
91
- });
92
- response.on("end", function () {
93
- if (response.statusCode == 204) {
94
- //204 is no content, and most JSON parses blow up on an empty string
95
- resolve(null);
96
- }
97
- else {
98
- let body = Buffer.concat(chunks);
99
- if (!('Content-Type' in options.headers) || options.headers['Content-Type'] === 'application/json') {
100
- body = JSON.parse(body.toString());
101
- }
102
- else {
103
- body = body.toString();
104
- }
105
- resolve(body);
106
- }
107
- });
108
- response.on("error", function (e) {
109
- reject(e);
110
- });
111
- });
112
- if (data) {
113
- if (!('Content-Type' in options.headers) || options.headers['Content-Type'] === 'application/json') {
114
- //We serialize using JSON.stringify as a default, or if a JSON is specified
115
- req.write(JSON.stringify(data));
116
- }
117
- else {
118
- // If another content-type is specified however, we respect the serialization provided
119
- req.write(data);
120
- }
121
- }
122
- req.end();
123
- });
53
+ async function doPostRequest(hostname, path, headers, data, port = 443) {
54
+ return new Promise(function (resolve, reject) {
55
+ const options = {
56
+ "method": "POST",
57
+ "hostname": hostname,
58
+ "path": path,
59
+ "headers": headers,
60
+ "port": port
61
+ };
62
+ api_1.propagation.inject(api_1.context.active(), options.headers);
63
+ const req = doHttpsRequest(options, resolve, reject);
64
+ setRequestBody(req, data);
65
+ req.end();
66
+ });
67
+ }
68
+ async function doPutRequest(hostname, path, headers, data, port = 443) {
69
+ return new Promise(function (resolve, reject) {
70
+ const options = {
71
+ "method": "PUT",
72
+ "hostname": hostname,
73
+ "path": path,
74
+ "headers": headers,
75
+ "port": port
76
+ };
77
+ api_1.propagation.inject(api_1.context.active(), options.headers);
78
+ const req = doHttpsRequest(options, resolve, reject);
79
+ setRequestBody(req, data);
80
+ req.end();
81
+ });
82
+ }
83
+ async function doDeleteRequest(hostname, path, headers, port = 443) {
84
+ return new Promise(function (resolve, reject) {
85
+ const options = {
86
+ "method": "DELETE",
87
+ "hostname": hostname,
88
+ "path": path,
89
+ "headers": headers,
90
+ "port": port
91
+ };
92
+ api_1.propagation.inject(api_1.context.active(), options.headers);
93
+ const req = doHttpsRequest(options, resolve, reject);
94
+ req.end();
124
95
  });
125
96
  }
126
- function doPutRequest(hostname, path, headers, data, port = 443) {
127
- return __awaiter(this, void 0, void 0, function* () {
128
- return new Promise(function (resolve, reject) {
129
- const options = {
130
- "method": "PUT",
131
- "hostname": hostname,
132
- "path": path,
133
- "headers": headers,
134
- "port": port
135
- };
136
- api_1.propagation.inject(api_1.context.active(), options.headers);
137
- const req = https.request(options, function (response) {
138
- const chunks = [];
139
- response.on("data", function (chunk) {
140
- chunks.push(chunk);
141
- });
142
- response.on("end", function () {
143
- if (response.statusCode == 204) {
144
- //204 is no content, and most JSON parses blow up on an empty string
145
- resolve(null);
97
+ function doHttpsRequest(options, resolve, reject) {
98
+ return https.request(options, function (response) {
99
+ const chunks = [];
100
+ response.on("data", function (chunk) {
101
+ chunks.push(chunk);
102
+ });
103
+ response.on("end", function () {
104
+ if (response.statusCode === 204) {
105
+ //204 is no content, and most JSON parses blow up on an empty string
106
+ resolve(null);
107
+ }
108
+ else {
109
+ try {
110
+ let body = Buffer.concat(chunks);
111
+ let parsedBody = body.toString();
112
+ //Get the response content-type header value so we can apply different parsing methods
113
+ const responseContentType = response.headers["content-type"]?.toLowerCase() ?? '';
114
+ if (responseContentType === '' || responseContentType.includes('application/json')) {
115
+ parsedBody = JSON.parse(body.toString());
116
+ }
117
+ else if (responseContentType.includes('application/xml') || responseContentType.includes('text/xml')) {
118
+ const parser = new fast_xml_parser_1.XMLParser({
119
+ ignoreDeclaration: true,
120
+ ignorePiTags: true
121
+ });
122
+ parsedBody = parser.parse(body.toString());
123
+ }
124
+ else if (responseContentType.includes('image/')) {
125
+ parsedBody = body.toString('base64');
126
+ }
127
+ if (response.statusCode !== undefined && response.statusCode >= 200 && response.statusCode < 300) {
128
+ resolve(parsedBody);
146
129
  }
147
130
  else {
148
- let body = Buffer.concat(chunks);
149
- if (!('Content-Type' in options.headers) || options.headers['Content-Type'] === 'application/json') {
150
- body = JSON.parse(body.toString());
151
- }
152
- else {
153
- body = body.toString();
154
- }
155
- resolve(body);
131
+ reject(parsedBody);
156
132
  }
157
- });
158
- response.on("error", function (e) {
159
- reject(e);
160
- });
161
- });
162
- if (data) {
163
- if (!('Content-Type' in options.headers) || options.headers['Content-Type'] === 'application/json') {
164
- //We serialize using JSON.stringify as a default, or if a JSON is specified
165
- req.write(JSON.stringify(data));
166
133
  }
167
- else {
168
- // If another content-type is specified however, we respect the serialization provided
169
- req.write(data);
134
+ catch (e) {
135
+ reject(e);
170
136
  }
171
137
  }
172
- req.end();
173
138
  });
174
- });
175
- }
176
- function doDeleteRequest(hostname, path, headers, port = 443) {
177
- return __awaiter(this, void 0, void 0, function* () {
178
- return new Promise(function (resolve, reject) {
179
- const options = {
180
- "method": "DELETE",
181
- "hostname": hostname,
182
- "path": path,
183
- "headers": headers,
184
- "port": port
185
- };
186
- api_1.propagation.inject(api_1.context.active(), options.headers);
187
- const req = https.request(options, function (response) {
188
- const chunks = [];
189
- response.on("data", function (chunk) {
190
- chunks.push(chunk);
191
- });
192
- response.on("end", function () {
193
- if (response.statusCode == 204) {
194
- //204 is no content, and most JSON parses blow up on an empty string
195
- resolve(null);
196
- }
197
- else {
198
- let body = Buffer.concat(chunks);
199
- if (!('Content-Type' in options.headers) || options.headers['Content-Type'] === 'application/json') {
200
- body = JSON.parse(body.toString());
201
- }
202
- else {
203
- body = body.toString();
204
- }
205
- resolve(body);
206
- }
207
- });
208
- response.on("error", function (e) {
209
- reject(e);
210
- });
211
- });
212
- req.end();
139
+ response.on("error", function (e) {
140
+ reject(e);
213
141
  });
214
142
  });
215
143
  }
144
+ function setRequestBody(request, data) {
145
+ if (data) {
146
+ const requestContentType = request.getHeader('content-type')?.toString() ?? '';
147
+ if (requestContentType === '' || requestContentType.includes('application/json')) {
148
+ //We serialize using JSON.stringify as a default, or if JSON is specified
149
+ request.write(JSON.stringify(data));
150
+ }
151
+ else {
152
+ // If another content-type is specified however, we respect the serialization provided
153
+ request.write(data);
154
+ }
155
+ }
156
+ }
216
157
  module.exports = {
217
158
  request,
218
159
  doGetRequest,
package/package.json CHANGED
@@ -1,43 +1,45 @@
1
- {
2
- "name": "@uoa/lambda-tracing",
3
- "version": "2.0.1",
4
- "description": "Library for logging & distributed tracing in UoA Lambda projects",
5
- "repository": {
6
- "type": "git",
7
- "url": "git+ssh://git@bitbucket.org/uoa/lambda-tracing.git"
8
- },
9
- "author": "Mitchell Faulconbridge <mitchell.faulconbridge@auckland.ac.nz>",
10
- "license": "MIT",
11
- "homepage": "https://bitbucket.org/uoa/lambda-tracing#readme",
12
- "keywords": [
13
- "uoa",
14
- "lambda",
15
- "logging",
16
- "distributed-tracing"
17
- ],
18
- "main": "dist/tracing.js",
19
- "types": "dist/tracing.d.ts",
20
- "scripts": {
21
- "test": "echo \"Error: no test specified\" && exit 1",
22
- "prepare": "tsc"
23
- },
24
- "exports": {
25
- ".": "./dist/tracing.js",
26
- "./tracing": "./dist/tracing.js",
27
- "./uoaHttps": "./dist/uoaHttps.js",
28
- "./logging": "./dist/logging.js"
29
- },
30
- "dependencies": {
31
- "@opentelemetry/api": "^1.1.0",
32
- "@opentelemetry/core": "^1.8.0",
33
- "@opentelemetry/instrumentation": "^0.28.0",
34
- "@opentelemetry/instrumentation-aws-lambda": "^0.31.0",
35
- "@opentelemetry/sdk-trace-node": "^1.8.0",
36
- "moment": "^2.29.3",
37
- "winston": "^3.7.2"
38
- },
39
- "devDependencies": {
40
- "@types/node": "^17.0.35",
41
- "typescript": "^4.7.2"
42
- }
43
- }
1
+ {
2
+ "name": "@uoa/lambda-tracing",
3
+ "version": "2.1.0-beta.2",
4
+ "description": "Library for logging & distributed tracing in UoA Lambda projects",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+ssh://git@bitbucket.org/uoa/lambda-tracing.git"
8
+ },
9
+ "author": "Mitchell Faulconbridge <mitchell.faulconbridge@auckland.ac.nz>",
10
+ "license": "MIT",
11
+ "homepage": "https://bitbucket.org/uoa/lambda-tracing#readme",
12
+ "keywords": [
13
+ "uoa",
14
+ "lambda",
15
+ "logging",
16
+ "distributed-tracing"
17
+ ],
18
+ "main": "dist/tracing.js",
19
+ "types": "dist/tracing.d.ts",
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\" && exit 1",
22
+ "prepare": "tsc",
23
+ "prepack": "tsc"
24
+ },
25
+ "exports": {
26
+ ".": "./dist/tracing.js",
27
+ "./tracing": "./dist/tracing.js",
28
+ "./uoaHttps": "./dist/uoaHttps.js",
29
+ "./logging": "./dist/logging.js"
30
+ },
31
+ "dependencies": {
32
+ "@opentelemetry/api": "^1.1.0",
33
+ "@opentelemetry/core": "^1.8.0",
34
+ "@opentelemetry/instrumentation": "^0.28.0",
35
+ "@opentelemetry/instrumentation-aws-lambda": "^0.31.0",
36
+ "@opentelemetry/sdk-trace-node": "^1.8.0",
37
+ "fast-xml-parser": "^4.3.4",
38
+ "moment": "^2.29.3",
39
+ "winston": "^3.7.2"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^17.0.35",
43
+ "typescript": "^4.7.2"
44
+ }
45
+ }
package/tracing.ts CHANGED
@@ -1,21 +1,14 @@
1
- import {NodeTracerProvider, BatchSpanProcessor} from '@opentelemetry/sdk-trace-node';
1
+ import {NodeTracerProvider} from '@opentelemetry/sdk-trace-node';
2
2
  import {AwsLambdaInstrumentation} from '@opentelemetry/instrumentation-aws-lambda';
3
3
  import {registerInstrumentations} from '@opentelemetry/instrumentation';
4
4
  import {B3_INFO_KEY, UoaB3Propagator} from "./UoaB3Propagator";
5
5
  import {context} from "@opentelemetry/api";
6
6
  import {AlwaysOnSampler} from "@opentelemetry/sdk-trace-base";
7
- import {ZipkinExporter} from "./zipkin/zipkin";
8
7
 
9
8
  const provider = new NodeTracerProvider({sampler: new AlwaysOnSampler()});
10
9
  let infoHeader: string | undefined;
11
10
 
12
- export function initializeTracing(serviceName: string) {
13
- const options = {
14
- url: process.env.zipkinUrl ? process.env.zipkinUrl : 'http://internal-zipkin-uoa-its-nonprod-internal-1407434909.ap-southeast-2.elb.amazonaws.com:443/api/v2/spans',
15
- serviceName: serviceName
16
- }
17
- provider.addSpanProcessor(new BatchSpanProcessor(new ZipkinExporter(options)));
18
-
11
+ export function initializeTracing() {
19
12
  provider.register({
20
13
  propagator: new UoaB3Propagator()
21
14
  });
@@ -34,8 +27,7 @@ export function initializeTracing(serviceName: string) {
34
27
  disableAwsContextPropagation: true
35
28
  })
36
29
  ]
37
- })
38
-
30
+ });
39
31
  }
40
32
 
41
33
  export function getTraceInfoHeader(): string {
package/tsconfig.json CHANGED
@@ -11,7 +11,7 @@
11
11
  // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
12
12
 
13
13
  /* Language and Environment */
14
- "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
14
+ "target": "ES2020", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
15
15
  // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
16
16
  // "jsx": "preserve", /* Specify what JSX code is generated. */
17
17
  // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
@@ -25,7 +25,7 @@
25
25
  // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
26
26
 
27
27
  /* Modules */
28
- "module": "commonjs", /* Specify what module code is generated. */
28
+ "module": "CommonJS", /* Specify what module code is generated. */
29
29
  // "rootDir": "./", /* Specify the root folder within your source files. */
30
30
  // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
31
31
  // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */