github.com/Ilhicas/nomad@v1.0.4-0.20210304152020-e86851182bc3/ui/app/utils/classes/allocation-stats-tracker.js (about) 1 import EmberObject, { get, computed } from '@ember/object'; 2 import { alias } from '@ember/object/computed'; 3 import RollingArray from 'nomad-ui/utils/classes/rolling-array'; 4 import AbstractStatsTracker from 'nomad-ui/utils/classes/abstract-stats-tracker'; 5 import classic from 'ember-classic-decorator'; 6 7 const percent = (numerator, denominator) => { 8 if (!numerator || !denominator) { 9 return 0; 10 } 11 return numerator / denominator; 12 }; 13 14 const empty = ts => ({ timestamp: ts, used: null, percent: null }); 15 16 @classic 17 class AllocationStatsTracker extends EmberObject.extend(AbstractStatsTracker) { 18 // Set via the stats computed property macro 19 allocation = null; 20 21 @computed('allocation.id') 22 get url() { 23 return `/v1/client/allocation/${this.get('allocation.id')}/stats`; 24 } 25 26 append(frame) { 27 const timestamp = new Date(Math.floor(frame.Timestamp / 1000000)); 28 29 const cpuUsed = Math.floor(frame.ResourceUsage.CpuStats.TotalTicks) || 0; 30 this.cpu.pushObject({ 31 timestamp, 32 used: cpuUsed, 33 percent: percent(cpuUsed, this.reservedCPU), 34 }); 35 36 const memoryUsed = frame.ResourceUsage.MemoryStats.RSS; 37 this.memory.pushObject({ 38 timestamp, 39 used: memoryUsed, 40 percent: percent(memoryUsed / 1024 / 1024, this.reservedMemory), 41 }); 42 43 for (var taskName in frame.Tasks) { 44 const taskFrame = frame.Tasks[taskName]; 45 const stats = this.tasks.findBy('task', taskName); 46 47 // If for whatever reason there is a task in the frame data that isn't in the 48 // allocation, don't attempt to append data for the task. 49 if (!stats) continue; 50 51 const frameTimestamp = new Date(Math.floor(taskFrame.Timestamp / 1000000)); 52 53 const taskCpuUsed = Math.floor(taskFrame.ResourceUsage.CpuStats.TotalTicks) || 0; 54 stats.cpu.pushObject({ 55 timestamp: frameTimestamp, 56 used: taskCpuUsed, 57 percent: percent(taskCpuUsed, stats.reservedCPU), 58 }); 59 60 const taskMemoryUsed = taskFrame.ResourceUsage.MemoryStats.RSS; 61 stats.memory.pushObject({ 62 timestamp: frameTimestamp, 63 used: taskMemoryUsed, 64 percent: percent(taskMemoryUsed / 1024 / 1024, stats.reservedMemory), 65 }); 66 } 67 } 68 69 pause() { 70 const ts = new Date(); 71 this.memory.pushObject(empty(ts)); 72 this.cpu.pushObject(empty(ts)); 73 this.tasks.forEach(task => { 74 task.memory.pushObject(empty(ts)); 75 task.cpu.pushObject(empty(ts)); 76 }); 77 } 78 79 // Static figures, denominators for stats 80 @alias('allocation.taskGroup.reservedCPU') reservedCPU; 81 @alias('allocation.taskGroup.reservedMemory') reservedMemory; 82 83 // Dynamic figures, collected over time 84 // []{ timestamp: Date, used: Number, percent: Number } 85 @computed('allocation', 'bufferSize') 86 get cpu() { 87 return RollingArray(this.bufferSize); 88 } 89 90 @computed('allocation', 'bufferSize') 91 get memory() { 92 return RollingArray(this.bufferSize); 93 } 94 95 @computed('allocation.taskGroup.tasks', 'bufferSize') 96 get tasks() { 97 const bufferSize = this.bufferSize; 98 const tasks = this.get('allocation.taskGroup.tasks') || []; 99 return tasks.map(task => ({ 100 task: get(task, 'name'), 101 102 // Static figures, denominators for stats 103 reservedCPU: get(task, 'reservedCPU'), 104 reservedMemory: get(task, 'reservedMemory'), 105 106 // Dynamic figures, collected over time 107 // []{ timestamp: Date, used: Number, percent: Number } 108 cpu: RollingArray(bufferSize), 109 memory: RollingArray(bufferSize), 110 })); 111 } 112 } 113 114 export default AllocationStatsTracker; 115 116 export function stats(allocationProp, fetch) { 117 return computed(allocationProp, function() { 118 return AllocationStatsTracker.create({ 119 fetch: fetch.call(this), 120 allocation: this.get(allocationProp), 121 }); 122 }); 123 }