diff --git a/Dockerfile.lambda b/Dockerfile.lambda index 3fd0df9..39cff9c 100644 --- a/Dockerfile.lambda +++ b/Dockerfile.lambda @@ -14,5 +14,6 @@ RUN yarn COPY . . ENV MODE=PROD +ENV ENABLE_AMPLITUDE_LOGGING=true CMD [ "index.handler" ] diff --git a/config.js b/config.js index 6e09dff..d2d873e 100644 --- a/config.js +++ b/config.js @@ -38,5 +38,6 @@ module.exports = { awsSesRegion: "eu-north-1", enableJsonLogs: isProd(), maxLimitForPrices: 3000, + enableAmplitudeLogging: getEnv("ENABLE_AMPLITUDE_LOGGING", false), isProd, }; diff --git a/helpers/amplitude-event-logger.js b/helpers/amplitude-event-logger.js new file mode 100644 index 0000000..3bfbde5 --- /dev/null +++ b/helpers/amplitude-event-logger.js @@ -0,0 +1,37 @@ +const Amplitude = require("@amplitude/node"); +const logger = require("./logger"); +const config = require("../config"); + +// Amplitude is a web analytics system. Learn more at https://amplitude.com +// We use it to simply measure get and post reuests to the RedStone Http Api +// and build nice analytics charts + +// Check the analytics dashboard using the link below +// https://analytics.amplitude.com/limestone/dashboard/ttoropr + +const client = Amplitude.init("4990f7285c58e8a009f7818b54fc01eb"); + +function logEvent({ + eventName, + eventProps, + ip, +}) { + if (config.enableAmplitudeLogging) { + logger.info( + `Logging event "${eventName}" in amplitude for ip: "${ip}". With props: ` + + JSON.stringify(eventProps)); + client.logEvent({ + event_type: eventName, + user_id: ip, // Currently we use ip address from request as a unique identifier + // user_id: 'datamonster@gmail.com', // Maybe in future we will use some access tokens as user ids + // location_lat: 37.77, + // location_lng: -122.39, + ip, + event_properties: eventProps, + }); + } +} + +module.exports = { + logEvent, +}; diff --git a/package.json b/package.json index 35a4834..77eba76 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test:ci": "NODE_ENV=test jest --ci --reporters='default' --reporters='./helpers/GithubActionsReporter'" }, "dependencies": { + "@amplitude/node": "^1.9.1", "@vendia/serverless-express": "^4.3.9", "arweave": "^1.10.14", "aws-sdk": "^2.931.0", diff --git a/routes/prices.js b/routes/prices.js index f1a5f25..89fc00e 100644 --- a/routes/prices.js +++ b/routes/prices.js @@ -3,6 +3,7 @@ const _ = require("lodash"); const config = require("../config"); const Price = require("../models/price"); +const { logEvent } = require("../helpers/amplitude-event-logger"); const { assertValidSignature } = require("../helpers/signature-verifier"); const { priceParamsToPriceObj, getProviderFromParams } = require("../utils"); const logger = require("../helpers/logger"); @@ -219,6 +220,13 @@ module.exports = (router) => { // Request validation const params = req.query; + // Saving API read event in amplitude + logEvent({ + eventName: "api-get-request", + eventProps: params, + ip: getIp(req), + }); + // Getting provider details const providerDetails = await getProviderFromParams(params); params.provider = providerDetails.address; @@ -256,6 +264,15 @@ module.exports = (router) => { const reqBody = req.body; let pricesSavedCount = 0; + // Saving API post event in amplitude + logEvent({ + eventName: "api-post-request", + eventProps: { + pricesCount: getPricesCount(reqBody), + }, + ip: getIp(req), + }); + if (Array.isArray(reqBody)) { const invalidPrices = reqBody.filter(p => !p.value); if (invalidPrices.length > 0) { diff --git a/yarn.lock b/yarn.lock index 42d8c23..d13b3bb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,38 @@ # yarn lockfile v1 +"@amplitude/identify@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@amplitude/identify/-/identify-1.9.1.tgz#17e5f0b8615001fd9e10edbbb52eedb4b2794c17" + integrity sha512-SlCa8LoYm1jzMeY+BVxcDmUujh0e6mNpyLIfd3zRRao55v7LHpMn1hSizxEzjeZxHR9cJC0HdSppWDp3V/NXwQ== + dependencies: + "@amplitude/types" "^1.9.1" + "@amplitude/utils" "^1.9.1" + tslib "^1.9.3" + +"@amplitude/node@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@amplitude/node/-/node-1.9.1.tgz#2333506d18a84a10c1cd30ed8620d33c8a953fc3" + integrity sha512-aXAy1P8ydMN2+/p6QMJYvk5OO1T5Ju1llIQnYN9xOtC47a34uXv7iOevPAOpRZOYosy+XkwGFITXU60KBYsEaQ== + dependencies: + "@amplitude/identify" "^1.9.1" + "@amplitude/types" "^1.9.1" + "@amplitude/utils" "^1.9.1" + tslib "^1.9.3" + +"@amplitude/types@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@amplitude/types/-/types-1.9.1.tgz#df614ac6d278c60c39bb49e05014cdcc7e7714e9" + integrity sha512-s10ewnlFjHjNWrUMVTPJ2YRj0eD5UoeL+d0HB01x2Ltae/jFgtHQBS/HGKYV5I+NyiaezjrrZImhAQ72Ww/+8g== + +"@amplitude/utils@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@amplitude/utils/-/utils-1.9.1.tgz#6d127b1a6f0b62c49a932ef00ecd471e554e192f" + integrity sha512-OO2w0gfs5b/dMRKh+PHhtqvb43Uf05MMUWrT3xa62P89mBtmusLvWnWycGdBu750YsnYwX8dfeZpYZ/zLH5ttQ== + dependencies: + "@amplitude/types" "^1.9.1" + tslib "^1.9.3" + "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.14.5": version "7.14.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.14.5.tgz#23b08d740e83f49c5e59945fbf1b43e80bbf4edb" @@ -5161,7 +5193,7 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -tslib@^1.9.0: +tslib@^1.9.0, tslib@^1.9.3: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==