Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ca177fa
Add safe failure to execution time calculation
timoruppell Nov 10, 2023
255de1c
Fix flow and add observation of non-async wrappees
timoruppell Nov 10, 2023
157acb8
Fix formatting and linter errors
timoruppell Nov 10, 2023
252cace
Bump version
timoruppell Nov 10, 2023
b329aeb
Convert indentation
timoruppell Nov 10, 2023
610c4b5
Remove superfluous checks
timoruppell Nov 10, 2023
f54abad
Fix linter errors
timoruppell Nov 10, 2023
afe703a
Add metadata
timoruppell Nov 10, 2023
4a173b4
Fix TS errors
timoruppell Nov 10, 2023
a3ed551
Update package.json
timoruppell Nov 10, 2023
964e8e8
Add new build
timoruppell Nov 10, 2023
a80ff50
Update README
timoruppell Nov 10, 2023
d4938a6
Update LICENSE
timoruppell Nov 10, 2023
65afc63
Merge branch 'main' into fix-async-bug
timoruppell Nov 10, 2023
c466f06
Update sourcemap
timoruppell Nov 10, 2023
feda74d
Remove additional context
timoruppell Nov 10, 2023
47e48dd
Improve test for async function
timoruppell Nov 10, 2023
087360f
Rebuild
timoruppell Nov 10, 2023
fa57a46
Expand test coverage
timoruppell Nov 15, 2023
28445ec
Fix test to account for very fast execution
timoruppell Nov 15, 2023
f7ca66c
Add more test coverage
timoruppell Nov 15, 2023
37ba3bc
Fix timer
timoruppell Nov 15, 2023
f45c903
Fix variable casing
timoruppell Nov 15, 2023
e5d51c4
Separately test for Promise vs uncalled async function
timoruppell Nov 24, 2023
a68f44d
Add (and ignore) type annotation
timoruppell Nov 24, 2023
390c44c
Rebuild
timoruppell Nov 24, 2023
6ca9881
Add test for Promise wrapping
timoruppell Nov 24, 2023
f56e48f
Remove unused yaml file
timoruppell Nov 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
837 changes: 163 additions & 674 deletions LICENSE

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
# Firetail Javascript Lambda Middleware

# FireTail Javascript Lambda Middleware

### Overview

The purpose of this module is to correctly log out the AWS Lambda event and response payload to allow the firetail extension to then send it on to the firetail logging api
The purpose of this module is to correctly log out the AWS Lambda event and response payload to allow the FireTail extension to then send it on to the FireTail logging API.

[![Code Coverage](https://github.com/FireTail-io/firetail-js-lambda/actions/workflows/codecov.yml/badge.svg)](https://github.com/FireTail-io/firetail-js-lib/actions/workflows/codecov.yml) [![codecov](https://codecov.io/gh/FireTail-io/firetail-js-lambda/branch/main/graph/badge.svg?token=BN44NPKV8H)](https://codecov.io/gh/FireTail-io/firetail-js-lambda) [![License](https://img.shields.io/pypi/l/firetail.svg)](https://github.com/FireTail-io/firetail-js-lambda/blob/main/LICENSE.txt)
[![Code Coverage](https://github.com/FireTail-io/firetail-js-lambda/actions/workflows/codecov.yml/badge.svg)](https://github.com/FireTail-io/firetail-js-lib/actions/workflows/codecov.yml) [![codecov](https://codecov.io/gh/FireTail-io/firetail-js-lambda/branch/main/graph/badge.svg?token=BN44NPKV8H)](https://codecov.io/gh/FireTail-io/firetail-js-lambda)[![License: LGPL v3](https://img.shields.io/badge/License-LGPL_v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)

The [![npm version](https://badge.fury.io/js/@public.firetail.io%2Ffiretail-js-lambda.svg)](https://www.npmjs.com/package/@public.firetail.io/firetail-js-lambda) is a function that wraps around an event handler function in a AWS Lambda to extract the event and response payloads into a base64 logging message.

### Installation
Install the module into your project

Implementing Middleware in lambda function
Install the module into your project.

Implementing Middleware in lambda function:

```js
import * as firetailWrapper from '@public.firetail.io/firetail-js-lambda'
import * as firetailWrapper from "@public.firetail.io/firetail-js-lambda";

module.exports.myFn = firetailWrapper((event,context) => {
module.exports.myFn = firetailWrapper((event, context) => {
// do work here..
return {
statusCode:200,
body: JSON.stringify(data)
statusCode: 200,
body: JSON.stringify(data),
};
});
```
220 changes: 171 additions & 49 deletions __tests__/index.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,181 @@
const Serverless_Events = require('./sampleEvents.json')
const data = require('./animals.json')
const Serverless_Events = require("./sampleEvents.json");
const data = require("./animals.json");
const firetailWrapper = require("../dist");

const timer = t => new Promise(r => setTimeout(() => r(), t));

//=====================================================
//====================================== test GET calls
//=====================================================

describe('test Firetail:Serverless', () => {
describe("test Firetail:Serverless", () => {
test("should work with async lambda function url", done => {
const time = 300;
const next = firetailWrapper(async event => {
await timer(time);
const statusCode = 200;
if (
event.queryStringParameters &&
event.queryStringParameters.limit
) {
return {
statusCode,
body: JSON.stringify(
data.slice(0, event.queryStringParameters.limit),
),
};
}
return {
statusCode,
body: JSON.stringify(data),
};
});

const cLog = console.log;

console.log = txt => {
expect(txt.startsWith("firetail:log-ext:")).toBe(true);
const base64 = txt?.slice(17);
const json = JSON.parse(atob(base64));
expect(json.executionTime).toBeGreaterThan(time - 10);
};
next(Serverless_Events["lambda function url"])
.then(({ statusCode, body }) => {
expect(statusCode).toBe(200);
expect(body).toBe(
'[{"id":1,"name":"Bubbles","tag":"fish"},' +
'{"id":2,"name":"Jax","tag":"cat"},' +
'{"id":3,"name":"Tiger Lily","tag":"cat"},' +
'{"id":4,"name":"Buzz","tag":"dog"},' +
'{"id":5,"name":"Duke","owner":"Tom"}]',
);
return next(Serverless_Events["api Gateway Proxy Event"]);
})
.then(({ statusCode, body }) => {
expect(statusCode).toBe(200);
expect(body).toBe(
'[{"id":1,"name":"Bubbles","tag":"fish"},' +
'{"id":2,"name":"Jax","tag":"cat"}]',
);
console.log = cLog.bind(console);
done();
});
});

test("should work with sync lambda function url", done => {
const next = firetailWrapper(event => {
const statusCode = 200;
if (
event.queryStringParameters &&
event.queryStringParameters.limit
) {
return {
statusCode,
body: JSON.stringify(
data.slice(0, event.queryStringParameters.limit),
),
};
}
return {
statusCode,
body: JSON.stringify(data),
};
});

const cLog = console.log;

console.log = txt => {
expect(txt.startsWith("firetail:log-ext:")).toBe(true);
const base64 = txt?.slice(17);
const json = JSON.parse(atob(base64));
expect(json.executionTime).toBeLessThan(10);
};
next(Serverless_Events["lambda function url"])
.then(({ statusCode, body }) => {
expect(statusCode).toBe(200);
expect(body).toBe(
'[{"id":1,"name":"Bubbles","tag":"fish"},' +
'{"id":2,"name":"Jax","tag":"cat"},' +
'{"id":3,"name":"Tiger Lily","tag":"cat"},' +
'{"id":4,"name":"Buzz","tag":"dog"},' +
'{"id":5,"name":"Duke","owner":"Tom"}]',
);
return next(Serverless_Events["api Gateway Proxy Event"]);
})
.then(({ statusCode, body }) => {
expect(statusCode).toBe(200);
expect(body).toBe(
'[{"id":1,"name":"Bubbles","tag":"fish"},' +
'{"id":2,"name":"Jax","tag":"cat"}]',
);
console.log = cLog.bind(console);
done();
});
});

test("should not throw with non-function lambda function url", done => {
const next = firetailWrapper({
statusCode: 200,
body: "some body",
});

test('should work with lambda function url', done => {
const cLog = console.log;

const next = firetailWrapper((event) => {
const statusCode = 200
if(event.queryStringParameters
&& event.queryStringParameters.limit){
return {
statusCode,
body: JSON.stringify(data.slice(0, event.queryStringParameters.limit)),
};
console.log = txt => {
expect(txt.startsWith("firetail:log-ext:")).toBe(true);
const base64 = txt?.slice(17);
const json = JSON.parse(atob(base64));
expect(json.executionTime).toBeLessThan(10);
};
next(Serverless_Events["lambda function url"]).then(
({ statusCode, body }) => {
expect(statusCode).toBe(200);
expect(body).toBe("some body");
done();
},
);
});

test("should not throw when Date() does not work or status code is not found", done => {
const next = firetailWrapper({
statusCode: null,
body: "some body",
});

const d = Date;

class C {
constructor(x, y) {
this.x = x;
this.y = y;
}
foo() {
return this.x + this.y;
}
}
return {
statusCode,
body: JSON.stringify(data),

Date = class D {
constructor() {}
getTime() {
return "not a date";
}
};

const cLog = console.log;

console.log = txt => {
expect(txt.startsWith("firetail:log-ext:")).toBe(true);
const base64 = txt?.slice(17);
const json = JSON.parse(atob(base64));
expect(json.executionTime).toBe(0);
expect(json.response.statusCode).toBe(200);
};
});

const cLog = console.log

console.log = (txt)=>{
expect(txt.startsWith("firetail:log-ext:")).toBe(true);
const payload = JSON.parse(Buffer.from(txt.slice(17), "base64").toString("ascii"));
expect(payload).toHaveProperty('execution_time');
expect(payload).toHaveProperty('event');
expect(payload).toHaveProperty('response');
expect(payload.response).toHaveProperty('statusCode');
expect(payload.response).toHaveProperty('body');
}

next(Serverless_Events["lambda function url"])
.then((a)=>{
const {statusCode,body} = a
expect(statusCode).toBe(200);
expect(body).toBe('[{"id":1,"name":"Bubbles","tag":"fish"},'+
'{"id":2,"name":"Jax","tag":"cat"},'+
'{"id":3,"name":"Tiger Lily","tag":"cat"},'+
'{"id":4,"name":"Buzz","tag":"dog"},'+
'{"id":5,"name":"Duke","owner":"Tom"}]')
return next(Serverless_Events["api Gateway Proxy Event"])
}).then(({statusCode,body})=>{
expect(statusCode).toBe(200);
expect(body).toBe('[{"id":1,"name":"Bubbles","tag":"fish"},'+
'{"id":2,"name":"Jax","tag":"cat"}]')
console.log = cLog.bind(console)
done()
})

})
})
next(Serverless_Events["lambda function url"]).then(
({ statusCode, body }) => {
expect(statusCode).toBe(null);
expect(body).toBe("some body");
done();
},
);
});
});
6 changes: 4 additions & 2 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { APIGatewayProxyEvent, APIGatewayProxyEventV2, Context } from 'aws-lambda';
declare function wrap(next: Function): (event: APIGatewayProxyEvent | APIGatewayProxyEventV2, context: Context) => any;
import { APIGatewayProxyEvent, APIGatewayProxyEventV2, Context } from "aws-lambda";
declare function wrap(next: Function & {
then?: Function;
}): (event: APIGatewayProxyEvent | APIGatewayProxyEventV2, context: Context) => any;
export = wrap;
33 changes: 21 additions & 12 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@public.firetail.io/firetail-js-lambda",
"version": "1.0.1",
"main":"dist/index.js",
"main": "dist/index.js",
"description": "Simple code example for the logging of lambda requests",
"scripts": {
"build": "tsc",
Expand All @@ -15,7 +15,6 @@
"type": "git",
"url": "git+https://github.com/FireTail-io/firetail-js-lambda.git"
},
"author": "Brian Shannon",
"license": "LGPL",
"bugs": {
"url": "https://github.com/FireTail-io/firetail-js-lambda/issues"
Expand Down
Loading