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