# All files / src metrics.coffee

21.43% Statements 3/14
0% Branches 0/7
0% Functions 0/2
21.43% Lines 3/14

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    1241x
    1x

    1x

     Transaction = require('./model/transactions').Transaction
    logger = require 'winston'

    # Calculates transaction metrics
    #
    # @startDate {Date} a timestamp representing the start of the range to calculate
    #                   metrics from (required)
    # @startDate {Date} a timestamp representing the end of the range to calculate
    #                   metrics to (required)
    # @transactionFilter {Object} a mongodb filter object to further restrict the
    #                             transactions collection (nullable)
    # @channelIDs {Array} an array of channel IDs as `ObjectID`s to filter by, if
    #                     not set all channels will be considered (nullable)
    # @timeSeries {String} one of 'minute', 'hour', 'day', 'week', 'month', 'year'.
    #                      If set the metrics will be grouped into a periods of the
    #                      stated duration, otherwise, metrics for the entire period
    #                      will be returned (nullable)
    # @groupByChannel {Boolean} if true the metrics will be grouped by each
    #                           particular channel that returns results (nullable)
    # @returns {Promise} that resolves to an array of metric objects for each
    #                    grouping (timeseries and/or channel) depending on the
    #                    parameters that are set
    # e.g. metrics.calculateMetrics new Date("2014-07-15T00:00:00.000Z"),
    # new Date("2014-07-19T00:00:00.000Z"), null, null, 'day', true
    # [
    #   {
    #     _id: {
    #       channelID: 111111111111111111111111,
    #       day: 18,
    #       week: 28,
    #       month: 7,
    #       year: 2014
    #     },
    #     total: 1,
    #     avgResp: 100,
    #     minResp: 100,
    #     maxResp: 100,
    #     failed: 0,
    #     successful: 0,
    #     processing: 1,
    #     completed: 0,
    #     completedWErrors: 0
    #   }, {
    #     _id:
    #       {
    #         channelID: 222222222222222222222222,
    #         day: 18,
    #         week: 28,
    #         month: 7,
    #         year: 2014 },
    #     total: 1,
    #     avgResp: 200,
    #     minResp: 200,
    #     maxResp: 200,
    #     failed: 0,
    #     successful: 0,
    #     processing: 0,
    #     completed: 1,
    #     completedWErrors: 0
    #   }
    # ]
    exports.calculateMetrics = (startDate, endDate, transactionFilter, channelIDs, timeSeries, groupByChannels) ->
      if not (startDate instanceof Date) or not (endDate instanceof Date)
        return new Promise (resolve, reject) ->
          reject new Error 'startDate and endDate must be provided and be of type Date'

      match =
        "request.timestamp":
          $lt: endDate
          $gt: startDate
      if transactionFilter
        Object.assign match, transactionFilter

      if channelIDs
        match.channelID =
          $in: channelIDs

      group =
        _id: {}
        total: $sum: 1
        avgResp: $avg: $subtract: [ "$response.timestamp", "$request.timestamp" ]
        minResp: $min: $subtract: [ "$response.timestamp", "$request.timestamp" ]
        maxResp: $max: $subtract: [ "$response.timestamp", "$request.timestamp" ]
        failed: $sum: $cond: [ $eq: [ "$status", "Failed" ], 1, 0 ]
        successful: $sum: $cond: [ $eq: [ "$status", "Successful" ], 1, 0 ]
        processing: $sum: $cond: [ $eq: [ "$status", "Processing" ], 1, 0 ]
        completed: $sum: $cond: [ $eq: [ "$status", "Completed" ], 1, 0 ]
        completedWErrors: $sum: $cond: [ $eq: [ "$status", "Completed with error(s)" ], 1, 0 ]
      if groupByChannels
        group._id.channelID = '$channelID'

      if timeSeries
        switch timeSeries
          when "minute"
            group._id.minute = $minute: "$request.timestamp"
            group._id.hour = $hour: "$request.timestamp"
            group._id.day = $dayOfMonth: "$request.timestamp"
            group._id.week = $week: "$request.timestamp"
            group._id.month = $month: "$request.timestamp"
            group._id.year = $year: "$request.timestamp"
          when "hour"
            group._id.hour = $hour: "$request.timestamp"
            group._id.week = $week: "$request.timestamp"
            group._id.day = $dayOfMonth: "$request.timestamp"
            group._id.month = $month: "$request.timestamp"
            group._id.year = $year: "$request.timestamp"
          when "day"
            group._id.day = $dayOfMonth: "$request.timestamp"
            group._id.week = $week: "$request.timestamp"
            group._id.month = $month: "$request.timestamp"
            group._id.year = $year: "$request.timestamp"
          when "week"
            group._id.week = $week: "$request.timestamp"
            group._id.month = $month: "$request.timestamp"
            group._id.year = $year: "$request.timestamp"
          when "month"
            group._id.month = $month: "$request.timestamp"
            group._id.year = $year: "$request.timestamp"
          when "year"
            group._id.year = $year: "$request.timestamp"

      pipeline = [ { $match: match }, { $group: group } ]
      return Transaction.aggregate(pipeline).exec()