Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
/*
 * (c) Copyright IBM Corp. 2021
 * (c) Copyright Instana Inc. and contributors 2015
 */

'use strict';

const path = require('path');

const slidingWindow = require('@supertenant/core').util.slidingWindow;

const windowOpts = { duration: 1000 };
const minorGcWindow = slidingWindow.create(windowOpts);
const majorGcWindow = slidingWindow.create(windowOpts);
const incrementalMarkingsWindow = slidingWindow.create(windowOpts);
const processWeakCallbacksWindow = slidingWindow.create(windowOpts);
const gcPauseWindow = slidingWindow.create(windowOpts);

/** @type {*} */
let gcStats;
let activateHasBeenCalled = false;
let hasBeenActivated = false;

exports.payloadPrefix = 'gc';

/** @type {{
 * minorGcs: number
 * majorGcs: number
 * incrementalMarkings: number
 * weakCallbackProcessing: number
 * gcPause: number
 * statsSupported?: boolean
 * usedHeapSizeAfterGc?: number
 * }} */
exports.currentPayload = {
  minorGcs: 0,
  majorGcs: 0,
  incrementalMarkings: 0,
  weakCallbackProcessing: 0,
  gcPause: 0,
  statsSupported: false
};

exports.activate = function activate() {
  activateHasBeenCalled = true;
  if (gcStats) {
    actuallyActivate();
  }
};

const nativeModuleLoader = require('./util/nativeModuleRetry')({
  nativeModuleName: 'gcstats.js',
  moduleRoot: path.join(__dirname, '..'),
  message:
    'Could not load gcstats.js. You will not be able to see GC information in Instana for this application. This ' +
    'typically occurs when native addons could not be built during module installation (npm install/yarn) or when ' +
    'npm install --no-optional or yarn --ignore-optional have been used to install dependencies. See the ' +
    'instructions to learn more about the requirements of the collector: ' +
    'https://www.ibm.com/docs/de/obi/current?topic=nodejs-collector-installation#native-add-ons'
});

/** @type {NodeJS.Timeout} */
let senseIntervalHandle;

nativeModuleLoader.once('loaded', gcStats_ => {
  gcStats = gcStats_;
  exports.currentPayload.statsSupported = true;
  if (activateHasBeenCalled) {
    actuallyActivate();
  }
});

nativeModuleLoader.once('failed', () => {
  exports.currentPayload.statsSupported = false;
});

function actuallyActivate() {
  if (hasBeenActivated) {
    return;
  }
  hasBeenActivated = true;
  gcStats.on('stats', (/** @type {*} */ stats) => {
    // gcstats exposes start and end in nanoseconds
    const pause = (stats.end - stats.start) / 1000000;
    gcPauseWindow.addPoint(pause);
    const type = stats.gctype;
    if (type === 1) {
      minorGcWindow.addPoint(1);
    } else if (type === 2) {
      majorGcWindow.addPoint(1);
    } else if (type === 4) {
      incrementalMarkingsWindow.addPoint(1);
    } else if (type === 8) {
      processWeakCallbacksWindow.addPoint(1);
    } else if (type === 15) {
      minorGcWindow.addPoint(1);
      majorGcWindow.addPoint(1);
      incrementalMarkingsWindow.addPoint(1);
      processWeakCallbacksWindow.addPoint(1);
    }
    exports.currentPayload.usedHeapSizeAfterGc = stats.after.usedHeapSize;
  });
  startSensing();
}

function startSensing() {
  senseIntervalHandle = setInterval(() => {
    exports.currentPayload.minorGcs = minorGcWindow.sum();
    exports.currentPayload.majorGcs = majorGcWindow.sum();
    exports.currentPayload.incrementalMarkings = incrementalMarkingsWindow.sum();
    exports.currentPayload.weakCallbackProcessing = processWeakCallbacksWindow.sum();
    exports.currentPayload.gcPause = gcPauseWindow.sum();
  }, 1000);
  senseIntervalHandle.unref();
}

exports.deactivate = function deactivate() {
  if (senseIntervalHandle) {
    clearInterval(senseIntervalHandle);
  }
  activateHasBeenCalled = false;
  hasBeenActivated = false;
};