Created
June 18, 2024 18:28
-
-
Save FabienLavocat/a37be2efcb4e0fe053d2374ae0c55f6e to your computer and use it in GitHub Desktop.
Dolby Millicast - compute the bandwidth consumed by the streams between two dates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var https = require('https'); | |
const readline = require('node:readline/promises'); | |
const { stdin: input, stdout: output } = require('node:process'); | |
/** | |
* Provide your Dolby Millicast API Secret | |
*/ | |
var bearer = null; | |
/** | |
* Compute the bandwidth from this date. | |
* Format: YYYY-MM-DD | |
*/ | |
var from = null; | |
/** | |
* Compute the bandwidth until this date. | |
* Format: YYYY-MM-DD | |
* Default: end of day today | |
*/ | |
var to = null; | |
async function promptForParameters() { | |
const rl = readline.createInterface({ input, output }); | |
if (!bearer) { | |
bearer = await rl.question('\x1b[33mProvide your Dolby Millicast API Secret:\x1b[0m '); | |
} | |
if (!from) { | |
from = await rl.question('\x1b[33mCompute the bandwidth from (YYYY-MM-DD):\x1b[0m '); | |
} | |
if (!to) { | |
const tomorrow = new Date(); | |
tomorrow.setDate(tomorrow.getDate() + 1); | |
const toDefault = tomorrow.toISOString().substring(0, 10); | |
to = await rl.question(`\x1b[33mCompute the bandwidth until (YYYY-MM-DD) (default is ${toDefault}):\x1b[0m `); | |
if (!to) { | |
to = toDefault; | |
} | |
} | |
rl.close(); | |
} | |
function getStreamIdsPage(page) { | |
return new Promise((resolve, reject) => { | |
var options = { | |
method: 'POST', | |
hostname: 'api.millicast.com', | |
path: '/graphql', | |
headers: { | |
'Content-Type': 'application/json', | |
Authorization: `Bearer ${bearer}`, | |
}, | |
}; | |
var req = https.request(options, function (res) { | |
var chunks = []; | |
res.on('data', function (chunk) { | |
chunks.push(chunk); | |
}); | |
res.on('end', function (chunk) { | |
var body = Buffer.concat(chunks); | |
resolve(JSON.parse(body.toString())); | |
}); | |
res.on('error', function (error) { | |
reject(error); | |
}); | |
}); | |
var postData = JSON.stringify({ | |
query: `query StreamStatPagination($page: Int = ${page}) {streamStatPagination( page: $page, perPage: 150, filter: { _operators: { from: { gt: "${from}" } }, AND: { _operators: { to: { lt: "${to}"} } } }) { count items { streamId from to } pageInfo { currentPage perPage pageCount itemCount hasNextPage hasPreviousPage } } }`, | |
}); | |
req.write(postData); | |
req.end(); | |
}); | |
} | |
async function getStreamIds() { | |
const streamIds = []; | |
let page = 1; | |
while (true) { | |
const result = await getStreamIdsPage(page++); | |
for (let index = 0; index < result.data.streamStatPagination.items.length; index++) { | |
const item = result.data.streamStatPagination.items[index]; | |
if (!streamIds.includes(item.streamId)) { | |
streamIds.push(item.streamId); | |
} | |
} | |
if (!result.data.streamStatPagination.pageInfo.hasNextPage) { | |
break; | |
} | |
} | |
return streamIds; | |
} | |
function loadStream(streamName) { | |
return new Promise((resolve, reject) => { | |
var options = { | |
method: 'GET', | |
hostname: 'api.millicast.com', | |
path: `/api/analytics/streams/series?resolution=Day&streamNames=${streamName}&startDate=${from}T00:00:00Z&stopDate=${to}T00:00:00Z`, | |
headers: { | |
Authorization: `Bearer ${bearer}`, | |
}, | |
maxRedirects: 20, | |
}; | |
var req = https.request(options, function (res) { | |
var chunks = []; | |
res.on('data', function (chunk) { | |
chunks.push(chunk); | |
}); | |
res.on('end', function (chunk) { | |
var body = Buffer.concat(chunks); | |
resolve(JSON.parse(body.toString())); | |
}); | |
res.on('error', function (error) { | |
reject(error); | |
}); | |
}); | |
req.end(); | |
}); | |
} | |
function toGB(bytes) { | |
const formatter = Intl.NumberFormat(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); | |
const gb = bytes / 1024 / 1024 / 1024; | |
return formatter.format(gb); | |
} | |
async function computeBw() { | |
const streamIds = await getStreamIds(); | |
var bw = 0; | |
for (let index = 0; index < streamIds.length; index++) { | |
const streamName = streamIds[index].substring(7); | |
const result = await loadStream(streamName); | |
if (result.data[streamName]) { | |
const bandwidth = result.data[streamName].bandwidth; | |
const dates = Object.keys(bandwidth); | |
for (let j = 0; j < dates.length; j++) { | |
const date = dates[j]; | |
const bytesOut = bandwidth[date].bytesOut; | |
const bytesIn = bandwidth[date].bytesIn; | |
bw += bytesOut + bytesIn; | |
if (bytesIn > 0) { | |
const strDate = new Date(date).toISOString().substring(0, 10); | |
const ratio = bytesOut / bytesIn; | |
const bwDay = toGB(bytesOut + bytesIn); | |
console.log(`${streamName} - ${strDate} - IN: ${toGB(bytesIn)} GB - OUT: ${toGB(bytesOut)} GB - Ratio: ${ratio.toFixed(2)}x - Total bw: ${bwDay} GB`); | |
} | |
} | |
console.log(); | |
} | |
} | |
return bw; | |
} | |
promptForParameters() | |
.then(computeBw) | |
.then((bw) => console.log(`Account bandwidth: ${toGB(bw)} GB`)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment