diff --git a/Source/AssemblyInfo.cs b/Source/AssemblyInfo.cs index c83e8ca..6cb920c 100644 --- a/Source/AssemblyInfo.cs +++ b/Source/AssemblyInfo.cs @@ -5,5 +5,5 @@ using System.Reflection; [assembly: AssemblyCompany("MS Open Tech")] [assembly: AssemblyProduct("Tx (LINQ to Logs and Traces)")] [assembly: AssemblyCopyright("Copyright © MS Open Tech 2012")] -[assembly: AssemblyVersion("1.0.50917.0")] -[assembly: AssemblyFileVersion("1.0.50917.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.0.50930.0")] +[assembly: AssemblyFileVersion("1.0.50930.0")] \ No newline at end of file diff --git a/Source/Tx.Windows/EtwNative/EtwNativeEvent.cs b/Source/Tx.Windows/EtwNative/EtwNativeEvent.cs index 837bd86..988b9e8 100644 --- a/Source/Tx.Windows/EtwNative/EtwNativeEvent.cs +++ b/Source/Tx.Windows/EtwNative/EtwNativeEvent.cs @@ -64,7 +64,7 @@ namespace Tx.Windows public DateTimeOffset TimeStamp { - get { return DateTime.FromFileTimeUtc(record->EventHeader.TimeStamp); } + get { return TimeUtil.DateTimeOffsetFromFileTime(record->EventHeader.TimeStamp); } } public Int64 TimeStampRaw diff --git a/Source/Tx.Windows/PerfCounters/PerfCounterFileReader.cs b/Source/Tx.Windows/PerfCounters/PerfCounterFileReader.cs index 9627119..023c8e8 100644 --- a/Source/Tx.Windows/PerfCounters/PerfCounterFileReader.cs +++ b/Source/Tx.Windows/PerfCounters/PerfCounterFileReader.cs @@ -55,7 +55,7 @@ namespace Tx.Windows break; PdhUtils.CheckStatus(status, PdhStatus.PDH_CSTATUS_VALID_DATA); - DateTime timestamp = DateTime.FromFileTimeUtc(time); + DateTime timestamp = TimeUtil.FromFileTime(time); foreach (PerfCounterInfo counterInfo in _counters) { diff --git a/Source/Tx.Windows/PerfCounters/PerfCounterRealTimeProbe.cs b/Source/Tx.Windows/PerfCounters/PerfCounterRealTimeProbe.cs index d626b13..8621e43 100644 --- a/Source/Tx.Windows/PerfCounters/PerfCounterRealTimeProbe.cs +++ b/Source/Tx.Windows/PerfCounters/PerfCounterRealTimeProbe.cs @@ -40,7 +40,7 @@ namespace Tx.Windows long time; PdhStatus status = PdhNativeMethods.PdhCollectQueryDataWithTime(_query, out time); PdhUtils.CheckStatus(status, PdhStatus.PDH_CSTATUS_VALID_DATA); - DateTime timestamp = DateTime.FromFileTimeUtc(time); + DateTime timestamp = TimeUtil.FromFileTime(time); foreach (PerfCounterInfo counterInfo in _counters) { diff --git a/Source/Tx.Windows/TimeUtil.cs b/Source/Tx.Windows/TimeUtil.cs new file mode 100644 index 0000000..3e7f109 --- /dev/null +++ b/Source/Tx.Windows/TimeUtil.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. + +using System; + +namespace Tx.Windows +{ + public sealed class TimeUtil + { + private const Int64 TicksPerMillisecond = 10000; + private const Int64 TicksPerSecond = TicksPerMillisecond * 1000; + private const Int64 TicksPerMinute = TicksPerSecond * 60; + private const Int64 TicksPerHour = TicksPerMinute * 60; + private const Int64 TicksPerDay = TicksPerHour * 24; + + // Number of days in a non-leap year + private const int DaysPerYear = 365; + // Number of days in 4 years + const int DaysPer4Years = DaysPerYear * 4 + 1; + // Number of days in 100 years + private const int DaysPer100Years = DaysPer4Years * 25 - 1; + // Number of days in 400 years + private const int DaysPer400Years = DaysPer100Years * 4 + 1; + + // Number of days from 1/1/0001 to 12/31/1600 + private const int DaysTo1601 = DaysPer400Years * 4; + + private const Int64 FileTimeOffset = DaysTo1601 * TicksPerDay; + + public static DateTimeOffset DateTimeOffsetFromFileTime(Int64 fileTime) + { + return new DateTimeOffset(FileTimeOffset + fileTime, TimeSpan.Zero); + } + + public static DateTime FromFileTime(Int64 fileTime) + { + return new DateTime(FileTimeOffset + fileTime, DateTimeKind.Local); + } + } +} + diff --git a/Source/Tx.Windows/Tx.Windows.csproj b/Source/Tx.Windows/Tx.Windows.csproj index ca1b85d..0dc44c9 100644 --- a/Source/Tx.Windows/Tx.Windows.csproj +++ b/Source/Tx.Windows/Tx.Windows.csproj @@ -87,6 +87,7 @@ + diff --git a/Test/UnitTests/PerfCounterTest.cs b/Test/UnitTests/PerfCounterTest.cs index 96d36bd..158de1e 100644 --- a/Test/UnitTests/PerfCounterTest.cs +++ b/Test/UnitTests/PerfCounterTest.cs @@ -10,6 +10,8 @@ using Tx.Windows; namespace Tests.Tx { + using System.Globalization; + [TestClass] public class PerfCounterTest { @@ -140,6 +142,39 @@ namespace Tests.Tx Assert.AreEqual(600, disk.Count()); } + [TestMethod] + public void PerformanceCounterProbeFirst() + { + PerformanceSample[] result; + var startTime = DateTimeOffset.UtcNow; + + using (var playback = new Playback()) + { + ((IPlaybackConfiguration)playback).AddInput( + () => PerfCounterObservable.FromRealTime(TimeSpan.FromSeconds(1), @"\Processor(_Total)\% User Time").Take(1), + typeof(PerfCounterPartitionTypeMap), + typeof(PerfCounterTypeMap)); + + var query = playback.GetObservable(); + + var enumerable = playback.BufferOutput(query); + + playback.Run(); + + result = enumerable.ToArray(); + } + var endTime = DateTimeOffset.UtcNow; + + Assert.AreEqual(1, result.Length); + + Assert.AreEqual("% User Time", result[0].CounterName, false, CultureInfo.InvariantCulture); + Assert.AreEqual("Processor", result[0].CounterSet, false, CultureInfo.InvariantCulture); + Assert.AreEqual("_Total", result[0].Instance, false, CultureInfo.InvariantCulture); + var dto = new DateTimeOffset(result[0].Timestamp); + Assert.IsTrue(dto >= startTime); + Assert.IsTrue(dto <= endTime); + } + IEnumerable PivotToInstanceSnapshots(Playback playback, string counterSet) { var all = playback.GetObservable();