From 3983c312be47d2f11456647cd7dcb92cdd85d487 Mon Sep 17 00:00:00 2001 From: Uday K <84223462+ukalbhor@users.noreply.github.com> Date: Tue, 21 Feb 2023 13:07:18 -0800 Subject: [PATCH] feat: add 'metric' logger method to accept otel metrics (#65) * feat: add 'metric' logger method to accept otel metrics * feat: server support to recognize `metrics` from the frontend --- server/server.js | 31 +++++++++++++++++++++++++++++-- src/logger.js | 26 ++++++++++++++++++++++++-- src/types.js | 5 +++++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/server/server.js b/server/server.js index e001366..6be9d6f 100644 --- a/server/server.js +++ b/server/server.js @@ -10,6 +10,11 @@ type ExpressResponse = express$Response; // eslint-disable-line no-undef type Payload = { [string]: string }; +export type Metric = {| + name: string, + dimensions: Payload, +|}; + type Logger = {| log: ( req: ExpressRequest, @@ -19,6 +24,7 @@ type Logger = {| meta?: Payload ) => void, track: (req: ExpressRequest, payload: Payload, meta?: Payload) => void, + metric: (req: ExpressRequest, payload: Metric, meta?: Payload) => void, meta: (req: ExpressRequest, meta: Payload) => void, |}; @@ -66,6 +72,18 @@ export const defaultLogger: Logger = { ); }, + metric(req, metric) { + console.log( + `[metric].${metric.name}\n`, + Object.keys(metric.dimensions) + .map((key) => { + return `\t${key}: ${metric.dimensions[key]}`; + }) + .join("\n"), + "\n" + ); + }, + meta(req, meta) { console.log( "[meta]\n", @@ -85,11 +103,13 @@ export function log( logs: {| events: $ReadOnlyArray, tracking?: $ReadOnlyArray, + metrics?: $ReadOnlyArray, meta?: Meta, |} ) { const events = logs.events || []; const tracking = logs.tracking || []; + const metrics = logs.metrics || []; const meta = logs.meta || {}; if (logger.meta) { @@ -115,6 +135,12 @@ export function log( logger.track(req, track, meta); }); } + + if (logger.metric) { + metrics.forEach((metric) => { + logger.metric(req, metric); + }); + } } type Query = { @@ -126,6 +152,7 @@ type Query = { type Body = {| events: $ReadOnlyArray, tracking?: $ReadOnlyArray, + metrics?: $ReadOnlyArray, meta: Meta, |}; @@ -140,8 +167,8 @@ export function handleRequest(req: ExpressRequest, logger: Logger) { const body: Body = req.body || {}; if (method.toLowerCase() === "post") { - const { events, tracking, meta } = body; - log(req, logger, { events, tracking, meta }); + const { events, tracking, metrics, meta } = body; + log(req, logger, { events, tracking, metrics, meta }); } else { const { event, level = LOG_LEVEL.INFO, ...payload } = query; diff --git a/src/logger.js b/src/logger.js index f3e0a84..f9f25b5 100644 --- a/src/logger.js +++ b/src/logger.js @@ -19,7 +19,7 @@ import { import { LOG_LEVEL, PROTOCOL } from "./constants"; import { extendIfDefined } from "./util"; import { type Transport, getHTTPTransport } from "./http"; -import type { Payload } from "./types"; +import type { Metric, Payload } from "./types"; type LoggerOptions = {| url?: string, @@ -34,6 +34,7 @@ type LoggerOptions = {| type ClientPayload = Payload; type Log = (name: string, payload?: ClientPayload) => LoggerType; // eslint-disable-line no-use-before-define type Track = (payload: ClientPayload) => LoggerType; // eslint-disable-line no-use-before-define +type LogMetric = (payload: Metric) => LoggerType; // eslint-disable-line no-use-before-define type Builder = (Payload) => ClientPayload; type AddBuilder = (Builder) => LoggerType; // eslint-disable-line no-use-before-define @@ -45,6 +46,7 @@ export type LoggerType = {| error: Log, track: Track, + metric: LogMetric, flush: () => ZalgoPromise, immediateFlush: () => ZalgoPromise, @@ -73,6 +75,7 @@ export function Logger({ payload: Payload, |}> = []; let tracking: Array = []; + let metrics: Array = []; const payloadBuilders: Array = []; const metaBuilders: Array = []; @@ -119,7 +122,7 @@ export function Logger({ return; } - if (!events.length && !tracking.length) { + if (!events.length && !tracking.length && !metrics.length) { return; } @@ -144,6 +147,7 @@ export function Logger({ events, meta, tracking, + metrics, }, enableSendBeacon, }).catch(noop); @@ -171,6 +175,7 @@ export function Logger({ events = []; tracking = []; + metrics = []; return ZalgoPromise.resolve(res).then(noop); }); @@ -276,6 +281,22 @@ export function Logger({ return logger; // eslint-disable-line no-use-before-define } + function metric(metricPayload: Metric): LoggerType { + if (!isBrowser()) { + return logger; // eslint-disable-line no-use-before-define + } + + print( + LOG_LEVEL.DEBUG, + `metric.${metricPayload.name}`, + metricPayload.dimensions + ); + + metrics.push(metricPayload); + + return logger; // eslint-disable-line no-use-before-define + } + function setTransport(newTransport: Transport): LoggerType { transport = newTransport; return logger; // eslint-disable-line no-use-before-define @@ -337,6 +358,7 @@ export function Logger({ warn, error, track, + metric, flush, immediateFlush, addPayloadBuilder, diff --git a/src/types.js b/src/types.js index 66a6c84..27578f9 100644 --- a/src/types.js +++ b/src/types.js @@ -1,3 +1,8 @@ /* @flow */ export type Payload = { [string]: string | boolean | null | void }; + +export type Metric = {| + name: string, + dimensions: Payload, +|};