All Downloads are FREE. Search and download functionalities are using the official Maven repository.

olokia-client-javascript.2.1.0.source-code.jolokia-cubism.js Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
 * Copyright 2012 Roland Huss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Jolokia integration into cubism (https://square.github.io/cubism/)
 *
 * This integration requires the following:
 * - cubism
 * - d3.js
 */
"use strict";

// Uses Node, AMD or browser globals to create a module.
(function (root, factory) {
    if (typeof define === "function" && define.amd) {
        // AMD. Register as an anonymous module.
        define(["cubism", "./jolokia"], factory);
    } else if (typeof module === "object" && module.exports) {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory(require("cubism"), require("./jolokia"));
    } else {
        // Browser globals
        if (root.Jolokia) {
            factory(root.cubism, root.Jolokia);
        } else {
            console.error("No " + (root.cubism ? "Cubism" : "Jolokia") + " definition found. " +
                          "Please include jolokia.js and cubism.js before jolokia-cubism.js");
        }
    }
}(typeof self !== "undefined" ? self : this, function (cubism, Jolokia) {

    var builder = function (cubism,Jolokia) {

        var VERSION = "2.0.3";

        var ctx_jolokia = function (url, opts) {
            var source = {},
                context = this,
                j4p = createAgent(url, opts),
                step = 5e3;                    // 5 seconds by default

            try
            {
                // Connect to start and stop events
                context.on("start",function() {
                    j4p.start();
                });

                context.on("stop",function() {
                    j4p.stop();
                });
            }
            catch(err)
            {
                // Still waiting for pull request https://github.com/square/cubism/pull/19 for supporting
                // "start" and "stop" events
            }

            /**
             * Factory method for create a metric objects which has various variants.
             *
             * If the first argument is a Jolokia request object (i.e. not a function), this request
             * is used for sending requests periodically.
             *
             * If the first argument is a function, this function is used for calculating the numeric value
             * to be plotted. The rest of the arguments can be one or more request objects, which are registered and their
             * responses are put as arguments to the given callback function.
             *
             * The last argument, if an object but not a Jolokia request (i.e. there is no type key), is
             * taken as an option object with the following possible keys:
             *
             * 
    *
  • name: name used in charts
  • *
  • delta: delta value in milliseconds for creating delta (velocity) charts. This is done by * taking the value measured that many milliseconds ago and subtract them from each other.
  • *
  • keepDelay: how many seconds back the fetched values should be kept.
  • *
* * Finally, if the last argument is a pure string, then this string is used as name for the chart. * * @return the metric objects which can be used in Cubism for creating charts. */ source.metric = function () { var values = []; // If the first argument is a function, this callback function is used for calculating the // value of a data point. The remaining arguments should be one or more Jolokia requests objects // and the callback function given will be called with as many response objects after each server query. // The callback function needs to return a single calculated numerical value var name; var argsLen = arguments.length; var options = {}; // Create metric upfront so that it can be used in extraction functions. The name defaults to the mbean name // but can be given as first argument var lastIdx = arguments.length - 1; var lastArg = arguments[lastIdx]; if (typeof lastArg == "string") { name = lastArg; argsLen = lastIdx; } // Options can be given as an object (but not a request with a 'type' property) if (typeof lastArg == "object" && !lastArg.type) { options = lastArg; name = options.name; argsLen = lastIdx; } if (!name && typeof arguments[0] != "function") { name = arguments[0].mbean; } // Metric which maps our previously locally stored values to the ones requested by cubism var metric = context.metric(mapValuesFunc(values, options.keepDelay, context.width), name); if (options.delta) { // Use cubism metric chaining for calculating the difference value and keep care that the // metric keeps old values up to the delta value var prevMetric = metric.shift(-options.delta); metric = metric.subtract(prevMetric); if (name) { metric.toString = function () { return name }; } } // If an extraction function is given, this can be used for fine grained manipulations of // the answer if (typeof arguments[0] == "function") { var func = arguments[0]; var respFunc = function (resp) { var isError = false; for (var i = 0; i < arguments.length; i++) { if (j4p.isError(arguments[i])) { isError = true; break; } } values.unshift( { time:Date.now(), value:isError ? NaN : func.apply(metric, arguments) } ); }; var args = [ respFunc ]; for (var i = 1; i < argsLen; i++) { args.push(arguments[i]); } j4p.register.apply(j4p, args); } else { // Register the argument given directly as a Jolokia request. The request must return a single // numerical value var request = arguments[0]; j4p.register(function (resp) { values.unshift({ time: Date.now(), value:j4p.isError(resp) ? NaN : Number(resp.value) }); }, request); } return metric; }; // Start up fetching of values in the background source.start = function (newStep) { newStep = newStep || step; j4p.start(newStep); }; // Stop fetching of values in the background source.stop = function() { j4p.stop() }; // Check whether the scheduler is running source.isRunning = function() { return j4p.isRunning() }; // Startup poller which will call the agent periodically return source; // ======================================================================================= // Private helper method // Create a new Jolokia agent or reuse a given one function createAgent(url, opts) { if (url instanceof Jolokia) { return url; } else { var args; if (typeof url == "string") { args = {url:url}; if (opts) { for (var key in opts) { if (opts.hasOwnProperty(key)) { args[key] = opts[key]; } } } } else { args = url; } return new Jolokia(args); } } // Generate function which picks the requested values from the values // stored periodically by the Jolokia poller. function mapValuesFunc(values, keepDelay, width) { return function (cStart, cStop, cStep, callback) { cStart = +cStart; cStop = +cStop; var retVals = [], cTime = cStop, vLen = values.length, vIdx = 0, vStart = vLen > 0 ? values[vLen - 1].time : undefined; if (!vLen || cStop < vStart) { // Nothing fetched yet or seeked interval doesn't overlap with stored values --> return only NaNs for (var t = cStart; t <= cStop; t += cStep) { retVals.push(NaN); } return callback(null, retVals); } // Fill up wit NaN until we reach the first stored val while (cTime > values[0].time + cStep) { retVals.unshift(NaN); cTime -= cStep; } while (cTime >= cStart && cTime >= vStart) { // Count down stored values until we find the next best 'fit' // (equals or closest before the step-calculated ime) while (values[vIdx].time > cTime) { vIdx++; } retVals.unshift(values[vIdx].value); cTime -= cStep; } // Finally prepend with 'NaN' for data not yet fetched while (cTime >= cStart) { retVals.unshift(NaN); cTime -= cStep; } // Remove older values if (vLen > width) { if (!keepDelay) { values.length = width; } else { var keepUntil = values[width].time - keepDelay, i = width; while (i < vLen && values[i].time > keepUntil) { i++; } values.length = i; } } callback(null, retVals); } } }; ctx_jolokia.VERSION = VERSION; cubism.context.prototype.jolokia = ctx_jolokia; return ctx_jolokia; }; return builder(cubism, Jolokia); }));




© 2015 - 2024 Weber Informatics LLC | Privacy Policy