From 9f0cbc593e47fcb1ac2a4b9703563afacc45bc2d Mon Sep 17 00:00:00 2001 From: Arturs Sosins Date: Sun, 15 Mar 2020 23:54:39 +0200 Subject: [PATCH] Add basic performance trace reporting --- examples/apm_example.js | 43 ++++++++++++++++++++++++++++++++++ lib/countly-bulk-user.js | 37 ++++++++++++++++++++++++++++- lib/countly.js | 50 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 examples/apm_example.js diff --git a/examples/apm_example.js b/examples/apm_example.js new file mode 100644 index 0000000..7a7b551 --- /dev/null +++ b/examples/apm_example.js @@ -0,0 +1,43 @@ +//since we need to test crashing the app +/*global app*/ +var Countly = require("../lib/countly.js"); + +Countly.init({ + app_key: "YOUR_APP_KEY", + url: "https://try.count.ly", //your server goes here + debug: true +}); + +//report app start trace +Countly.report_app_start(); + +//example express middleware +function expressMiddleware(req, res, next) { + var trace = { + type: "network", + name: req.baseUrl + req.path, + stz: Date.now(), + }; + + var processed = false; + + function processRequest() { + if (!processed) { + processed = true; + trace.etz = Date.now(); + trace.apm_metrics = { + response_time: trace.etz - trace.stz, + response_code: res.statusCode + }; + Countly.report_trace(trace); + } + } + + res.on('finish', processRequest); + + res.on('close', processRequest); + + next(); +} + +app.use(expressMiddleware); \ No newline at end of file diff --git a/lib/countly-bulk-user.js b/lib/countly-bulk-user.js index 6dc6f9d..8165f38 100644 --- a/lib/countly-bulk-user.js +++ b/lib/countly-bulk-user.js @@ -406,7 +406,7 @@ function CountlyBulkUser(conf){ * @param {string=} feedback.email - user's email * @param {string=} feedback.comment - user's comment **/ - this.report_feedback = function (feedback) { + this.report_feedback = function (feedback, timestamp) { if (this.check_consent("star-rating")) { if (!feedback.widget_id) { log("Feedback must contain widget_id property"); @@ -423,6 +423,9 @@ function CountlyBulkUser(conf){ count: 1, segmentation: {} }; + if(timestamp){ + event.timestamp = timestamp; + } event.segmentation = getProperties(feedback, props); log("Reporting feedback: ", event); this.add_event(event); @@ -431,6 +434,38 @@ function CountlyBulkUser(conf){ return this; }; + /** + * Report performance trace + * @param {Object} trace - apm trace object + * @param {string} trace.type - device or network + * @param {string} trace.name - url or view of the trace + * @param {number} trace.stz - start timestamp + * @param {number} trace.etz - end timestamp + * @param {Object} trace.app_metrics - key/value metrics like duration, to report with trace where value is number + * @param {Object=} trace.apm_attr - object profiling attributes (not yet supported) + */ + this.report_trace = function (trace) { + if (this.check_consent("apm")) { + var props = ["type", "name", "stz", "etz", "apm_metrics", "apm_attr"]; + for (var i = 0; i < props.length; i++) { + if (props[i] !== "apm_attr" && typeof trace[props[i]] === "undefined") { + log("APM trace must have a", props[i]); + return; + } + } + + var e = getProperties(trace, props); + e.timestamp = trace.stz; + var date = new Date(); + e.hour = date.getHours(); + e.dow = date.getDay(); + var query = prepareQuery({ apm: JSON.stringify(e) }); + log("Adding APM trace: ", e); + conf.server.add_request(query); + } + return this; + }; + /** * Report crash * @param {Object} crash - object containing information about crash and state of device diff --git a/lib/countly.js b/lib/countly.js index becacdd..35110c3 100644 --- a/lib/countly.js +++ b/lib/countly.js @@ -944,6 +944,56 @@ Countly.Bulk = Bulk; Countly.track_view(name, viewSegments); }; + /** + * Report performance trace + * @param {Object} trace - apm trace object + * @param {string} trace.type - device or network + * @param {string} trace.name - url or view of the trace + * @param {number} trace.stz - start timestamp + * @param {number} trace.etz - end timestamp + * @param {Object} trace.app_metrics - key/value metrics like duration, to report with trace where value is number + * @param {Object=} trace.apm_attr - object profiling attributes (not yet supported) + */ + Countly.report_trace = function (trace) { + if (Countly.check_consent("apm")) { + var props = ["type", "name", "stz", "etz", "apm_metrics", "apm_attr"]; + for (var i = 0; i < props.length; i++) { + if (props[i] !== "apm_attr" && typeof trace[props[i]] === "undefined") { + log("APM trace must have a", props[i]); + return; + } + } + + var e = getProperties(trace, props); + e.timestamp = trace.stz; + var date = new Date(); + e.hour = date.getHours(); + e.dow = date.getDay(); + toRequestQueue({ apm: JSON.stringify(e) }); + log("Adding APM trace: ", e); + } + }; + + /** + * Report app start trace + */ + Countly.report_app_start = function () { + //do on next tick to allow synchronous code to load + process.nextTick(function() { + var start = Math.floor(process.uptime() * 1000); + var end = Date.now(); + Countly.report_trace({ + type: "device", + name: process.title || process.argv.join(" "), + stz: start, + etz: end, + app_metrics: { + duration: end - start + } + }); + }); + }; + /** * Make raw request with provided parameters * @example Countly.request({app_key:"somekey", devide_id:"someid", events:"[{'key':'val','count':1}]", begin_session:1});