Juu Sii (UC)

Uudised peamiselt Unified Communications valdkonnast eesti keeles.

Finding Sent/Received per user per day and average message size

Finding Sent/Received per user per day and average message size

  • Comments 7
  • Likes

I need quite often to upgrade customers Exchange organization to newer version. Before I can start upgrade I need to figure out how many servers and what kind of hardware customer needs for new Exchange servers. Exchange Product Group released Excel spreadsheets to simplify finding hardware for new Exchange environment (you can find Exchange 2013 Server Role Requirements Calculator or Exchange 2010 Server Role Requirements Calculator at Exchange PG blog). Calculator is expecting 2 input values present for these calculations: sent/received item count per user per day, and average message size. Finding these values are not something you can explicitly get from system and usually we need to use some script which analyze message tracking log and calculates these values. I believe that most popular method is using MessageStats script created by Rob Campbell and blog article by Neil Johnson. Script will analyze lots of information and creates CSV file which you should import to Excel, remove some columns and add some formulas at the end of table to get sent/received count and average message size. If you are using often this script and later modifying CSV file then it doesn’t feel complicated. Although if you are using first time or not so often, then you usually using blog article and following carefully steps. Most of the time you usually spending just waiting until script is finished and for bigger companies (lots of severs and thousands of users) it might take loooong (hours, even days).

I get bored (I believe this is the right word) to modifying CSV file every time after script has finished. Usually my customers are just leaving this activity to me, just sending CSV files to me. And quite often I want to get sent/received items and average message size when I am already onsite and analyzing their Exchange environment but getting CSV file is problem as I don’t have Internet access at customer site. That’s why I was starting to create script which will give you sent/received item count and average message size automatically as output of script work and without additional work. After starting to create the script I changed little bit the scope and added some additional functionality the script can do. So currently Powershell script is ready and these values you are looking are displayed at the end of script. And as bonus the script is working more than twice faster compared with the MessageStat script.

Finding good name for script was quite challenging. I finally decided to name it as CalcMsgAverage.ps1. You can get syntax for script with command CalcMsgAverage.ps1 -Help:

You can also use CalsMsgAverage.ps1 -Examples command to get view some examples which cover some basic scenarios:

Some comments for several parameters in script.

First bundle for specifying timeframe: Period, StartTime and EndTime. Script will need at least one of these present. If there is none of timeframe parameters specified then Period is set to 1, EndTime is set script startup time and StartTime as 1 day back from EndTime (so it will analyze last 24 hours records). Most common usage might be to analyze last 30 days from script startup: CalcMsgAverage.ps1 30 (Period is positional parameter and you don’t need to specify it). If all three time parameters are present then Period will be ignored and calculated from StartTime and EndTime parameter. By the way – you can use fraction part with Period parameter, for example 1.5 as Period means one and half day or 36 hours. Please take a note that period is important to calculate average values. For example if you have server log files for 10 days only but you are specifying Period as 20 days, then even if you have data for 10 days, average will be calculated for 20 days (instead of dividing by 10, it will be divided by 20). It means smaller number compared actual value. Usually this might happen for new servers only where collecting message tracking information haven’t done for longer period.

You can also specify what servers to analyze (using Servers parameter). This could be useful if you want to analyze only few servers from bigger range. The opposite functional approach using SkipServers parameter which enables you skip certain servers from analyzing results (for example some servers might be down). For both parameters if there are more than one name then include text to parenthesis (single or double) and separate values by coma or semicolon. If you include both Servers and SkipServers parameters then SkipServers parameter will be ignored (why the hell you need specify servers and then skip them?).

There is one parameter I created targeted to Exchange 2013 only (it will make no difference for older Exchange versions). This parameter is SkipHealthMailboxes which makes script to skip all Exchange 2013 health messages from calculation and analyze activities. Usually the difference is very small and not so different from actual value. It might give some effect if you have Exchange 2013 installed for some period but no user mailboxes migrated to this server yet. So no sent/received mails for users but all traffic is only for health mailbox probe messages.

I did testing comparing CalcMsgAverage script by analyzing 30 days of data for about 700 user environment and then using exactly the same timeframe for MessageStats script.

First example using CalcMsgAverage with 30 days period, running 40 minutes 40 seconds.

Second example using CalcMsgAverage with 30 days (exactly the same start and end time) but using SkipHealthMailboxes parameter (MBX01 and MBX02 is Exchange 2013). Running time 40 minutes 6 seconds.

Third example using MessageStats with 30 days (exactly the same start and end time written inside to script). Running time 7300 seconds which is little more than 2 hours. It means CalcMsgAverage is more than twice faster compared to MessageStats (40 minutes versus 121 minutes).

I also found that there are some inconsistency between CalcMsgAverage and MessageStats. I did some tests to find out why it’s happening and found out that MessageStats is analyzing incorrectly under certain conditions (it will add e-mail size to calculation but don’t increase user count which will give back wrong statistical results).

Please let me know your feedback, also suggestions and bug report (I really hope there are none but you never know). You can download CalcMsgAverage script from TechNet Gallery here.

Comments
  • Nice script! Is it in the TechNet Gallery too?

  • Awesome
    Thanks

  • Now it is published to TechNet Gallery too

  • Thanks!

  • When running the script inside an Exchange 2013 shell I get the following output:

    [PS] C:\scripts>.\CalcMsgAverage.ps1 -Servers "DC-Exchange"
    Cannot convert the "DC-EXCHANGE" value of type "System.String" to type "System.Collections.ArrayList".
    At C:\scripts\CalcMsgAverage.ps1:145 char:1
    + $Exchange2013Transport = [System.Collections.ArrayList]($ExchangeServers | Where ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

    Cannot convert the "DC-EXCHANGE" value of type "System.String" to type "System.Collections.ArrayList".
    At C:\scripts\CalcMsgAverage.ps1:147 char:1
    + $TransportServers = [System.Collections.ArrayList]($ExchangeServers | Where {$_. ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [], RuntimeException
    + FullyQualifiedErrorId : ConvertToFinalInvalidCastException

    You cannot call a method on a null-valued expression.
    At C:\scripts\CalcMsgAverage.ps1:171 char:13
    + If (-not $TransportServers.Contains($Server)) {
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

    Any help would be greatly appreciated.

  • @Tee: I have seen similar error few months ago and the reason seems to be not updated .NET version. One option is definitely update .NET to 3.5.1 version, another option is to little bit change the lines 145 and 147 to make it work even not updated .NET (this is how I solved it last time). I try to find some time to provide update which should be solving this problem also.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment