Skip to content

Instantly share code, notes, and snippets.

@binarymax
Created July 3, 2024 17:23
Show Gist options
  • Save binarymax/16ef2ed12d0aa446a6240c5fbb95e2c3 to your computer and use it in GitHub Desktop.
Save binarymax/16ef2ed12d0aa446a6240c5fbb95e2c3 to your computer and use it in GitHub Desktop.

Revisions

  1. binarymax created this gist Jul 3, 2024.
    90 changes: 90 additions & 0 deletions telemetry.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    const Utils = require('./utils');
    const Index = require('../search/index');

    const FILTERS = ['your','filter','fields','here'];

    const Telemetry = {

    // Middleware to start a span before the route controller
    start : function(req, res, next) {
    if(req && !req.span) {
    req.startTime = process.hrtime(); // Capture start time
    let span = {
    'trace_id' : Utils.generateUniqueId(16),
    'span_id' : Utils.generateUniqueId(8),
    'http.method': req.method,
    'http.url': req.originalUrl,
    'http.target': req.url,
    'http.host': req.headers.host,
    'http.scheme': req.protocol,
    'http.user_agent': req.headers['user-agent'],
    'http.route': req.route ? req.route.path : '',
    'timestamp': new Date().toISOString(),
    }
    req.span = span;
    }
    next();
    },

    // Middleware to end the span and log it to OpenSearch after the route controller
    end : function(req, res, next) {
    let span = req.span;
    if (span) {

    res.on('finish',()=>{

    const tookTime = process.hrtime(req.startTime);
    span.took = parseInt((tookTime[0] * 1000) + (tookTime[1] / 1000000)); // Convert to milliseconds

    span['http.status_code'] = res.statusCode
    span['http.response_content_length'] = res.get('content-length') || 0;
    span['http.flavor'] = `HTTP/${req.httpVersion}`;

    if(req.user && typeof req.user =='object') {
    span.organizationid = req.user.organizationid;
    span.userid = req.user.id;
    }

    if(req.params && req.params.id) {
    span.resourceid = req.params.id;
    }

    if(req.query) {
    //Search Query
    ['query','page'].forEach(k=>{
    if(req.query[k]) span[k] = req.query[k];
    });
    let filter = {};
    FILTERS.forEach(k=>{
    if(req.query[k]) filter[k] = req.query[k];
    });
    if (filter) span.filter = JSON.stringify(filter);
    }

    if(res.hits) {
    //Search Results
    let ids = [];
    res.hits.forEach((h)=>{
    if(h&&h.inner_hits&&h.inner_hits.sections.hits.hits){
    h.inner_hits.sections.hits.hits.forEach(ih=>{
    ids.push(
    JSON.stringify({"d":h._source.id,"s":ih._source.id})
    );
    });
    } else {
    ids.push(JSON.stringify({"d":h._source.id}));
    }
    })
    if(ids.length) span.results=ids;
    //console.log(span.results);
    }

    Index.index_log(span);
    })
    }
    //Some routes don't have a 'next'
    if(next) next();
    }
    }

    module.exports = Telemetry;