( function ( $, root, undefined ) { root.rediscache = root.rediscache || {}; var rediscache = root.rediscache; $.extend( rediscache, { metrics: { computed: null, }, chart: null, chart_defaults: { noData: { text: root.rediscache_metrics ? rediscache.l10n.no_data : rediscache.l10n.no_cache, align: 'center', verticalAlign: 'middle', offsetY: -25, style: { color: '#72777c', fontSize: '14px', fontFamily: 'inherit', } }, stroke: { width: [2, 2], curve: 'smooth', dashArray: [0, 8], }, colors: [ '#0096dd', '#72777c', ], annotations: { texts: [{ x: '15%', y: '30%', fontSize: '20px', fontWeight: 600, fontFamily: 'inherit', foreColor: '#72777c', }], }, chart: { type: 'line', height: $( '#metrics-pane #widget-redis-stats' ).length ? '300px' : '100%', toolbar: { show: false }, zoom: { enabled: false }, animations: { enabled: false }, }, dataLabels: { enabled: false, }, legend: { show: false, }, fill: { opacity: [0.25, 1], }, xaxis: { type: 'datetime', labels: { format: 'HH:mm', datetimeUTC: false, style: { colors: '#72777c', fontSize: '13px', fontFamily: 'inherit' }, }, tooltip: { enabled: false }, }, yaxis: { type: 'numeric', tickAmount: 4, min: 0, labels: { style: { colors: '#72777c', fontSize: '13px', fontFamily: 'inherit' }, formatter: function ( value ) { return Math.round( value ); }, }, }, tooltip: { fixed: { enabled: true, position: 'bottomLeft', offsetY: 15, offsetX: 0, }, } }, templates: { tooltip_title: _.template( '
<%- title %>
' ), series_group: _.template( '
' + ' ' + '
' + '
' + ' <%- name %>:' + ' <%- value %>' + '
' + '
' + '
' ), series_pro: _.template( '
' + ' ' + '
' + '
' + ' <%- name %>' + '
' + '
' + '
' ), } } ); // Build the charts by deep extending the chart defaults $.extend( rediscache, { charts: { time: $.extend( true, {}, rediscache.chart_defaults, { yaxis: { labels: { formatter: function ( value ) { return Math.round( value ) + ' ms'; }, }, }, tooltip: { custom: function ({ series, seriesIndex, dataPointIndex, w }) { return [ rediscache.templates.tooltip_title({ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] ) .toTimeString().slice( 0, 5 ), }), rediscache.templates.series_group({ color: rediscache.chart_defaults.colors[0], name: w.globals.seriesNames[0], value: series[0][ dataPointIndex ].toFixed(2) + ' ms', }), rediscache.templates.series_pro({ color: rediscache.chart_defaults.colors[1], name: rediscache.l10n.pro, }), ].join(''); }, }, } ), bytes: $.extend( true, {}, rediscache.chart_defaults, { yaxis: { labels: { formatter: function ( value ) { var i = value === 0 ? 0 : Math.floor( Math.log( value ) / Math.log( 1024 ) ); return parseFloat( (value / Math.pow( 1024, i ) ).toFixed( i ? 2 : 0 ) ) + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i]; }, }, }, tooltip: { custom: function ({ series, seriesIndex, dataPointIndex, w }) { var value = series[0][ dataPointIndex ]; var i = value === 0 ? 0 : Math.floor( Math.log( value ) / Math.log( 1024 ) ); var bytes = parseFloat( (value / Math.pow( 1024, i ) ).toFixed( i ? 2 : 0 ) ) + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i]; return [ rediscache.templates.tooltip_title({ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] ).toTimeString().slice( 0, 5 ), }), rediscache.templates.series_group({ color: rediscache.chart_defaults.colors[0], name: w.globals.seriesNames[0], value: bytes, }), rediscache.templates.series_pro({ color: rediscache.chart_defaults.colors[1], name: rediscache.l10n.pro, }), ].join(''); }, }, } ), ratio: $.extend( true, {}, rediscache.chart_defaults, { yaxis: { max: 100, labels: { formatter: function ( value ) { return Math.round( value ) + '%'; }, }, }, tooltip: { custom: function ({ series, seriesIndex, dataPointIndex, w }) { return [ rediscache.templates.tooltip_title({ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] ) .toTimeString().slice( 0, 5 ), }), rediscache.templates.series_group({ color: rediscache.chart_defaults.colors[0], name: w.globals.seriesNames[0], value: Math.round( series[0][ dataPointIndex ] * 100 ) / 100 + '%', }), ].join(''); }, }, } ), calls: $.extend( true, {}, rediscache.chart_defaults, { tooltip: { custom: function ({ series, seriesIndex, dataPointIndex, w }) { return [ rediscache.templates.tooltip_title({ title: new Date( w.globals.seriesX[ seriesIndex ][ dataPointIndex ] ) .toTimeString().slice( 0, 5 ), }), rediscache.templates.series_group({ color: rediscache.chart_defaults.colors[0], name: w.globals.seriesNames[0], value: Math.round( series[0][ dataPointIndex ] ), }), rediscache.templates.series_pro({ color: rediscache.chart_defaults.colors[1], name: rediscache.l10n.pro, }), ].join(''); }, }, } ), }, } ); var compute_metrics = function ( raw_metrics ) { var metrics = {}; // parse raw metrics in blocks of minutes for ( var entry in raw_metrics ) { var values = {}; var timestamp = raw_metrics[ entry ].timestamp; var minute = ( timestamp - timestamp % 60 ) * 1000; for ( var key in raw_metrics[ entry ] ) { if ( raw_metrics[ entry ].hasOwnProperty( key ) ) { values[ key ] = Number( raw_metrics[ entry ][ key ] ); } } if ( ! metrics[ minute ] ) { metrics[ minute ] = []; } metrics[ minute ].push( values ); } // calculate median value for each block for ( var entry in metrics ) { if ( metrics[ entry ].length === 1 ) { metrics[ entry ] = metrics[ entry ].shift(); continue; } var medians = {}; for ( var key in metrics[ entry ][0] ) { medians[ key ] = compute_median( metrics[ entry ].map( function ( metric ) { return metric[ key ]; } ) ); } metrics[ entry ] = medians; } var computed = []; for ( var timestamp in metrics ) { var entry = metrics[ timestamp ]; entry.date = Number( timestamp ); entry.time = entry.time * 1000; computed.push( entry ); } computed.sort( function( a, b ) { return a.date - b.date; } ); return computed.length < 2 ? [] : computed; }; var compute_median = function ( numbers ) { var median = 0; var numsLen = numbers.length; numbers.sort(); if ( numsLen % 2 === 0 ) { median = ( numbers[ numsLen / 2 - 1 ] + numbers[ numsLen / 2 ] ) / 2; } else { median = numbers[ ( numsLen - 1 ) / 2 ]; } return median; }; var render_chart = function ( id ) { if ( rediscache.chart ) { rediscache.chart.updateOptions( rediscache.charts[ id ] ); return; } var chart = new ApexCharts( document.querySelector( '#redis-stats-chart' ), rediscache.charts[ id ] ); chart.render(); root.rediscache.chart = chart; }; var setup_charts = function () { var metrics = {}; for ( var type in rediscache.charts ) { if ( ! rediscache.charts.hasOwnProperty( type ) ) { continue; } metrics[type] = rediscache.metrics.computed.map( function ( entry ) { return [ entry.date, entry[type] ]; } ); rediscache.charts[type].series = [{ name: rediscache.l10n[type], type: 'area', data: metrics[type], }]; } if ( ! rediscache.disable_pro ) { var pro_charts = { time: function ( entry ) { return [ entry[0], entry[1] * 0.5 ] }, bytes: function ( entry ) { return [ entry[0], entry[1] * 0.3 ] }, calls: function ( entry ) { return [ entry[0], Math.round( entry[1] / 50 ) + 5 ] }, }; for ( var type in pro_charts ) { if ( ! rediscache.charts[type] ) { continue; } rediscache.charts[type].series.push({ name: rediscache.l10n.pro, type: 'line', data: metrics[type].map( pro_charts[type] ), }); } } }; // executed on page load $(function () { var $tabs = $( '#rediscache .nav-tab-wrapper' ); var $panes = $( '#rediscache .content-column .tab-content' ); $tabs.find( 'a' ).on( 'click.redis-cache', function ( event ) { var toggle = $( this ).data( 'toggle' ); $( this ).blur(); show_tab( toggle ); if ( history.pushState ) { history.pushState( null, null, '#' + toggle ); } return false; } ); var firstRender = window.location.hash.indexOf('metrics') === -1; var show_tab = function ( name ) { $tabs.find( '.nav-tab-active' ).removeClass( 'nav-tab-active' ); $panes.find( '.tab-pane.active' ).removeClass( 'active' ); $( '#' + name + '-tab' ).addClass( 'nav-tab-active' ); $( '#' + name + '-pane' ).addClass( 'active' ); if (name === 'metrics' && firstRender) { firstRender = false; render_chart( 'time' ); } }; var show_current_tab = function () { var tabHash = window.location.hash.replace( '#', '' ); if ( tabHash !== '' && $( '#' + tabHash + '-tab' ) ) { show_tab( tabHash ); } }; show_current_tab(); $( window ).on( 'hashchange', show_current_tab ); if ( $( '#widget-redis-stats' ).length ) { rediscache.metrics.computed = compute_metrics( root.rediscache_metrics ); setup_charts(); render_chart( 'time' ); } $( '#widget-redis-stats ul a[data-chart]' ).on( 'click.redis-cache', function ( event ) { event.preventDefault(); $( '#widget-redis-stats .active' ).removeClass( 'active' ); $( this ).blur().addClass( 'active' ); render_chart( $( event.target ).data( 'chart' ) ); } ); $( '.notice.is-dismissible[data-dismissible]' ).on( 'click.roc-dismiss-notice', '.notice-dismiss', function ( event ) { event.preventDefault(); var $parent = $( this ).parent(); $.post( ajaxurl, { notice: $parent.data( 'dismissible' ), action: 'roc_dismiss_notice', _ajax_nonce: $parent.data( 'nonce' ), } ); } ); if ( $( '#redis-cache-copy-button' ).length ) { if ( typeof ClipboardJS === 'undefined' ) { $( '#redis-cache-copy-button' ).remove(); } else { var successTimeout; var clipboard = new ClipboardJS( '#redis-cache-copy-button .copy-button' ); clipboard.on( 'success', function( e ) { var triggerElement = $( e.trigger ), successElement = $( '.success', triggerElement.closest( 'div' ) ); e.clearSelection(); triggerElement.trigger( 'focus' ); clearTimeout( successTimeout ); successElement.removeClass( 'hidden' ); successTimeout = setTimeout( function() { successElement.addClass( 'hidden' ); if ( clipboard.clipboardAction.fakeElem && clipboard.clipboardAction.removeFake ) { clipboard.clipboardAction.removeFake(); } }, 3000 ); } ); } } }); } ( window[ rediscache.jQuery ], window ) );