Generates a report with the number of promote transactions and versions promoted per user and stream that occurred in select streams during a specified time period. In the appSettings section of PromoCount.exe.config
change the StartTime and EndTime to their respective values and include the streams to query in the Streams section. Include the depots where the streams are located in the Depots section. Results are written to the daily log file PromoCountResults-YYYY-MM-DD.log
created (or updated) in the same folder where PromoCount.exe
resides.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="activeDir" type="AcUtils.ADSection, AcUtils, Version=1.6.4.0, Culture=neutral, PublicKeyToken=26470c2daf5c2e2f, processorArchitecture=MSIL"/>
<section name="Depots" type="AcUtils.DepotsSection, AcUtils, Version=1.6.4.0, Culture=neutral, PublicKeyToken=26470c2daf5c2e2f, processorArchitecture=MSIL"/>
<section name="Streams" type="AcUtils.StreamsSection, AcUtils, Version=1.6.4.0, Culture=neutral, PublicKeyToken=26470c2daf5c2e2f, processorArchitecture=MSIL"/>
</configSections>
<activeDir>
<domains>
<!-- contact your company LDAP administrator for these values -->
<add host="xyzdc.yourcorp.com" path="DC=OMIT1,DC=ad,DC=yourcorp,DC=com"/>
<add host="abcdc.yourcorp.com" path="DC=OMIT2,DC=yourcorp,DC=com"/>
</domains>
<properties>
</properties>
</activeDir>
<Depots>
<depots>
<!-- depots where the streams below are located -->
</depots>
</Depots>
<Streams>
<streams>
<!-- add/
remove the streams
to query
from depots listed above -->
<add
stream=
"NEPTUNE_MAINT1"/>
</streams>
</Streams>
<appSettings>
<!-- YYYY/MM/DD hh:mm:ss (24 hour time format) -->
<add key="StartTime" value="2018/04/16 00:00:00"/>
<add key="EndTime" value="2018/04/20 23:59:59"/>
</appSettings>
<system.diagnostics>
<assert assertuienabled="false"/>
<sources>
<source name="PromoCount">
<listeners>
<remove name="Default"/>
<add name="AcLog" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"/>
<add name="PromoCountResults" type="Microsoft.VisualBasic.Logging.FileLogTraceListener, Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL"/>
</listeners>
</source>
</sources>
</system.diagnostics>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
</startup>
</configuration>
using System.Collections.Generic;
using Microsoft.VisualBasic.Logging;
namespace PromoCount
{
class Program
{
#region class variables
private static DomainCollection _domains;
private static DepotsCollection _selDepots;
private static StreamsCollection _selStreams;
private static string _startTime;
private static string _endTime;
private static AcUsers _users;
private static AcDepots _depots;
private static readonly object _locker = new object();
private static FileLogTraceListener _tl;
#endregion
static int Main()
{
if (!init()) return 1;
Task<bool> r = promoCountAsync();
return (r.Result) ? 0 : 1;
}
private static async Task<bool> promoCountAsync()
{
bool ret = false;
try
{
Dictionary<AcStream, Task<AcResult>> map = new Dictionary<AcStream, Task<AcResult>>(_selStreams.Count);
Func<AcStream, Task<AcResult>> run = (
stream) =>
{
Task<AcResult> result = AcCommand.runAsync(
$@"hist -fx -k promote -s ""{stream}"" -t ""{_endTime} - {_startTime}""");
lock (_locker) { map.Add(
stream, result); }
return result;
};
var tasks =
from s in _depots.SelectMany(d => d.Streams)
where _selStreams.OfType<StreamElement>().Any(se => se.Stream == s.Name)
select run(s);
AcResult[] arr = await Task.WhenAll(tasks);
if (arr == null || arr.Any(r => r.RetVal != 0)) return false;
log($"Promotions to select streams from {_startTime} to {_endTime}.{Environment.NewLine}");
int tgrandtot = 0; int vgrandtot = 0;
foreach (var ii in map.OrderBy(n => n.Key))
{
log($"{ii.Key} {{{$"promotions\\versions"}}}:");
AcResult r = ii.Value.Result;
XElement xml = XElement.Parse(r.CmdResult);
ILookup<string, XElement> look = xml.Elements("transaction")
.ToLookup(n => (string)n.Attribute("user"), n => n);
int tsubtot = 0; int vsubtot = 0;
foreach (var jj in look.OrderBy(n => _users.getUser(n.Key)))
{
AcUser
user = _users.getUser(jj.Key);
int tnum = jj.Count();
int vnum = jj.Elements("version").Count();
string val = $"{{{tnum}\\{vnum}}}";
log($"\t{user.ToString().PadRight(40, '.')}{val.PadLeft(13, '.')}");
tsubtot += tnum; tgrandtot += tnum;
vsubtot += vnum; vgrandtot += vnum;
}
log($"\tTotal {tsubtot} promotions and {vsubtot} versions.{Environment.NewLine}");
}
log($"Grand total of {tgrandtot} promotions and {vgrandtot} versions.");
ret = true;
}
catch (AcUtilsException ecx)
{
AcDebug.Log($"AcUtilsException caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}");
}
catch (Exception ecx)
{
AcDebug.Log($"Exception caught and logged in Program.promoCountAsync{Environment.NewLine}{ecx.Message}");
}
return ret;
}
private static bool init()
{
if (!AcDebug.initAcLogging())
{
Console.WriteLine("Logging support initialization failed.");
return false;
}
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AcDebug.unhandledException);
Task<string> prncpl = AcQuery.getPrincipalAsync();
if (String.IsNullOrEmpty(prncpl.Result))
{
AcDebug.Log($"Not logged into AccuRev.{Environment.NewLine}Please login and try again.");
return false;
}
if (!initAppConfigData()) return false;
if (!initPromoCountResultsLogging()) return false;
_users = new AcUsers(_domains, null, includeGroupsList: false, includeDeactivated: true);
_depots = new AcDepots(dynamicOnly: true);
Task<bool[]> lists = Task.WhenAll(_depots.initAsync(_selDepots), _users.initAsync());
if (lists == null || lists.Result.Any(n => n == false)) return false;
return true;
}
private static bool initAppConfigData()
{
bool ret = true;
try
{
_startTime = AcQuery.getAppConfigSetting<string>("StartTime").Trim();
_endTime = AcQuery.getAppConfigSetting<string>("EndTime").Trim();
ADSection adSection = ConfigurationManager.GetSection("activeDir") as ADSection;
if (adSection == null)
{
AcDebug.Log("Error in Program.initAppConfigData creating ADSection");
ret = false;
}
else
_domains = adSection.Domains;
DepotsSection depotsConfigSection = ConfigurationManager.GetSection("Depots") as DepotsSection;
if (depotsConfigSection == null)
{
AcDebug.Log("Error in Program.initAppConfigData creating DepotsSection");
ret = false;
}
else
_selDepots = depotsConfigSection.Depots;
StreamsSection streamsConfigSection = ConfigurationManager.GetSection("Streams") as StreamsSection;
if (streamsConfigSection == null)
{
AcDebug.Log("Error in Program.initAppConfigData creating StreamsSection");
ret = false;
}
else
_selStreams = streamsConfigSection.Streams;
}
catch (ConfigurationErrorsException exc)
{
Process currentProcess = Process.GetCurrentProcess();
ProcessModule pm = currentProcess.MainModule;
AcDebug.Log($"Invalid data in {pm.ModuleName}.config{Environment.NewLine}{exc.Message}");
ret = false;
}
return ret;
}
private static bool initPromoCountResultsLogging()
{
bool ret = false;
try
{
TraceSource ts = new TraceSource("PromoCount");
_tl = (FileLogTraceListener)ts.Listeners["PromoCountResults"];
_tl.Location = LogFileLocation.ExecutableDirectory;
_tl.BaseFileName = "PromoCountResults";
_tl.MaxFileSize = 83886080;
_tl.ReserveDiskSpace = 2500000000;
_tl.LogFileCreationSchedule = LogFileCreationScheduleOption.Daily;
_tl.AutoFlush = true;
ret = true;
}
catch (Exception exc)
{
AcDebug.Log($"Exception caught and logged in Program.initPromoCountResultsLogging{Environment.NewLine}{exc.Message}");
}
return ret;
}
private static void log(
string text)
{
if (_tl != null)
_tl.WriteLine(text);
}
}
}