1
\$\begingroup\$

The following is a snippet from a script I have that fetches a list of objects representing requests to a server and graphs them using C3.js. I've only included the relevant code that parses the list of request objects for relevant data.

const iterByDay = (min, max, callback) => {
  var tmp = moment(min)
  for (const day = tmp; day.isBefore(max); day.add(1, 'day')) {
    callback(day)
  }
}

const getDateRange = data => {
  return data.length < 2 ? null : {
    min: moment(data[0].timestamp).startOf('day'),
    max: moment(data[data.length - 1].timestamp).endOf('day')
  }
}

const min = l => {
  return !l ? 0 : Math.round(Math.min(...l))
}

const avg = l => {
  return !l ? 0 : Math.round(l.reduce((a, b) => a + b) / l.length)
}

const max = l => {
  return !l ? 0 : Math.round(Math.max(...l))
}

const getTrafficData = data => {
  const hitsPerDay = new Map()
  for (const entry of data) {
    const day = moment(entry.timestamp).startOf('day').toString()
    hitsPerDay.set(day, (hitsPerDay.get(day) || 0) + 1)
  }
  const dateColumn = ['date']
  const hitsPerDayColumn = ['total requests']
  const range = getDateRange(data)
  iterByDay(range.min, range.max, day => {
    dateColumn.push(day.format('YYYY-MM-DD'))
    day = day.toString()
    hitsPerDayColumn.push(hitsPerDay.get(day) || 0)
  })
  return [dateColumn, hitsPerDayColumn]
}

const getResponseTimeData = data => {
  const timesByDay = []
  for (var entry of data) {
    const day = moment(entry.timestamp).startOf('day')
    if (timesByDay[day]) {
      timesByDay[day].push(entry.responseTime || 0)
    } else {
      timesByDay[day] = [entry.responseTime || 0]
    }
  };
  const dateColumn = ['date']
  const minColumn = ['min']
  const avgColumn = ['avg']
  const maxColumn = ['max']
  const range = getDateRange(data)
  iterByDay(range.min, range.max, day => {
    dateColumn.push(day.format('YYYY-MM-DD'))
    minColumn.push(min(timesByDay[day]))
    avgColumn.push(avg(timesByDay[day]))
    maxColumn.push(max(timesByDay[day]))
  })
  return [dateColumn, maxColumn, avgColumn, minColumn]
}

const getSectionFrequencyData = data => {
  const frequencies = new Map()
  for (const entry of data) {
    const url = /\/([a-z]+)|$/g.exec(entry.req.url || '')[1] || 'home'
    frequencies.set(url, (frequencies.get(url) || 0) + 1)
  }
  const sorted10 = new Map(
    [...frequencies.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10)
  )
  return [
    ['sections', ...sorted10.keys()],
    ['frequency', ...sorted10.values()]
  ]
}

const getCountryFrequencyData = data => {
  const frequencies = new Map()
  for (const entry of data) {
    const country = entry.country || 'unknown'
    frequencies.set(country, (frequencies.get(country) || 0) + 1)
  }
  const sorted10 = new Map(
    [...frequencies.entries()].sort((a, b) => b[1] - a[1]).slice(0, 10)
  )
  return [
    ['countries', ...sorted10.keys()],
    ['frequency', ...sorted10.values()]
  ]
}

The functions are passed lists of objects that look like this:

[{
  timestamp: ...,
  country: ...,
  url: ...,
  ....
}, {
  timestamp: ...,
  country: ...,
  url: ...,
  ...
}]

and I am guaranteed that the objects are already sorted chronologically by timestamp. I'm sure that this code can be vastly improved.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.