sidekiq 6.5.4 → 6.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- checksums.yaml +4 -4
 - data/Changes.md +6 -0
 - data/lib/sidekiq/job_retry.rb +1 -0
 - data/lib/sidekiq/metrics/deploy.rb +2 -2
 - data/lib/sidekiq/metrics/query.rb +102 -73
 - data/lib/sidekiq/version.rb +1 -1
 - data/lib/sidekiq/web/action.rb +3 -3
 - data/lib/sidekiq/web/application.rb +7 -7
 - data/lib/sidekiq/web.rb +1 -1
 - data/web/assets/javascripts/chart.min.js +13 -0
 - data/web/assets/javascripts/chartjs-plugin-annotation.min.js +7 -0
 - data/web/assets/javascripts/metrics.js +262 -0
 - data/web/assets/stylesheets/application.css +44 -1
 - data/web/locales/el.yml +43 -19
 - data/web/locales/en.yml +4 -1
 - data/web/views/metrics.erb +47 -37
 - data/web/views/metrics_for_job.erb +77 -82
 - metadata +5 -2
 
| 
         @@ -0,0 +1,7 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            /*!
         
     | 
| 
      
 2 
     | 
    
         
            +
            * chartjs-plugin-annotation v2.0.0
         
     | 
| 
      
 3 
     | 
    
         
            +
            * https://www.chartjs.org/chartjs-plugin-annotation/index
         
     | 
| 
      
 4 
     | 
    
         
            +
             * (c) 2022 chartjs-plugin-annotation Contributors
         
     | 
| 
      
 5 
     | 
    
         
            +
             * Released under the MIT License
         
     | 
| 
      
 6 
     | 
    
         
            +
             */
         
     | 
| 
      
 7 
     | 
    
         
            +
            !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("chart.js"),require("chart.js/helpers")):"function"==typeof define&&define.amd?define(["chart.js","chart.js/helpers"],e):(t="undefined"!=typeof globalThis?globalThis:t||self)["chartjs-plugin-annotation"]=e(t.Chart,t.Chart.helpers)}(this,(function(t,e){"use strict";const o={modes:{point:(t,e)=>r(t,e,{intersect:!0}),nearest:(t,o,n)=>function(t,o,n){let i=Number.POSITIVE_INFINITY;return r(t,o,n).reduce(((t,r)=>{const s=r.getCenterPoint(),a=function(t,e,o){if("x"===o)return{x:t.x,y:e.y};if("y"===o)return{x:e.x,y:t.y};return e}(o,s,n.axis),d=e.distanceBetweenPoints(o,a);return d<i?(t=[r],i=d):d===i&&t.push(r),t}),[]).sort(((t,e)=>t._index-e._index)).slice(0,1)}(t,o,n),x:(t,e,o)=>r(t,e,{intersect:o.intersect,axis:"x"}),y:(t,e,o)=>r(t,e,{intersect:o.intersect,axis:"y"})}};function n(t,e,n){return(o.modes[n.mode]||o.modes.nearest)(t,e,n)}function r(t,e,o){return t.visibleElements.filter((t=>o.intersect?t.inRange(e.x,e.y):function(t,e,o){return"x"!==o&&"y"!==o?t.inRange(e.x,e.y,"x",!0)||t.inRange(e.x,e.y,"y",!0):t.inRange(e.x,e.y,o,!0)}(t,e,o.axis)))}const i=["enter","leave"],s=i.concat("click");function a(t,e,o){if(t.listened)switch(e.type){case"mousemove":case"mouseout":return function(t,e,o){if(!t.moveListened)return;let r;r="mousemove"===e.type?n(t,e,o.interaction):[];const i=t.hovered;t.hovered=r;const s={state:t,event:e};let a=d(s,"leave",i,r);return d(s,"enter",r,i)||a}(t,e,o);case"click":return function(t,e,o){const r=t.listeners,i=n(t,e,o.interaction);let s;for(const t of i)s=l(t.options.click||r.click,t,e)||s;return s}(t,e,o)}}function d({state:t,event:e},o,n,r){let i;for(const s of n)r.indexOf(s)<0&&(i=l(s.options[o]||t.listeners[o],s,e)||i);return i}function l(t,o,n){return!0===e.callback(t,[o.$context,n])}const c=(t,e)=>e>t||t.length>e.length&&t.slice(0,e.length)===e,h=.001,u=(t,e,o)=>Math.min(o,Math.max(e,t));function f(t,e,o){for(const n of Object.keys(t))t[n]=u(t[n],e,o);return t}function x(t,{x:e,y:o,x2:n,y2:r},i,s){const a=s/2,d=t.x>=e-a-h&&t.x<=n+a+h,l=t.y>=o-a-h&&t.y<=r+a+h;return"x"===i?d:("y"===i||d)&&l}function y(t,e){const{centerX:o,centerY:n}=t.getProps(["centerX","centerY"],e);return{x:o,y:n}}const p=t=>"string"==typeof t&&t.endsWith("%"),b=t=>u(parseFloat(t)/100,0,1);function g(t,e){return"start"===e?0:"end"===e?t:p(e)?b(e)*t:t/2}function m(t,e){return"number"==typeof e?e:p(e)?b(e)*t:t}function w(t){return e.isObject(t)?{x:e.valueOrDefault(t.x,"center"),y:e.valueOrDefault(t.y,"center")}:{x:t=e.valueOrDefault(t,"center"),y:t}}function v(t){return t&&(e.defined(t.xValue)||e.defined(t.yValue))}const S=new Map;function M(t){if(t&&"object"==typeof t){const e=t.toString();return"[object HTMLImageElement]"===e||"[object HTMLCanvasElement]"===e}}function C(t,{x:o,y:n},r){r&&(t.translate(o,n),t.rotate(e.toRadians(r)),t.translate(-o,-n))}function D(t,e){if(e&&e.borderWidth)return t.lineCap=e.borderCapStyle,t.setLineDash(e.borderDash),t.lineDashOffset=e.borderDashOffset,t.lineJoin=e.borderJoinStyle,t.lineWidth=e.borderWidth,t.strokeStyle=e.borderColor,!0}function j(t,e){t.shadowColor=e.backgroundShadowColor,t.shadowBlur=e.shadowBlur,t.shadowOffsetX=e.shadowOffsetX,t.shadowOffsetY=e.shadowOffsetY}function k(t,o){const n=o.content;if(M(n))return{width:m(n.width,o.width),height:m(n.height,o.height)};const r=e.toFont(o.font),i=o.textStrokeWidth,s=e.isArray(n)?n:[n],a=s.join()+r.string+i+(t._measureText?"-spriting":"");if(!S.has(a)){t.save(),t.font=r.string;const e=s.length;let o=0;for(let n=0;n<e;n++){const e=s[n];o=Math.max(o,t.measureText(e).width+i)}t.restore();const n=e*r.lineHeight+i;S.set(a,{width:o,height:n})}return S.get(a)}function P(t,o,n){const{x:r,y:i,width:s,height:a}=o;t.save(),j(t,n);const d=D(t,n);t.fillStyle=n.backgroundColor,t.beginPath(),e.addRoundedRectPath(t,{x:r,y:i,w:s,h:a,radius:f(e.toTRBLCorners(n.borderRadius),0,Math.min(s,a)/2)}),t.closePath(),t.fill(),d&&(t.shadowColor=n.borderShadowColor,t.stroke()),t.restore()}function O(t,o,n){return o="number"==typeof o?o:t.parse(o),e.isFinite(o)?t.getPixelForValue(o):n}function A(t,e,o){const n=e[o];if(n||"scaleID"===o)return n;const r=o.charAt(0),i=Object.values(t).filter((t=>t.axis&&t.axis===r));return i.length?i[0].id:r}function I(t,e){if(t){const o=t.options.reverse;return{start:O(t,e.min,o?e.end:e.start),end:O(t,e.max,o?e.start:e.end)}}}function Y(t,e){const{chartArea:o,scales:n}=t,r=n[A(n,e,"xScaleID")],i=n[A(n,e,"yScaleID")];let s=o.width/2,a=o.height/2;return r&&(s=O(r,e.xValue,r.left+r.width/2)),i&&(a=O(i,e.yValue,i.top+i.height/2)),{x:s,y:a}}function R(t,e){const o=t.scales,n=o[A(o,e,"xScaleID")],r=o[A(o,e,"yScaleID")];if(!n&&!r)return{};let{left:i,right:s}=n||t.chartArea,{top:a,bottom:d}=r||t.chartArea;const l=X(n,{min:e.xMin,max:e.xMax,start:i,end:s});i=l.start,s=l.end;const c=X(r,{min:e.yMin,max:e.yMax,start:d,end:a});return a=c.start,d=c.end,{x:i,y:a,x2:s,y2:d,width:s-i,height:d-a,centerX:i+(s-i)/2,centerY:a+(d-a)/2}}function W(t,e){if(!v(e)){const o=R(t,e);let n=e.radius;n&&!isNaN(n)||(n=Math.min(o.width,o.height)/2,e.radius=n);const r=2*n;return{x:o.x+e.xAdjust,y:o.y+e.yAdjust,x2:o.x+r+e.xAdjust,y2:o.y+r+e.yAdjust,centerX:o.centerX+e.xAdjust,centerY:o.centerY+e.yAdjust,width:r,height:r}}return function(t,e){const o=Y(t,e),n=2*e.radius;return{x:o.x-e.radius+e.xAdjust,y:o.y-e.radius+e.yAdjust,x2:o.x+e.radius+e.xAdjust,y2:o.y+e.radius+e.yAdjust,centerX:o.x+e.xAdjust,centerY:o.y+e.yAdjust,width:n,height:n}}(t,e)}function X(t,e){const o=I(t,e)||e;return{start:Math.min(o.start,o.end),end:Math.max(o.start,o.end)}}function E(t,e,o){const n=Math.cos(o),r=Math.sin(o),i=e.x,s=e.y;return{x:i+n*(t.x-i)-r*(t.y-s),y:s+r*(t.x-i)+n*(t.y-s)}}function T(t,o,n){const r=function(t,o,n){const r=o.axis,i=o.id,s=r+"ScaleID",a={min:e.valueOrDefault(o.min,Number.NEGATIVE_INFINITY),max:e.valueOrDefault(o.max,Number.POSITIVE_INFINITY)};for(const e of n)e.scaleID===i?V(e,o,["value","endValue"],a):A(t,e,s)===i&&V(e,o,[r+"Min",r+"Max",r+"Value"],a);return a}(t.scales,o,n);let i=z(o,r,"min","suggestedMin");i=z(o,r,"max","suggestedMax")||i,i&&"function"==typeof o.handleTickRangeOptions&&o.handleTickRangeOptions()}function z(t,o,n,r){if(e.isFinite(o[n])&&!function(t,o,n){return e.defined(t[o])||e.defined(t[n])}(t.options,n,r)){const e=t[n]!==o[n];return t[n]=o[n],e}}function _(t,e){for(const o of["scaleID","xScaleID","yScaleID"]){const n=A(e,t,o);n&&!e[n]&&N(t,o)&&console.warn(`No scale found with id '${n}' for annotation '${t.id}'`)}}function N(t,o){if("scaleID"===o)return!0;const n=o.charAt(0);for(const o of["Min","Max","Value"])if(e.defined(t[n+o]))return!0;return!1}function V(t,o,n,r){for(const i of n){const n=t[i];if(e.defined(n)){const t=o.parse(n);r.min=Math.min(r.min,t),r.max=Math.max(r.max,t)}}}class B extends t.Element{inRange(t,o,n,r){const{x:i,y:s}=E({x:t,y:o},this.getCenterPoint(r),e.toRadians(-this.options.rotation));return x({x:i,y:s},this.getProps(["x","y","x2","y2"],r),n,this.options.borderWidth)}getCenterPoint(t){return y(this,t)}draw(t){t.save(),C(t,this.getCenterPoint(),this.options.rotation),P(t,this,this.options),t.restore()}get label(){return this.elements&&this.elements[0]}resolveElementProperties(t,e){const o=R(t,e),{x:n,y:r}=o;return o.elements=[{type:"label",optionScope:"label",properties:L(t,o,e)}],o.initProperties={x:n,y:r},o}}function H(t,e){const{start:o,end:n,borderWidth:r}=t,{position:i,padding:{start:s,end:a},adjust:d}=e;return o+r/2+d+g(n-r-o-s-a-e.size,i)}function L(t,o,n){const r=n.label;r.backgroundColor="transparent",r.callout.display=!1;const i=w(r.position),s=e.toPadding(r.padding),a=k(t.ctx,r),d=function({properties:t,options:e},o,n,r){const{x:i,x2:s,width:a}=t;return H({start:i,end:s,size:a,borderWidth:e.borderWidth},{position:n.x,padding:{start:r.left,end:r.right},adjust:e.label.xAdjust,size:o.width})}({properties:o,options:n},a,i,s),l=function({properties:t,options:e},o,n,r){const{y:i,y2:s,height:a}=t;return H({start:i,end:s,size:a,borderWidth:e.borderWidth},{position:n.y,padding:{start:r.top,end:r.bottom},adjust:e.label.yAdjust,size:o.height})}({properties:o,options:n},a,i,s),c=a.width+s.width,h=a.height+s.height;return{x:d,y:l,x2:d+c,y2:l+h,width:c,height:h,centerX:d+c/2,centerY:l+h/2,rotation:r.rotation}}B.id="boxAnnotation",B.defaults={adjustScaleRange:!0,backgroundShadowColor:"transparent",borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderRadius:0,borderShadowColor:"transparent",borderWidth:1,display:!0,label:{backgroundColor:"transparent",borderWidth:0,callout:{display:!1},color:"black",content:null,display:!1,drawTime:void 0,font:{family:void 0,lineHeight:void 0,size:void 0,style:void 0,weight:"bold"},height:void 0,padding:6,position:"center",rotation:void 0,textAlign:"start",textStrokeColor:void 0,textStrokeWidth:0,width:void 0,xAdjust:0,yAdjust:0,z:void 0},rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,xMax:void 0,xMin:void 0,xScaleID:void 0,yMax:void 0,yMin:void 0,yScaleID:void 0,z:0},B.defaultRoutes={borderColor:"color",backgroundColor:"color"},B.descriptors={label:{_fallback:!0}};const $=(t,e,o)=>({x:t.x+o*(e.x-t.x),y:t.y+o*(e.y-t.y)}),F=(t,e,o)=>$(e,o,Math.abs((t-e.y)/(o.y-e.y))).x,J=(t,e,o)=>$(e,o,Math.abs((t-e.x)/(o.x-e.x))).y,q=t=>t*t;class U extends t.Element{inRange(t,e,o,n){const r=this.options.borderWidth/2;if("x"!==o&&"y"!==o){const o={mouseX:t,mouseY:e};return function(t,{mouseX:e,mouseY:o},n=.001,r){const{x:i,y:s,x2:a,y2:d}=t.getProps(["x","y","x2","y2"],r),l=a-i,c=d-s,h=q(l)+q(c),u=0===h?-1:((e-i)*l+(o-s)*c)/h;let f,x;u<0?(f=i,x=s):u>1?(f=a,x=d):(f=i+u*l,x=s+u*c);return q(e-f)+q(o-x)<=n}(this,o,q(r),n)||Q(this,o,n)}const i=((t,e,{x:o,y:n,x2:r,y2:i},s)=>"y"===s?{start:Math.min(n,i),end:Math.max(n,i),value:e}:{start:Math.min(o,r),end:Math.max(o,r),value:t})(t,e,this.getProps(["x","y","x2","y2"],n),o);return i.value>=i.start-r&&i.value<=i.end+r||Q(this,{mouseX:t,mouseY:e},n,o)}getCenterPoint(t){return y(this,t)}draw(t){const{x:e,y:o,x2:n,y2:r,options:i}=this;if(t.save(),!D(t,i))return t.restore();j(t,i);const s=Math.atan2(r-o,n-e),a=Math.sqrt(Math.pow(n-e,2)+Math.pow(r-o,2)),{startOpts:d,endOpts:l,startAdjust:c,endAdjust:h}=function(t){const e=t.options,o=e.arrowHeads&&e.arrowHeads.start,n=e.arrowHeads&&e.arrowHeads.end;return{startOpts:o,endOpts:n,startAdjust:nt(t,o),endAdjust:nt(t,n)}}(this);t.translate(e,o),t.rotate(s),t.beginPath(),t.moveTo(0+c,0),t.lineTo(a-h,0),t.shadowColor=i.borderShadowColor,t.stroke(),rt(t,0,c,d),rt(t,a,-h,l),t.restore()}get label(){return this.elements&&this.elements[0]}resolveElementProperties(t,e){const{scales:o,chartArea:n}=t,r=o[e.scaleID],i={x:n.left,y:n.top,x2:n.right,y2:n.bottom};let s,a;if(r)s=O(r,e.value,NaN),a=O(r,e.endValue,s),r.isHorizontal()?(i.x=s,i.x2=a):(i.y=s,i.y2=a);else{const t=o[A(o,e,"xScaleID")],n=o[A(o,e,"yScaleID")];t&&Z(i,t,{min:e.xMin,max:e.xMax,start:t.left,end:t.right,startProp:"x",endProp:"x2"}),n&&Z(i,n,{min:e.yMin,max:e.yMax,start:n.bottom,end:n.top,startProp:"y",endProp:"y2"})}const{x:d,y:l,x2:c,y2:h}=i,u=function({x:t,y:e,x2:o,y2:n},{top:r,right:i,bottom:s,left:a}){return!(t<a&&o<a||t>i&&o>i||e<r&&n<r||e>s&&n>s)}(i,t.chartArea),f=u?function(t,e,o){const{x:n,y:r}=K(t,e,o),{x:i,y:s}=K(e,t,o);return{x:n,y:r,x2:i,y2:s,width:Math.abs(i-n),height:Math.abs(s-r)}}({x:d,y:l},{x:c,y:h},t.chartArea):{x:d,y:l,x2:c,y2:h,width:Math.abs(c-d),height:Math.abs(h-l)};return f.centerX=(c+d)/2,f.centerY=(h+l)/2,u||(e.label.display=!1),f.elements=[{type:"label",optionScope:"label",properties:tt(t,f,e.label)}],f}}U.id="lineAnnotation";const G={backgroundColor:void 0,backgroundShadowColor:void 0,borderColor:void 0,borderDash:void 0,borderDashOffset:void 0,borderShadowColor:void 0,borderWidth:void 0,display:void 0,fill:void 0,length:void 0,shadowBlur:void 0,shadowOffsetX:void 0,shadowOffsetY:void 0,width:void 0};function K({x:t,y:e},o,{top:n,right:r,bottom:i,left:s}){return t<s&&(e=J(s,{x:t,y:e},o),t=s),t>r&&(e=J(r,{x:t,y:e},o),t=r),e<n&&(t=F(n,{x:t,y:e},o),e=n),e>i&&(t=F(i,{x:t,y:e},o),e=i),{x:t,y:e}}function Q(t,{mouseX:e,mouseY:o},n,r){const i=t.label;return i.options.display&&i.inRange(e,o,r,n)}function Z(t,e,o){const n=I(e,o);t[o.startProp]=n.start,t[o.endProp]=n.end}function tt(t,o,n){n.callout.display=!1;const r=n.borderWidth,i=e.toPadding(n.padding),s=k(t.ctx,n);return function(t,o,n,r){const{width:i,height:s,padding:a}=n,{xAdjust:d,yAdjust:l}=o,c={x:t.x,y:t.y},h={x:t.x2,y:t.y2},u="auto"===o.rotation?function(t){const{x:o,y:n,x2:r,y2:i}=t,s=Math.atan2(i-n,r-o);return s>e.PI/2?s-e.PI:s<e.PI/-2?s+e.PI:s}(t):e.toRadians(o.rotation),f=function(t,e,o){const n=Math.cos(o),r=Math.sin(o);return{w:Math.abs(t*n)+Math.abs(e*r),h:Math.abs(t*r)+Math.abs(e*n)}}(i,s,u),x=function(t,e,o,n){let r;const i=function(t,e){const{x:o,x2:n,y:r,y2:i}=t,s=Math.min(r,i)-e.top,a=Math.min(o,n)-e.left,d=e.bottom-Math.max(r,i),l=e.right-Math.max(o,n);return{x:Math.min(a,l),y:Math.min(s,d),dx:a<=l?1:-1,dy:s<=d?1:-1}}(t,n);r="start"===e.position?et({w:t.x2-t.x,h:t.y2-t.y},o,e,i):"end"===e.position?1-et({w:t.x-t.x2,h:t.y-t.y2},o,e,i):g(1,e.position);return r}(t,o,{labelSize:f,padding:a},r),y=$(c,h,x),p={size:f.w,min:r.left,max:r.right,padding:a.left},b={size:f.h,min:r.top,max:r.bottom,padding:a.top},m=ot(y.x,p)+d,w=ot(y.y,b)+l;return{x:m-i/2,y:w-s/2,x2:m+i/2,y2:w+s/2,centerX:m,centerY:w,width:i,height:s,rotation:e.toDegrees(u)}}(o,n,{width:s.width+i.width+r,height:s.height+i.height+r,padding:i},t.chartArea)}function et(t,e,o,n){const{labelSize:r,padding:i}=e,s=t.w*n.dx,a=t.h*n.dy,d=s>0&&(r.w/2+i.left-n.x)/s,l=a>0&&(r.h/2+i.top-n.y)/a;return u(Math.max(d,l),0,.25)}function ot(t,e){const{size:o,min:n,max:r,padding:i}=e,s=o/2;return o>r-n?(r+n)/2:(n>=t-i-s&&(t=n+i+s),r<=t+i+s&&(t=r-i-s),t)}function nt(t,e){if(!e||!e.display)return 0;const{length:o,width:n}=e,r=t.options.borderWidth/2,i={x:o,y:n+r},s={x:0,y:r};return Math.abs(F(0,i,s))}function rt(t,e,o,n){if(!n||!n.display)return;const{length:r,width:i,fill:s,backgroundColor:a,borderColor:d}=n,l=Math.abs(e-r)+o;t.beginPath(),j(t,n),D(t,n),t.moveTo(l,-i),t.lineTo(e+o,0),t.lineTo(l,i),!0===s?(t.fillStyle=a||d,t.closePath(),t.fill(),t.shadowColor="transparent"):t.shadowColor=n.borderShadowColor,t.stroke()}U.defaults={adjustScaleRange:!0,arrowHeads:{display:!1,end:Object.assign({},G),fill:!1,length:12,start:Object.assign({},G),width:6},borderDash:[],borderDashOffset:0,borderShadowColor:"transparent",borderWidth:2,display:!0,endValue:void 0,label:{backgroundColor:"rgba(0,0,0,0.8)",backgroundShadowColor:"transparent",borderCapStyle:"butt",borderColor:"black",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderRadius:6,borderShadowColor:"transparent",borderWidth:0,callout:{display:!1},color:"#fff",content:null,display:!1,drawTime:void 0,font:{family:void 0,lineHeight:void 0,size:void 0,style:void 0,weight:"bold"},height:void 0,padding:6,position:"center",rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,textAlign:"center",textStrokeColor:void 0,textStrokeWidth:0,width:void 0,xAdjust:0,yAdjust:0,z:void 0},scaleID:void 0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,value:void 0,xMax:void 0,xMin:void 0,xScaleID:void 0,yMax:void 0,yMin:void 0,yScaleID:void 0,z:0},U.descriptors={arrowHeads:{start:{_fallback:!0},end:{_fallback:!0},_fallback:!0}},U.defaultRoutes={borderColor:"color"};class it extends t.Element{inRange(t,o,n,r){const i=this.options.rotation,s=this.options.borderWidth;if("x"!==n&&"y"!==n)return function(t,o,n,r){const{width:i,height:s,centerX:a,centerY:d}=o,l=i/2,c=s/2;if(l<=0||c<=0)return!1;const h=e.toRadians(n||0),u=r/2||0,f=Math.cos(h),x=Math.sin(h),y=Math.pow(f*(t.x-a)+x*(t.y-d),2),p=Math.pow(x*(t.x-a)-f*(t.y-d),2);return y/Math.pow(l+u,2)+p/Math.pow(c+u,2)<=1.0001}({x:t,y:o},this.getProps(["width","height","centerX","centerY"],r),i,s);const{x:a,y:d,x2:l,y2:c}=this.getProps(["x","y","x2","y2"],r),u=s/2,f="y"===n?{start:d,end:c}:{start:a,end:l},x=E({x:t,y:o},this.getCenterPoint(r),e.toRadians(-i));return x[n]>=f.start-u-h&&x[n]<=f.end+u+h}getCenterPoint(t){return y(this,t)}draw(t){const{width:o,height:n,centerX:r,centerY:i,options:s}=this;t.save(),C(t,this.getCenterPoint(),s.rotation),j(t,this.options),t.beginPath(),t.fillStyle=s.backgroundColor;const a=D(t,s);t.ellipse(r,i,n/2,o/2,e.PI/2,0,2*e.PI),t.fill(),a&&(t.shadowColor=s.borderShadowColor,t.stroke()),t.restore()}resolveElementProperties(t,e){return R(t,e)}}it.id="ellipseAnnotation",it.defaults={adjustScaleRange:!0,backgroundShadowColor:"transparent",borderDash:[],borderDashOffset:0,borderShadowColor:"transparent",borderWidth:1,display:!0,rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,xMax:void 0,xMin:void 0,xScaleID:void 0,yMax:void 0,yMin:void 0,yScaleID:void 0,z:0},it.defaultRoutes={borderColor:"color",backgroundColor:"color"};const st=["left","bottom","top","right"];class at extends t.Element{inRange(t,o,n,r){const{x:i,y:s}=E({x:t,y:o},this.getCenterPoint(r),e.toRadians(-this.rotation));return x({x:i,y:s},this.getProps(["x","y","x2","y2"],r),n,this.options.borderWidth)}getCenterPoint(t){return y(this,t)}draw(t){const o=this.options;o.display&&o.content&&(t.save(),C(t,this.getCenterPoint(),this.rotation),function(t,o){const{pointX:n,pointY:r,options:i}=o,s=i.callout,a=s&&s.display&&function(t,o){const n=o.position;if(st.includes(n))return n;return function(t,o){const{x:n,y:r,x2:i,y2:s,width:a,height:d,pointX:l,pointY:c,centerX:h,centerY:u,rotation:f}=t,x={x:h,y:u},y=o.start,p=m(a,y),b=m(d,y),g=[n,n+p,n+p,i],w=[r+b,s,r,s],v=[];for(let t=0;t<4;t++){const o=E({x:g[t],y:w[t]},x,e.toRadians(f));v.push({position:st[t],distance:e.distanceBetweenPoints(o,{x:l,y:c})})}return v.sort(((t,e)=>t.distance-e.distance))[0].position}(t,o)}(o,s);if(!a||function(t,e,o){const{pointX:n,pointY:r}=t,i=e.margin;let s=n,a=r;"left"===o?s+=i:"right"===o?s-=i:"top"===o?a+=i:"bottom"===o&&(a-=i);return t.inRange(s,a)}(o,s,a))return;t.save(),t.beginPath();if(!D(t,s))return t.restore();const{separatorStart:d,separatorEnd:l}=function(t,e){const{x:o,y:n,x2:r,y2:i}=t,s=function(t,e){const{width:o,height:n,options:r}=t,i=r.callout.margin+r.borderWidth/2;if("right"===e)return o+i;if("bottom"===e)return n+i;return-i}(t,e);let a,d;"left"===e||"right"===e?(a={x:o+s,y:n},d={x:a.x,y:i}):(a={x:o,y:n+s},d={x:r,y:a.y});return{separatorStart:a,separatorEnd:d}}(o,a),{sideStart:c,sideEnd:h}=function(t,e,o){const{y:n,width:r,height:i,options:s}=t,a=s.callout.start,d=function(t,e){const o=e.side;if("left"===t||"top"===t)return-o;return o}(e,s.callout);let l,c;"left"===e||"right"===e?(l={x:o.x,y:n+m(i,a)},c={x:l.x+d,y:l.y}):(l={x:o.x+m(r,a),y:o.y},c={x:l.x,y:l.y+d});return{sideStart:l,sideEnd:c}}(o,a,d);(s.margin>0||0===i.borderWidth)&&(t.moveTo(d.x,d.y),t.lineTo(l.x,l.y));t.moveTo(c.x,c.y),t.lineTo(h.x,h.y);const u=E({x:n,y:r},o.getCenterPoint(),e.toRadians(-o.rotation));t.lineTo(u.x,u.y),t.stroke(),t.restore()}(t,this),P(t,this,o),function(t,o,n){const r=n.content;if(M(r))return void t.drawImage(r,o.x,o.y,o.width,o.height);const i=e.isArray(r)?r:[r],s=e.toFont(n.font),a=s.lineHeight,d=function(t,e){const{x:o,width:n}=t,r=e.textAlign;return"center"===r?o+n/2:"end"===r||"right"===r?o+n:o}(o,n),l=o.y+a/2+n.textStrokeWidth/2;t.save(),t.font=s.string,t.textBaseline="middle",t.textAlign=n.textAlign,function(t,e){if(e.textStrokeWidth>0)return t.lineJoin="round",t.miterLimit=2,t.lineWidth=e.textStrokeWidth,t.strokeStyle=e.textStrokeColor,!0}(t,n)&&i.forEach(((e,o)=>t.strokeText(e,d,l+o*a))),t.fillStyle=n.color,i.forEach(((e,o)=>t.fillText(e,d,l+o*a))),t.restore()}(t,function({x:t,y:o,width:n,height:r,options:i}){const s=i.borderWidth/2,a=e.toPadding(i.padding);return{x:t+a.left+s,y:o+a.top+s,width:n-a.left-a.right-i.borderWidth,height:r-a.top-a.bottom-i.borderWidth}}(this),o),t.restore())}resolveElementProperties(t,o){let n;if(v(o))n=Y(t,o);else{const{centerX:e,centerY:r}=R(t,o);n={x:e,y:r}}const r=e.toPadding(o.padding),i=function(t,e,o,n){const r=e.width+n.width+o.borderWidth,i=e.height+n.height+o.borderWidth,s=w(o.position),a=dt(t.x,r,o.xAdjust,s.x),d=dt(t.y,i,o.yAdjust,s.y);return{x:a,y:d,x2:a+r,y2:d+i,width:r,height:i,centerX:a+r/2,centerY:d+i/2}}(n,k(t.ctx,o),o,r);return{pointX:n.x,pointY:n.y,...i,rotation:o.rotation}}}function dt(t,e,o=0,n){return t-g(e,n)+o}at.id="labelAnnotation",at.defaults={adjustScaleRange:!0,backgroundColor:"transparent",backgroundShadowColor:"transparent",borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderRadius:0,borderShadowColor:"transparent",borderWidth:0,callout:{borderCapStyle:"butt",borderColor:void 0,borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:1,display:!1,margin:5,position:"auto",side:5,start:"50%"},color:"black",content:null,display:!0,font:{family:void 0,lineHeight:void 0,size:void 0,style:void 0,weight:void 0},height:void 0,padding:6,position:"center",rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,textAlign:"center",textStrokeColor:void 0,textStrokeWidth:0,width:void 0,xAdjust:0,xMax:void 0,xMin:void 0,xScaleID:void 0,xValue:void 0,yAdjust:0,yMax:void 0,yMin:void 0,yScaleID:void 0,yValue:void 0,z:0},at.defaultRoutes={borderColor:"color"};class lt extends t.Element{inRange(t,e,o,n){const{x:r,y:i,x2:s,y2:a,width:d}=this.getProps(["x","y","x2","y2","width"],n),l=this.options.borderWidth;if("x"!==o&&"y"!==o)return function(t,e,o,n){if(!t||!e||o<=0)return!1;const r=n/2;return Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2)<=Math.pow(o+r,2)}({x:t,y:e},this.getCenterPoint(n),d/2,l);const c=l/2,h="y"===o?{start:i,end:a,value:e}:{start:r,end:s,value:t};return h.value>=h.start-c&&h.value<=h.end+c}getCenterPoint(t){return y(this,t)}draw(t){const o=this.options,n=o.borderWidth;if(o.radius<.1)return;t.save(),t.fillStyle=o.backgroundColor,j(t,o);const r=D(t,o);o.borderWidth=0,e.drawPoint(t,o,this.centerX,this.centerY),r&&!M(o.pointStyle)&&(t.shadowColor=o.borderShadowColor,t.stroke()),t.restore(),o.borderWidth=n}resolveElementProperties(t,e){return W(t,e)}}lt.id="pointAnnotation",lt.defaults={adjustScaleRange:!0,backgroundShadowColor:"transparent",borderDash:[],borderDashOffset:0,borderShadowColor:"transparent",borderWidth:1,display:!0,pointStyle:"circle",radius:10,rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,xAdjust:0,xMax:void 0,xMin:void 0,xScaleID:void 0,xValue:void 0,yAdjust:0,yMax:void 0,yMin:void 0,yScaleID:void 0,yValue:void 0,z:0},lt.defaultRoutes={borderColor:"color",backgroundColor:"color"};class ct extends t.Element{inRange(t,o,n,r){if("x"!==n&&"y"!==n)return this.options.radius>=.1&&this.elements.length>1&&function(t,e,o,n){let r=!1,i=t[t.length-1].getProps(["bX","bY"],n);for(const s of t){const t=s.getProps(["bX","bY"],n);t.bY>o!=i.bY>o&&e<(i.bX-t.bX)*(o-t.bY)/(i.bY-t.bY)+t.bX&&(r=!r),i=t}return r}(this.elements,t,o,r);const i=E({x:t,y:o},this.getCenterPoint(r),e.toRadians(-this.options.rotation)),s=this.elements.map((t=>"y"===n?t.bY:t.bX)),a=Math.min(...s),d=Math.max(...s);return i[n]>=a&&i[n]<=d}getCenterPoint(t){return y(this,t)}draw(t){const{elements:e,options:o}=this;t.save(),t.beginPath(),t.fillStyle=o.backgroundColor,j(t,o);const n=D(t,o);let r=!0;for(const o of e)r?(t.moveTo(o.x,o.y),r=!1):t.lineTo(o.x,o.y);t.closePath(),t.fill(),n&&(t.shadowColor=o.borderShadowColor,t.stroke()),t.restore()}resolveElementProperties(t,o){const n=W(t,o),{x:r,y:i}=n,{sides:s,rotation:a}=o,d=[],l=2*e.PI/s;let c=a*e.RAD_PER_DEG;for(let t=0;t<s;t++,c+=l)d.push(ht(n,o,c));return n.elements=d,n.initProperties={x:r,y:i},n}}function ht({centerX:t,centerY:e},{radius:o,borderWidth:n},r){const i=n/2,s=Math.sin(r),a=Math.cos(r),d={x:t+s*o,y:e-a*o};return{type:"point",optionScope:"point",properties:{x:d.x,y:d.y,centerX:d.x,centerY:d.y,bX:t+s*(o+i),bY:e-a*(o+i)}}}ct.id="polygonAnnotation",ct.defaults={adjustScaleRange:!0,backgroundShadowColor:"transparent",borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderShadowColor:"transparent",borderWidth:1,display:!0,point:{radius:0},radius:10,rotation:0,shadowBlur:0,shadowOffsetX:0,shadowOffsetY:0,sides:3,xAdjust:0,xMax:void 0,xMin:void 0,xScaleID:void 0,xValue:void 0,yAdjust:0,yMax:void 0,yMin:void 0,yScaleID:void 0,yValue:void 0,z:0},ct.defaultRoutes={borderColor:"color",backgroundColor:"color"};const ut={box:B,ellipse:it,label:at,line:U,point:lt,polygon:ct};Object.keys(ut).forEach((e=>{t.defaults.describe(`elements.${ut[e].id}`,{_fallback:"plugins.annotation.common"})}));const ft={update:Object.assign};function xt(t="line"){return ut[t]?t:(console.warn(`Unknown annotation type: '${t}', defaulting to 'line'`),"line")}function yt(o,n,r,i){const s=function(e,o,n){if("reset"===n||"none"===n||"resize"===n)return ft;return new t.Animations(e,o)}(o,r.animations,i),a=n.annotations,d=function(t,e){const o=e.length,n=t.length;if(n<o){const e=o-n;t.splice(n,0,...new Array(e))}else n>o&&t.splice(o,n-o);return t}(n.elements,a);for(let t=0;t<a.length;t++){const n=a[t],r=gt(d,t,n.type),i=n.setContext(vt(o,r,n)),l=r.resolveElementProperties(o,i);l.skip=pt(l),"elements"in l&&(bt(r,l,i,s),delete l.elements),e.defined(r.x)||Object.assign(r,l),l.options=mt(i),s.update(r,l)}}function pt(t){return isNaN(t.x)||isNaN(t.y)}function bt(t,{elements:e,initProperties:o},n,r){const i=t.elements||(t.elements=[]);i.length=e.length;for(let t=0;t<e.length;t++){const s=e[t],a=s.properties,d=gt(i,t,s.type,o),l=n[s.optionScope].override(s);a.options=mt(l),r.update(d,a)}}function gt(t,o,n,r){const i=ut[xt(n)];let s=t[o];return s&&s instanceof i||(s=t[o]=new i,e.isObject(r)&&Object.assign(s,r)),s}function mt(t){const e=ut[xt(t.type)],o={};o.id=t.id,o.type=t.type,o.drawTime=t.drawTime,Object.assign(o,wt(t,e.defaults),wt(t,e.defaultRoutes));for(const e of s)o[e]=t[e];return o}function wt(t,o){const n={};for(const r of Object.keys(o)){const i=o[r],s=t[r];n[r]=e.isObject(i)?wt(s,i):s}return n}function vt(t,e,o){return e.$context||(e.$context=Object.assign(Object.create(t.getContext()),{element:e,id:o.id,type:"annotation"}))}const St=new Map;var Mt={id:"annotation",version:"2.0.0",beforeRegister(){!function(t,e,o,n=!0){const r=o.split(".");let i=0;for(const s of e.split(".")){const a=r[i++];if(parseInt(s,10)<parseInt(a,10))break;if(c(a,s)){if(n)throw new Error(`${t} v${o} is not supported. v${e} or newer is required.`);return!1}}}("chart.js","3.7",t.Chart.version)},afterRegister(){t.Chart.register(ut)},afterUnregister(){t.Chart.unregister(ut)},beforeInit(t){St.set(t,{annotations:[],elements:[],visibleElements:[],listeners:{},listened:!1,moveListened:!1,hovered:[]})},beforeUpdate(t,o,n){const r=St.get(t).annotations=[];let i=n.annotations;e.isObject(i)?Object.keys(i).forEach((t=>{const o=i[t];e.isObject(o)&&(o.id=t,r.push(o))})):e.isArray(i)&&r.push(...i),function(t,e){for(const o of t)_(o,e)}(r,t.scales)},afterDataLimits(t,e){const o=St.get(t);T(t,e.scale,o.annotations.filter((t=>t.display&&t.adjustScaleRange)))},afterUpdate(t,o,r){const a=St.get(t);!function(t,o,r){o.listened=!1,o.moveListened=!1,o._getElements=n,s.forEach((t=>{"function"==typeof r[t]?(o.listened=!0,o.listeners[t]=r[t]):e.defined(o.listeners[t])&&delete o.listeners[t]})),i.forEach((t=>{"function"==typeof r[t]&&(o.moveListened=!0)})),o.listened&&o.moveListened||o.annotations.forEach((t=>{o.listened||"function"!=typeof t.click||(o.listened=!0),o.moveListened||i.forEach((e=>{"function"==typeof t[e]&&(o.listened=!0,o.moveListened=!0)}))}))}(0,a,r),yt(t,a,r,o.mode),a.visibleElements=a.elements.filter((t=>!t.skip&&t.options.display))},beforeDatasetsDraw(t,e,o){Ct(t,"beforeDatasetsDraw",o.clip)},afterDatasetsDraw(t,e,o){Ct(t,"afterDatasetsDraw",o.clip)},beforeDraw(t,e,o){Ct(t,"beforeDraw",o.clip)},afterDraw(t,e,o){Ct(t,"afterDraw",o.clip)},beforeEvent(t,e,o){a(St.get(t),e.event,o)&&(e.changed=!0)},destroy(t){St.delete(t)},_getState:t=>St.get(t),defaults:{animations:{numbers:{properties:["x","y","x2","y2","width","height","centerX","centerY","pointX","pointY","radius"],type:"number"}},clip:!0,interaction:{mode:void 0,axis:void 0,intersect:void 0},common:{drawTime:"afterDatasetsDraw",label:{}}},descriptors:{_indexable:!1,_scriptable:t=>!s.includes(t),annotations:{_allKeys:!1,_fallback:(t,e)=>`elements.${ut[xt(e.type)].id}`},interaction:{_fallback:!0},common:{label:{_fallback:!0}}},additionalOptionScopes:[""]};function Ct(t,o,n){const{ctx:r,chartArea:i}=t,{visibleElements:s}=St.get(t);n&&e.clipArea(r,i);const a=function(t,e){const o=[];for(const n of t)if(n.options.drawTime===e&&o.push(n),n.elements&&n.elements.length)for(const t of n.elements)t.options.display&&t.options.drawTime===e&&o.push(t);return o}(s,o).sort(((t,e)=>t.options.z-e.options.z));for(const e of a)e.draw(t.ctx,i);n&&e.unclipArea(r)}return t.Chart.register(Mt),Mt}));
         
     | 
| 
         @@ -0,0 +1,262 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
         
     | 
| 
      
 2 
     | 
    
         
            +
              Chart.defaults.borderColor = "#333"
         
     | 
| 
      
 3 
     | 
    
         
            +
              Chart.defaults.color = "#aaa"
         
     | 
| 
      
 4 
     | 
    
         
            +
            }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class BaseChart {
         
     | 
| 
      
 7 
     | 
    
         
            +
              constructor(id, options) {
         
     | 
| 
      
 8 
     | 
    
         
            +
                this.ctx = document.getElementById(id);
         
     | 
| 
      
 9 
     | 
    
         
            +
                this.options = options
         
     | 
| 
      
 10 
     | 
    
         
            +
                this.fallbackColor = "#999";
         
     | 
| 
      
 11 
     | 
    
         
            +
                this.colors = [
         
     | 
| 
      
 12 
     | 
    
         
            +
                  // Colors taken from https://www.chartjs.org/docs/latest/samples/utils.html
         
     | 
| 
      
 13 
     | 
    
         
            +
                  "#537bc4",
         
     | 
| 
      
 14 
     | 
    
         
            +
                  "#4dc9f6",
         
     | 
| 
      
 15 
     | 
    
         
            +
                  "#f67019",
         
     | 
| 
      
 16 
     | 
    
         
            +
                  "#f53794",
         
     | 
| 
      
 17 
     | 
    
         
            +
                  "#acc236",
         
     | 
| 
      
 18 
     | 
    
         
            +
                  "#166a8f",
         
     | 
| 
      
 19 
     | 
    
         
            +
                  "#00a950",
         
     | 
| 
      
 20 
     | 
    
         
            +
                  "#58595b",
         
     | 
| 
      
 21 
     | 
    
         
            +
                  "#8549ba",
         
     | 
| 
      
 22 
     | 
    
         
            +
                  "#991b1b",
         
     | 
| 
      
 23 
     | 
    
         
            +
                ];
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                this.chart = new Chart(this.ctx, {
         
     | 
| 
      
 26 
     | 
    
         
            +
                  type: this.options.chartType,
         
     | 
| 
      
 27 
     | 
    
         
            +
                  data: { labels: this.options.labels, datasets: this.datasets },
         
     | 
| 
      
 28 
     | 
    
         
            +
                  options: this.chartOptions,
         
     | 
| 
      
 29 
     | 
    
         
            +
                });
         
     | 
| 
      
 30 
     | 
    
         
            +
              }
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              addMarksToChart() {
         
     | 
| 
      
 33 
     | 
    
         
            +
                this.options.marks.forEach(([bucket, label], i) => {
         
     | 
| 
      
 34 
     | 
    
         
            +
                  this.chart.options.plugins.annotation.annotations[`deploy-${i}`] = {
         
     | 
| 
      
 35 
     | 
    
         
            +
                    type: "line",
         
     | 
| 
      
 36 
     | 
    
         
            +
                    xMin: bucket,
         
     | 
| 
      
 37 
     | 
    
         
            +
                    xMax: bucket,
         
     | 
| 
      
 38 
     | 
    
         
            +
                    borderColor: "rgba(220, 38, 38, 0.4)",
         
     | 
| 
      
 39 
     | 
    
         
            +
                    borderWidth: 2,
         
     | 
| 
      
 40 
     | 
    
         
            +
                  };
         
     | 
| 
      
 41 
     | 
    
         
            +
                });
         
     | 
| 
      
 42 
     | 
    
         
            +
              }
         
     | 
| 
      
 43 
     | 
    
         
            +
            }
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
            class JobMetricsOverviewChart extends BaseChart {
         
     | 
| 
      
 46 
     | 
    
         
            +
              constructor(id, options) {
         
     | 
| 
      
 47 
     | 
    
         
            +
                super(id, { ...options, chartType: "line" });
         
     | 
| 
      
 48 
     | 
    
         
            +
                this.swatches = [];
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                this.addMarksToChart();
         
     | 
| 
      
 51 
     | 
    
         
            +
                this.chart.update();
         
     | 
| 
      
 52 
     | 
    
         
            +
              }
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
              registerSwatch(id) {
         
     | 
| 
      
 55 
     | 
    
         
            +
                const el = document.getElementById(id);
         
     | 
| 
      
 56 
     | 
    
         
            +
                el.onchange = () => this.toggle(el.value, el.checked);
         
     | 
| 
      
 57 
     | 
    
         
            +
                this.swatches[el.value] = el;
         
     | 
| 
      
 58 
     | 
    
         
            +
                this.updateSwatch(el.value);
         
     | 
| 
      
 59 
     | 
    
         
            +
              }
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              updateSwatch(kls) {
         
     | 
| 
      
 62 
     | 
    
         
            +
                const el = this.swatches[kls];
         
     | 
| 
      
 63 
     | 
    
         
            +
                const ds = this.chart.data.datasets.find((ds) => ds.label == kls);
         
     | 
| 
      
 64 
     | 
    
         
            +
                el.checked = !!ds;
         
     | 
| 
      
 65 
     | 
    
         
            +
                el.style.color = ds ? ds.borderColor : null;
         
     | 
| 
      
 66 
     | 
    
         
            +
              }
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
              toggle(kls, visible) {
         
     | 
| 
      
 69 
     | 
    
         
            +
                if (visible) {
         
     | 
| 
      
 70 
     | 
    
         
            +
                  this.chart.data.datasets.push(this.dataset(kls));
         
     | 
| 
      
 71 
     | 
    
         
            +
                } else {
         
     | 
| 
      
 72 
     | 
    
         
            +
                  const i = this.chart.data.datasets.findIndex((ds) => ds.label == kls);
         
     | 
| 
      
 73 
     | 
    
         
            +
                  this.colors.unshift(this.chart.data.datasets[i].borderColor);
         
     | 
| 
      
 74 
     | 
    
         
            +
                  this.chart.data.datasets.splice(i, 1);
         
     | 
| 
      
 75 
     | 
    
         
            +
                }
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                this.updateSwatch(kls);
         
     | 
| 
      
 78 
     | 
    
         
            +
                this.chart.update();
         
     | 
| 
      
 79 
     | 
    
         
            +
              }
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              dataset(kls) {
         
     | 
| 
      
 82 
     | 
    
         
            +
                const color = this.colors.shift() || this.fallbackColor;
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                return {
         
     | 
| 
      
 85 
     | 
    
         
            +
                  label: kls,
         
     | 
| 
      
 86 
     | 
    
         
            +
                  data: this.options.series[kls],
         
     | 
| 
      
 87 
     | 
    
         
            +
                  borderColor: color,
         
     | 
| 
      
 88 
     | 
    
         
            +
                  backgroundColor: color,
         
     | 
| 
      
 89 
     | 
    
         
            +
                  borderWidth: 2,
         
     | 
| 
      
 90 
     | 
    
         
            +
                  pointRadius: 2,
         
     | 
| 
      
 91 
     | 
    
         
            +
                };
         
     | 
| 
      
 92 
     | 
    
         
            +
              }
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
              get datasets() {
         
     | 
| 
      
 95 
     | 
    
         
            +
                return Object.entries(this.options.series)
         
     | 
| 
      
 96 
     | 
    
         
            +
                  .filter(([kls, _]) => this.options.visible.includes(kls))
         
     | 
| 
      
 97 
     | 
    
         
            +
                  .map(([kls, _]) => this.dataset(kls));
         
     | 
| 
      
 98 
     | 
    
         
            +
              }
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              get chartOptions() {
         
     | 
| 
      
 101 
     | 
    
         
            +
                return {
         
     | 
| 
      
 102 
     | 
    
         
            +
                  aspectRatio: 4,
         
     | 
| 
      
 103 
     | 
    
         
            +
                  scales: {
         
     | 
| 
      
 104 
     | 
    
         
            +
                    y: {
         
     | 
| 
      
 105 
     | 
    
         
            +
                      beginAtZero: true,
         
     | 
| 
      
 106 
     | 
    
         
            +
                      title: {
         
     | 
| 
      
 107 
     | 
    
         
            +
                        text: "Total execution time (sec)",
         
     | 
| 
      
 108 
     | 
    
         
            +
                        display: true,
         
     | 
| 
      
 109 
     | 
    
         
            +
                      },
         
     | 
| 
      
 110 
     | 
    
         
            +
                    },
         
     | 
| 
      
 111 
     | 
    
         
            +
                  },
         
     | 
| 
      
 112 
     | 
    
         
            +
                  interaction: {
         
     | 
| 
      
 113 
     | 
    
         
            +
                    mode: "x",
         
     | 
| 
      
 114 
     | 
    
         
            +
                  },
         
     | 
| 
      
 115 
     | 
    
         
            +
                  plugins: {
         
     | 
| 
      
 116 
     | 
    
         
            +
                    legend: {
         
     | 
| 
      
 117 
     | 
    
         
            +
                      display: false,
         
     | 
| 
      
 118 
     | 
    
         
            +
                    },
         
     | 
| 
      
 119 
     | 
    
         
            +
                    tooltip: {
         
     | 
| 
      
 120 
     | 
    
         
            +
                      callbacks: {
         
     | 
| 
      
 121 
     | 
    
         
            +
                        title: (items) => `${items[0].label} UTC`,
         
     | 
| 
      
 122 
     | 
    
         
            +
                        label: (item) =>
         
     | 
| 
      
 123 
     | 
    
         
            +
                          `${item.dataset.label}: ${item.parsed.y.toFixed(1)} seconds`,
         
     | 
| 
      
 124 
     | 
    
         
            +
                        footer: (items) => {
         
     | 
| 
      
 125 
     | 
    
         
            +
                          const bucket = items[0].label;
         
     | 
| 
      
 126 
     | 
    
         
            +
                          const marks = this.options.marks.filter(([b, _]) => b == bucket);
         
     | 
| 
      
 127 
     | 
    
         
            +
                          return marks.map(([b, msg]) => `Deploy: ${msg}`);
         
     | 
| 
      
 128 
     | 
    
         
            +
                        },
         
     | 
| 
      
 129 
     | 
    
         
            +
                      },
         
     | 
| 
      
 130 
     | 
    
         
            +
                    },
         
     | 
| 
      
 131 
     | 
    
         
            +
                  },
         
     | 
| 
      
 132 
     | 
    
         
            +
                };
         
     | 
| 
      
 133 
     | 
    
         
            +
              }
         
     | 
| 
      
 134 
     | 
    
         
            +
            }
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            class HistTotalsChart extends BaseChart {
         
     | 
| 
      
 137 
     | 
    
         
            +
              constructor(id, options) {
         
     | 
| 
      
 138 
     | 
    
         
            +
                super(id, { ...options, chartType: "bar" });
         
     | 
| 
      
 139 
     | 
    
         
            +
              }
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
              get datasets() {
         
     | 
| 
      
 142 
     | 
    
         
            +
                return [{
         
     | 
| 
      
 143 
     | 
    
         
            +
                  data: this.options.series,
         
     | 
| 
      
 144 
     | 
    
         
            +
                  backgroundColor: this.colors[0],
         
     | 
| 
      
 145 
     | 
    
         
            +
                  borderWidth: 0,
         
     | 
| 
      
 146 
     | 
    
         
            +
                }];
         
     | 
| 
      
 147 
     | 
    
         
            +
              }
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
              get chartOptions() {
         
     | 
| 
      
 150 
     | 
    
         
            +
                return {
         
     | 
| 
      
 151 
     | 
    
         
            +
                  aspectRatio: 6,
         
     | 
| 
      
 152 
     | 
    
         
            +
                  scales: {
         
     | 
| 
      
 153 
     | 
    
         
            +
                    y: {
         
     | 
| 
      
 154 
     | 
    
         
            +
                      beginAtZero: true,
         
     | 
| 
      
 155 
     | 
    
         
            +
                      title: {
         
     | 
| 
      
 156 
     | 
    
         
            +
                        text: "Total jobs",
         
     | 
| 
      
 157 
     | 
    
         
            +
                        display: true,
         
     | 
| 
      
 158 
     | 
    
         
            +
                      },
         
     | 
| 
      
 159 
     | 
    
         
            +
                    },
         
     | 
| 
      
 160 
     | 
    
         
            +
                  },
         
     | 
| 
      
 161 
     | 
    
         
            +
                  interaction: {
         
     | 
| 
      
 162 
     | 
    
         
            +
                    mode: "x",
         
     | 
| 
      
 163 
     | 
    
         
            +
                  },
         
     | 
| 
      
 164 
     | 
    
         
            +
                  plugins: {
         
     | 
| 
      
 165 
     | 
    
         
            +
                    legend: {
         
     | 
| 
      
 166 
     | 
    
         
            +
                      display: false,
         
     | 
| 
      
 167 
     | 
    
         
            +
                    },
         
     | 
| 
      
 168 
     | 
    
         
            +
                    tooltip: {
         
     | 
| 
      
 169 
     | 
    
         
            +
                      callbacks: {
         
     | 
| 
      
 170 
     | 
    
         
            +
                        label: (item) => `${item.parsed.y} jobs`,
         
     | 
| 
      
 171 
     | 
    
         
            +
                      },
         
     | 
| 
      
 172 
     | 
    
         
            +
                    },
         
     | 
| 
      
 173 
     | 
    
         
            +
                  },
         
     | 
| 
      
 174 
     | 
    
         
            +
                };
         
     | 
| 
      
 175 
     | 
    
         
            +
              }
         
     | 
| 
      
 176 
     | 
    
         
            +
            }
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
            class HistBubbleChart extends BaseChart {
         
     | 
| 
      
 179 
     | 
    
         
            +
              constructor(id, options) {
         
     | 
| 
      
 180 
     | 
    
         
            +
                super(id, { ...options, chartType: "bubble" });
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                this.addMarksToChart();
         
     | 
| 
      
 183 
     | 
    
         
            +
                this.chart.update();
         
     | 
| 
      
 184 
     | 
    
         
            +
              }
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              get datasets() {
         
     | 
| 
      
 187 
     | 
    
         
            +
                const data = [];
         
     | 
| 
      
 188 
     | 
    
         
            +
                let maxCount = 0;
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                Object.entries(this.options.hist).forEach(([bucket, hist]) => {
         
     | 
| 
      
 191 
     | 
    
         
            +
                  hist.forEach((count, histBucket) => {
         
     | 
| 
      
 192 
     | 
    
         
            +
                    if (count > 0) {
         
     | 
| 
      
 193 
     | 
    
         
            +
                      data.push({
         
     | 
| 
      
 194 
     | 
    
         
            +
                        x: bucket,
         
     | 
| 
      
 195 
     | 
    
         
            +
                        // histogram data is ordered fastest to slowest, but this.histIntervals is
         
     | 
| 
      
 196 
     | 
    
         
            +
                        // slowest to fastest (so it displays correctly on the chart).
         
     | 
| 
      
 197 
     | 
    
         
            +
                        y:
         
     | 
| 
      
 198 
     | 
    
         
            +
                          this.options.histIntervals[this.options.histIntervals.length - 1 - histBucket] /
         
     | 
| 
      
 199 
     | 
    
         
            +
                          1000,
         
     | 
| 
      
 200 
     | 
    
         
            +
                        count: count,
         
     | 
| 
      
 201 
     | 
    
         
            +
                      });
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                      if (count > maxCount) maxCount = count;
         
     | 
| 
      
 204 
     | 
    
         
            +
                    }
         
     | 
| 
      
 205 
     | 
    
         
            +
                  });
         
     | 
| 
      
 206 
     | 
    
         
            +
                });
         
     | 
| 
      
 207 
     | 
    
         
            +
             
     | 
| 
      
 208 
     | 
    
         
            +
                // Chart.js will not calculate the bubble size. We have to do that.
         
     | 
| 
      
 209 
     | 
    
         
            +
                const maxRadius = this.ctx.offsetWidth / this.options.labels.length;
         
     | 
| 
      
 210 
     | 
    
         
            +
                const minRadius = 1
         
     | 
| 
      
 211 
     | 
    
         
            +
                const multiplier = (maxRadius / maxCount) * 1.5;
         
     | 
| 
      
 212 
     | 
    
         
            +
                data.forEach((entry) => {
         
     | 
| 
      
 213 
     | 
    
         
            +
                  entry.r = entry.count * multiplier + minRadius;
         
     | 
| 
      
 214 
     | 
    
         
            +
                });
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                return [{
         
     | 
| 
      
 217 
     | 
    
         
            +
                  data: data,
         
     | 
| 
      
 218 
     | 
    
         
            +
                  backgroundColor: "#537bc4",
         
     | 
| 
      
 219 
     | 
    
         
            +
                  borderColor: "#537bc4",
         
     | 
| 
      
 220 
     | 
    
         
            +
                }];
         
     | 
| 
      
 221 
     | 
    
         
            +
              }
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
              get chartOptions() {
         
     | 
| 
      
 224 
     | 
    
         
            +
                return {
         
     | 
| 
      
 225 
     | 
    
         
            +
                  aspectRatio: 3,
         
     | 
| 
      
 226 
     | 
    
         
            +
                  scales: {
         
     | 
| 
      
 227 
     | 
    
         
            +
                    x: {
         
     | 
| 
      
 228 
     | 
    
         
            +
                      type: "category",
         
     | 
| 
      
 229 
     | 
    
         
            +
                      labels: this.options.labels,
         
     | 
| 
      
 230 
     | 
    
         
            +
                    },
         
     | 
| 
      
 231 
     | 
    
         
            +
                    y: {
         
     | 
| 
      
 232 
     | 
    
         
            +
                      title: {
         
     | 
| 
      
 233 
     | 
    
         
            +
                        text: "Execution time (sec)",
         
     | 
| 
      
 234 
     | 
    
         
            +
                        display: true,
         
     | 
| 
      
 235 
     | 
    
         
            +
                      },
         
     | 
| 
      
 236 
     | 
    
         
            +
                    },
         
     | 
| 
      
 237 
     | 
    
         
            +
                  },
         
     | 
| 
      
 238 
     | 
    
         
            +
                  interaction: {
         
     | 
| 
      
 239 
     | 
    
         
            +
                    mode: "x",
         
     | 
| 
      
 240 
     | 
    
         
            +
                  },
         
     | 
| 
      
 241 
     | 
    
         
            +
                  plugins: {
         
     | 
| 
      
 242 
     | 
    
         
            +
                    legend: {
         
     | 
| 
      
 243 
     | 
    
         
            +
                      display: false,
         
     | 
| 
      
 244 
     | 
    
         
            +
                    },
         
     | 
| 
      
 245 
     | 
    
         
            +
                    tooltip: {
         
     | 
| 
      
 246 
     | 
    
         
            +
                      callbacks: {
         
     | 
| 
      
 247 
     | 
    
         
            +
                        title: (items) => `${items[0].raw.x} UTC`,
         
     | 
| 
      
 248 
     | 
    
         
            +
                        label: (item) =>
         
     | 
| 
      
 249 
     | 
    
         
            +
                          `${item.parsed.y} seconds: ${item.raw.count} job${
         
     | 
| 
      
 250 
     | 
    
         
            +
                            item.raw.count == 1 ? "" : "s"
         
     | 
| 
      
 251 
     | 
    
         
            +
                          }`,
         
     | 
| 
      
 252 
     | 
    
         
            +
                        footer: (items) => {
         
     | 
| 
      
 253 
     | 
    
         
            +
                          const bucket = items[0].raw.x;
         
     | 
| 
      
 254 
     | 
    
         
            +
                          const marks = this.options.marks.filter(([b, _]) => b == bucket);
         
     | 
| 
      
 255 
     | 
    
         
            +
                          return marks.map(([b, msg]) => `Deploy: ${msg}`);
         
     | 
| 
      
 256 
     | 
    
         
            +
                        },
         
     | 
| 
      
 257 
     | 
    
         
            +
                      },
         
     | 
| 
      
 258 
     | 
    
         
            +
                    },
         
     | 
| 
      
 259 
     | 
    
         
            +
                  },
         
     | 
| 
      
 260 
     | 
    
         
            +
                };
         
     | 
| 
      
 261 
     | 
    
         
            +
              }
         
     | 
| 
      
 262 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -67,10 +67,15 @@ body { 
     | 
|
| 
       67 
67 
     | 
    
         
             
              padding: 0 20px;
         
     | 
| 
       68 
68 
     | 
    
         
             
            }
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
       70 
     | 
    
         
            -
            h3 {
         
     | 
| 
      
 70 
     | 
    
         
            +
            h1, h2, h3 {
         
     | 
| 
      
 71 
     | 
    
         
            +
              font-size: 24px;
         
     | 
| 
       71 
72 
     | 
    
         
             
              line-height: 45px;
         
     | 
| 
       72 
73 
     | 
    
         
             
            }
         
     | 
| 
       73 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
            .header-with-subheader h2 {
         
     | 
| 
      
 76 
     | 
    
         
            +
              margin-top: -18px;
         
     | 
| 
      
 77 
     | 
    
         
            +
            }
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
       74 
79 
     | 
    
         
             
            .centered {
         
     | 
| 
       75 
80 
     | 
    
         
             
              text-align: center;
         
     | 
| 
       76 
81 
     | 
    
         
             
            }
         
     | 
| 
         @@ -954,3 +959,41 @@ div.interval-slider input { 
     | 
|
| 
       954 
959 
     | 
    
         
             
              padding: 3px 7px;
         
     | 
| 
       955 
960 
     | 
    
         
             
              margin-left: 5px;
         
     | 
| 
       956 
961 
     | 
    
         
             
            }
         
     | 
| 
      
 962 
     | 
    
         
            +
             
     | 
| 
      
 963 
     | 
    
         
            +
            .metrics-swatch-wrapper {
         
     | 
| 
      
 964 
     | 
    
         
            +
              display: flex;
         
     | 
| 
      
 965 
     | 
    
         
            +
              align-items: center;
         
     | 
| 
      
 966 
     | 
    
         
            +
              gap: 6px;
         
     | 
| 
      
 967 
     | 
    
         
            +
            }
         
     | 
| 
      
 968 
     | 
    
         
            +
             
     | 
| 
      
 969 
     | 
    
         
            +
            .metrics-swatch[type=checkbox] {
         
     | 
| 
      
 970 
     | 
    
         
            +
              display: inline-block;
         
     | 
| 
      
 971 
     | 
    
         
            +
              width: 16px;
         
     | 
| 
      
 972 
     | 
    
         
            +
              height: 16px;
         
     | 
| 
      
 973 
     | 
    
         
            +
              margin: 0;
         
     | 
| 
      
 974 
     | 
    
         
            +
              border-radius: 2px;
         
     | 
| 
      
 975 
     | 
    
         
            +
              appearance: none;
         
     | 
| 
      
 976 
     | 
    
         
            +
              -webkit-appearance: none;
         
     | 
| 
      
 977 
     | 
    
         
            +
              -moz-appearance: none;
         
     | 
| 
      
 978 
     | 
    
         
            +
              border: 1px solid #bbb;
         
     | 
| 
      
 979 
     | 
    
         
            +
              color: white;
         
     | 
| 
      
 980 
     | 
    
         
            +
              background-color: currentColor;
         
     | 
| 
      
 981 
     | 
    
         
            +
            }
         
     | 
| 
      
 982 
     | 
    
         
            +
             
     | 
| 
      
 983 
     | 
    
         
            +
            /* We need to add the checkmark since we've taken over the appearance */
         
     | 
| 
      
 984 
     | 
    
         
            +
            .metrics-swatch[type=checkbox]:checked {
         
     | 
| 
      
 985 
     | 
    
         
            +
              border-color: currentColor;
         
     | 
| 
      
 986 
     | 
    
         
            +
              background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
         
     | 
| 
      
 987 
     | 
    
         
            +
              background-size: 100% 100%;
         
     | 
| 
      
 988 
     | 
    
         
            +
              background-position: center;
         
     | 
| 
      
 989 
     | 
    
         
            +
              background-repeat: no-repeat;
         
     | 
| 
      
 990 
     | 
    
         
            +
            }
         
     | 
| 
      
 991 
     | 
    
         
            +
             
     | 
| 
      
 992 
     | 
    
         
            +
            .metrics-swatch[type=checkbox]:focus {
         
     | 
| 
      
 993 
     | 
    
         
            +
              outline: 1px solid #888;
         
     | 
| 
      
 994 
     | 
    
         
            +
              outline-offset: 2px;
         
     | 
| 
      
 995 
     | 
    
         
            +
            }
         
     | 
| 
      
 996 
     | 
    
         
            +
             
     | 
| 
      
 997 
     | 
    
         
            +
            canvas {
         
     | 
| 
      
 998 
     | 
    
         
            +
              margin: 20px 0 30px;
         
     | 
| 
      
 999 
     | 
    
         
            +
            }
         
     | 
    
        data/web/locales/el.yml
    CHANGED
    
    | 
         @@ -6,11 +6,12 @@ el: # <---- change this to your locale code 
     | 
|
| 
       6 
6 
     | 
    
         
             
              Namespace: Namespace
         
     | 
| 
       7 
7 
     | 
    
         
             
              Realtime: Τρέχουσα Κατάσταση
         
     | 
| 
       8 
8 
     | 
    
         
             
              History: Ιστορικό
         
     | 
| 
       9 
     | 
    
         
            -
              Busy:  
     | 
| 
       10 
     | 
    
         
            -
               
     | 
| 
       11 
     | 
    
         
            -
               
     | 
| 
       12 
     | 
    
         
            -
               
     | 
| 
       13 
     | 
    
         
            -
               
     | 
| 
      
 9 
     | 
    
         
            +
              Busy: Υπό επεξεργασία
         
     | 
| 
      
 10 
     | 
    
         
            +
              Utilization: Σε χρήση
         
     | 
| 
      
 11 
     | 
    
         
            +
              Processed: Επεξεργάστηκαν
         
     | 
| 
      
 12 
     | 
    
         
            +
              Failed: Απέτυχαν
         
     | 
| 
      
 13 
     | 
    
         
            +
              Scheduled: Προγραμματισμένα
         
     | 
| 
      
 14 
     | 
    
         
            +
              Retries: Επαναλήψεις
         
     | 
| 
       14 
15 
     | 
    
         
             
              Enqueued: Μπήκαν στην στοίβα
         
     | 
| 
       15 
16 
     | 
    
         
             
              Worker: Εργάτης
         
     | 
| 
       16 
17 
     | 
    
         
             
              LivePoll: Τρέχουσα Κατάσταση
         
     | 
| 
         @@ -20,40 +21,42 @@ el: # <---- change this to your locale code 
     | 
|
| 
       20 
21 
     | 
    
         
             
              Job: Εργασία
         
     | 
| 
       21 
22 
     | 
    
         
             
              Arguments: Ορίσματα
         
     | 
| 
       22 
23 
     | 
    
         
             
              Extras: Extras
         
     | 
| 
       23 
     | 
    
         
            -
              Started:  
     | 
| 
      
 24 
     | 
    
         
            +
              Started: Ξεκίνησε
         
     | 
| 
       24 
25 
     | 
    
         
             
              ShowAll: Εμφάνιση Όλων
         
     | 
| 
       25 
26 
     | 
    
         
             
              CurrentMessagesInQueue: Τρέχουσες εργασίες <span class='title'>%{queue}</span>
         
     | 
| 
       26 
27 
     | 
    
         
             
              Delete: Διαγραφή
         
     | 
| 
       27 
28 
     | 
    
         
             
              AddToQueue: Προσθήκη στην στοίβα
         
     | 
| 
       28 
     | 
    
         
            -
              AreYouSureDeleteJob: Θέλετε να διαγράψετε την  
     | 
| 
       29 
     | 
    
         
            -
              AreYouSureDeleteQueue: Θέλετε να διαγράψετε την %{queue}  
     | 
| 
      
 29 
     | 
    
         
            +
              AreYouSureDeleteJob: Θέλετε να διαγράψετε αυτή την εργασία;
         
     | 
| 
      
 30 
     | 
    
         
            +
              AreYouSureDeleteQueue: Θέλετε να διαγράψετε την στοίβα %{queue}; Αυτό θα διαγράψει όλες τις εργασίες εντός της στοίβας, θα εμφανιστεί ξανά εάν προωθήσετε περισσότερες εργασίες σε αυτήν στο μέλλον.
         
     | 
| 
       30 
31 
     | 
    
         
             
              Queues: Στοίβες
         
     | 
| 
       31 
32 
     | 
    
         
             
              Size: Μέγεθος
         
     | 
| 
       32 
33 
     | 
    
         
             
              Actions: Ενέργειες
         
     | 
| 
       33 
     | 
    
         
            -
              NextRetry: Επόμενη  
     | 
| 
       34 
     | 
    
         
            -
              RetryCount: Αριθμός  
     | 
| 
       35 
     | 
    
         
            -
              RetryNow:  
     | 
| 
       36 
     | 
    
         
            -
               
     | 
| 
      
 34 
     | 
    
         
            +
              NextRetry: Επόμενη Προσπάθεια
         
     | 
| 
      
 35 
     | 
    
         
            +
              RetryCount: Αριθμός Προσπαθειών
         
     | 
| 
      
 36 
     | 
    
         
            +
              RetryNow: Επανάληψη Τώρα
         
     | 
| 
      
 37 
     | 
    
         
            +
              # Kill: Kill
         
     | 
| 
      
 38 
     | 
    
         
            +
              LastRetry: Τελευταία Προσπάθεια
         
     | 
| 
       37 
39 
     | 
    
         
             
              OriginallyFailed: Αρχικές Αποτυχίες
         
     | 
| 
       38 
     | 
    
         
            -
              AreYouSure: Είστε  
     | 
| 
       39 
     | 
    
         
            -
              DeleteAll: Διαγραφή  
     | 
| 
      
 40 
     | 
    
         
            +
              AreYouSure: Είστε σίγουρος;
         
     | 
| 
      
 41 
     | 
    
         
            +
              DeleteAll: Διαγραφή Όλων
         
     | 
| 
       40 
42 
     | 
    
         
             
              RetryAll: Επανάληψη Όλων
         
     | 
| 
       41 
     | 
    
         
            -
               
     | 
| 
      
 43 
     | 
    
         
            +
              # KillAll: Kill All
         
     | 
| 
      
 44 
     | 
    
         
            +
              NoRetriesFound: Δεν βρέθηκαν εργασίες προς επαναλήψη
         
     | 
| 
       42 
45 
     | 
    
         
             
              Error: Σφάλμα
         
     | 
| 
       43 
46 
     | 
    
         
             
              ErrorClass: Κλάση σφάλματος
         
     | 
| 
       44 
47 
     | 
    
         
             
              ErrorMessage: Μήνυμα Σφάλματος
         
     | 
| 
       45 
     | 
    
         
            -
              ErrorBacktrace:  
     | 
| 
      
 48 
     | 
    
         
            +
              ErrorBacktrace: Backtrace Σφάλματος
         
     | 
| 
       46 
49 
     | 
    
         
             
              GoBack: ← Πίσω
         
     | 
| 
       47 
50 
     | 
    
         
             
              NoScheduledFound: Δεν βρέθηκαν προγραμματισμένες εργασίες
         
     | 
| 
       48 
51 
     | 
    
         
             
              When: Πότε
         
     | 
| 
       49 
52 
     | 
    
         
             
              ScheduledJobs: Προγραμματισμένες Εργασίες
         
     | 
| 
       50 
     | 
    
         
            -
              idle:  
     | 
| 
       51 
     | 
    
         
            -
              active:  
     | 
| 
      
 53 
     | 
    
         
            +
              idle: αδρανές
         
     | 
| 
      
 54 
     | 
    
         
            +
              active: ενεργό
         
     | 
| 
       52 
55 
     | 
    
         
             
              Version: Έκδοση
         
     | 
| 
       53 
56 
     | 
    
         
             
              Connections: Συνδέσεις
         
     | 
| 
       54 
57 
     | 
    
         
             
              MemoryUsage: Χρήση Μνήμης
         
     | 
| 
       55 
58 
     | 
    
         
             
              PeakMemoryUsage: Μέγιστη Χρήση Μνήμης
         
     | 
| 
       56 
     | 
    
         
            -
              Uptime:  
     | 
| 
      
 59 
     | 
    
         
            +
              Uptime: Ημέρες Λειτουργίας
         
     | 
| 
       57 
60 
     | 
    
         
             
              OneWeek: 1 εβδομάδα
         
     | 
| 
       58 
61 
     | 
    
         
             
              OneMonth: 1 μήνας
         
     | 
| 
       59 
62 
     | 
    
         
             
              ThreeMonths: 3 μήνες
         
     | 
| 
         @@ -62,7 +65,28 @@ el: # <---- change this to your locale code 
     | 
|
| 
       62 
65 
     | 
    
         
             
              DeadJobs: Αδρανείς Εργασίες
         
     | 
| 
       63 
66 
     | 
    
         
             
              NoDeadJobsFound: Δεν βρέθηκαν αδρανείς εργασίες
         
     | 
| 
       64 
67 
     | 
    
         
             
              Dead: Αδρανείς
         
     | 
| 
      
 68 
     | 
    
         
            +
              Process: Διεργασία
         
     | 
| 
       65 
69 
     | 
    
         
             
              Processes: Διεργασίες
         
     | 
| 
      
 70 
     | 
    
         
            +
              Name: Όνομα
         
     | 
| 
       66 
71 
     | 
    
         
             
              Thread: Νήμα
         
     | 
| 
       67 
72 
     | 
    
         
             
              Threads: Νήματα
         
     | 
| 
       68 
73 
     | 
    
         
             
              Jobs: Εργασίες
         
     | 
| 
      
 74 
     | 
    
         
            +
              Paused: Σε παύση
         
     | 
| 
      
 75 
     | 
    
         
            +
              Stop: Διακοπή
         
     | 
| 
      
 76 
     | 
    
         
            +
              Quiet: Σίγαση
         
     | 
| 
      
 77 
     | 
    
         
            +
              StopAll: Διακοπή Όλων
         
     | 
| 
      
 78 
     | 
    
         
            +
              QuietAll: Σίγαση Όλων
         
     | 
| 
      
 79 
     | 
    
         
            +
              PollingInterval: Συχνότητα Ανανέωσης
         
     | 
| 
      
 80 
     | 
    
         
            +
              Plugins: Πρόσθετα
         
     | 
| 
      
 81 
     | 
    
         
            +
              NotYetEnqueued: Δεν προστέθηκε στην στοίβα ακόμη
         
     | 
| 
      
 82 
     | 
    
         
            +
              CreatedAt: Δημιουργήθηκε στις
         
     | 
| 
      
 83 
     | 
    
         
            +
              BackToApp: Πίσω στην Εφαρμογή
         
     | 
| 
      
 84 
     | 
    
         
            +
              Latency: Καθυστέρηση
         
     | 
| 
      
 85 
     | 
    
         
            +
              Pause: Παύση
         
     | 
| 
      
 86 
     | 
    
         
            +
              Unpause: Κατάργηση Παύσης
         
     | 
| 
      
 87 
     | 
    
         
            +
              Metrics: Μετρήσεις
         
     | 
| 
      
 88 
     | 
    
         
            +
              NoDataFound: Δεν βρέθηκαν δεδομένα
         
     | 
| 
      
 89 
     | 
    
         
            +
              ExecutionTime: Συνολικός Χρόνος Εκτέλεσης
         
     | 
| 
      
 90 
     | 
    
         
            +
              AvgExecutionTime: Μέσος Χρόνος Εκτέλεσης
         
     | 
| 
      
 91 
     | 
    
         
            +
              # Context: Context
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
    
        data/web/locales/en.yml
    CHANGED
    
    | 
         @@ -86,5 +86,8 @@ en: # <---- change this to your locale code 
     | 
|
| 
       86 
86 
     | 
    
         
             
              Unpause: Unpause
         
     | 
| 
       87 
87 
     | 
    
         
             
              Metrics: Metrics
         
     | 
| 
       88 
88 
     | 
    
         
             
              NoDataFound: No data found
         
     | 
| 
       89 
     | 
    
         
            -
              ExecutionTime: Execution Time
         
     | 
| 
      
 89 
     | 
    
         
            +
              ExecutionTime: Total Execution Time
         
     | 
| 
      
 90 
     | 
    
         
            +
              AvgExecutionTime: Average Execution Time
         
     | 
| 
       90 
91 
     | 
    
         
             
              Context: Context
         
     | 
| 
      
 92 
     | 
    
         
            +
              Bucket: Bucket
         
     | 
| 
      
 93 
     | 
    
         
            +
              NoJobMetricsFound: No recent job metrics were found
         
     | 
    
        data/web/views/metrics.erb
    CHANGED
    
    | 
         @@ -1,59 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            <script type="text/javascript" src="<%= root_path %>javascripts/chart.min.js"></script>
         
     | 
| 
      
 2 
     | 
    
         
            +
            <script type="text/javascript" src="<%= root_path %>javascripts/chartjs-plugin-annotation.min.js"></script>
         
     | 
| 
      
 3 
     | 
    
         
            +
            <script type="text/javascript" src="<%= root_path %>javascripts/metrics.js"></script>
         
     | 
| 
       1 
4 
     | 
    
         | 
| 
       2 
     | 
    
         
            -
            < 
     | 
| 
      
 5 
     | 
    
         
            +
            <h2>Total execution time</h2>
         
     | 
| 
       3 
6 
     | 
    
         | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
             
     | 
| 
      
 7 
     | 
    
         
            +
            <%
         
     | 
| 
      
 8 
     | 
    
         
            +
              table_limit = 20
         
     | 
| 
      
 9 
     | 
    
         
            +
              chart_limit = 5
         
     | 
| 
      
 10 
     | 
    
         
            +
              job_results = @query_result.job_results.sort_by { |(kls, jr)| jr.totals["s"] }.reverse.first(table_limit)
         
     | 
| 
      
 11 
     | 
    
         
            +
              visible_kls = job_results.first(chart_limit).map(&:first)
         
     | 
| 
      
 12 
     | 
    
         
            +
            %>
         
     | 
| 
       6 
13 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                   
     | 
| 
       16 
     | 
    
         
            -
                   
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                        <td><%= val %></td>
         
     | 
| 
       21 
     | 
    
         
            -
                        <td><%= top.dig("ms", kls) %></td>
         
     | 
| 
       22 
     | 
    
         
            -
                      </tr>
         
     | 
| 
       23 
     | 
    
         
            -
                    <% end %>
         
     | 
| 
       24 
     | 
    
         
            -
                  <% else %>
         
     | 
| 
       25 
     | 
    
         
            -
                      <tr><td colspan=3><%= t("NoDataFound") %></td></tr>
         
     | 
| 
       26 
     | 
    
         
            -
                  <% end %>
         
     | 
| 
       27 
     | 
    
         
            -
                </tbody>
         
     | 
| 
       28 
     | 
    
         
            -
              </table>
         
     | 
| 
       29 
     | 
    
         
            -
            </div>
         
     | 
| 
      
 14 
     | 
    
         
            +
            <canvas id="job-metrics-overview-chart"></canvas>
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            <script>
         
     | 
| 
      
 17 
     | 
    
         
            +
              window.jobMetricsChart = new JobMetricsOverviewChart(
         
     | 
| 
      
 18 
     | 
    
         
            +
                "job-metrics-overview-chart",
         
     | 
| 
      
 19 
     | 
    
         
            +
                <%= Sidekiq.dump_json({
         
     | 
| 
      
 20 
     | 
    
         
            +
                  series: job_results.map { |(kls, jr)| [kls, jr.dig("series", "s")] }.to_h,
         
     | 
| 
      
 21 
     | 
    
         
            +
                  marks: @query_result.marks.map { |m| [m.bucket, m.label] },
         
     | 
| 
      
 22 
     | 
    
         
            +
                  visible: visible_kls,
         
     | 
| 
      
 23 
     | 
    
         
            +
                  labels: @query_result.buckets,
         
     | 
| 
      
 24 
     | 
    
         
            +
                }) %>
         
     | 
| 
      
 25 
     | 
    
         
            +
              )
         
     | 
| 
      
 26 
     | 
    
         
            +
            </script>
         
     | 
| 
       30 
27 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
            < 
     | 
| 
      
 28 
     | 
    
         
            +
            <h2>Most Time-Consuming Jobs</h2>
         
     | 
| 
       32 
29 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
            <% topms = top["ms"]&.first(10) %>
         
     | 
| 
       34 
30 
     | 
    
         
             
            <div class="table_container">
         
     | 
| 
       35 
31 
     | 
    
         
             
              <table class="table table-bordered table-striped table-hover">
         
     | 
| 
       36 
32 
     | 
    
         
             
                <tbody>
         
     | 
| 
       37 
33 
     | 
    
         
             
                  <tr>
         
     | 
| 
       38 
34 
     | 
    
         
             
                    <th><%= t('Name') %></th>
         
     | 
| 
       39 
35 
     | 
    
         
             
                    <th><%= t('Processed') %></th>
         
     | 
| 
      
 36 
     | 
    
         
            +
                    <th><%= t('Failed') %></th>
         
     | 
| 
       40 
37 
     | 
    
         
             
                    <th><%= t('ExecutionTime') %></th>
         
     | 
| 
      
 38 
     | 
    
         
            +
                    <th><%= t('AvgExecutionTime') %></th>
         
     | 
| 
       41 
39 
     | 
    
         
             
                  </tr>
         
     | 
| 
       42 
     | 
    
         
            -
                  <% if  
     | 
| 
       43 
     | 
    
         
            -
                    <%  
     | 
| 
      
 40 
     | 
    
         
            +
                  <% if job_results.any? %>
         
     | 
| 
      
 41 
     | 
    
         
            +
                    <% job_results.each_with_index do |(kls, jr), i| %>
         
     | 
| 
       44 
42 
     | 
    
         
             
                      <tr>
         
     | 
| 
       45 
     | 
    
         
            -
                        <td 
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
                        <td>
         
     | 
| 
      
 44 
     | 
    
         
            +
                          <div class="metrics-swatch-wrapper">
         
     | 
| 
      
 45 
     | 
    
         
            +
                            <% id = "metrics-swatch-#{kls}" %>
         
     | 
| 
      
 46 
     | 
    
         
            +
                            <input
         
     | 
| 
      
 47 
     | 
    
         
            +
                              type="checkbox"
         
     | 
| 
      
 48 
     | 
    
         
            +
                              id="<%= id %>"
         
     | 
| 
      
 49 
     | 
    
         
            +
                              class="metrics-swatch"
         
     | 
| 
      
 50 
     | 
    
         
            +
                              value="<%= kls %>"
         
     | 
| 
      
 51 
     | 
    
         
            +
                            />
         
     | 
| 
      
 52 
     | 
    
         
            +
                            <code><a href="<%= root_path %>metrics/<%= kls %>"><%= kls %></a></code>
         
     | 
| 
      
 53 
     | 
    
         
            +
                          </div>
         
     | 
| 
      
 54 
     | 
    
         
            +
                          <script>jobMetricsChart.registerSwatch("<%= id %>")</script>
         
     | 
| 
      
 55 
     | 
    
         
            +
                        </td>
         
     | 
| 
      
 56 
     | 
    
         
            +
                        <td><%= jr.dig("totals", "p") %></td>
         
     | 
| 
      
 57 
     | 
    
         
            +
                        <td><%= jr.dig("totals", "f") %></td>
         
     | 
| 
      
 58 
     | 
    
         
            +
                        <td><%= jr.dig("totals", "s").round(2) %> seconds</td>
         
     | 
| 
      
 59 
     | 
    
         
            +
                        <td><%= jr.total_avg("s").round(2) %> seconds</td>
         
     | 
| 
       48 
60 
     | 
    
         
             
                      </tr>
         
     | 
| 
       49 
61 
     | 
    
         
             
                    <% end %>
         
     | 
| 
       50 
62 
     | 
    
         
             
                  <% else %>
         
     | 
| 
       51 
     | 
    
         
            -
                      <tr><td colspan= 
     | 
| 
      
 63 
     | 
    
         
            +
                      <tr><td colspan=5><%= t("NoDataFound") %></td></tr>
         
     | 
| 
       52 
64 
     | 
    
         
             
                  <% end %>
         
     | 
| 
       53 
65 
     | 
    
         
             
                </tbody>
         
     | 
| 
       54 
66 
     | 
    
         
             
              </table>
         
     | 
| 
       55 
67 
     | 
    
         
             
            </div>
         
     | 
| 
       56 
68 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
            <p>
         
     | 
| 
       58 
     | 
    
         
            -
            Data from <%= @resultset[:starts_at] %> to <%= @resultset[:ends_at] %>
         
     | 
| 
       59 
     | 
    
         
            -
            </p>
         
     | 
| 
      
 69 
     | 
    
         
            +
            <p><small>Data from <%= @query_result.starts_at %> to <%= @query_result.ends_at %></small></p>
         
     |