Remove some ifdefs that can be done in a better way and merge additional bug fixes that happened in the nuget package branch.
Refactor some code to eliminate ifdefs for projectN.
Refactor code so that the ProjectN support uses partial classes instead of ifdefs.
Round 2 of making sure everything compiles in CoreCLR and in ProjectN.
Add formatting to the debugger message that EventSource prints when an internal error happens.
Change null strings to be represented as empty strings in TraceLogging.
Remove some ifdefs that can be done in a better way and merge additional bug fixes that happened in the nuget package branch.
Change WriteEventString to use an anonymous struct instead of EventMessage.
</Type>
<Type Status="ImplRoot" Name="System.Diagnostics.StackFrameHelper" />
- <Type Status="ImplRoot" Name="System.Diagnostics.Tracing.EnumHelper<UnderlyingType>">
- <Member Name="Identity(UnderlyingType)" />
- </Type>
-
<Type Name="System.Diagnostics.Tracing.EventAttribute">
<Member Name="#ctor(System.Int32)" />
<Member Name="get_EventId" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventDescriptor.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventProvider.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSource_CoreCLR.cs" />
<DiagnosticsSources Condition="'$(FeatureXplatEventSource)' == 'true'" Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\XplatEventLogger.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\EventSourceException.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\FrameworkEventSource.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\FieldMetadata.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\InvokeTypeInfo.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\NameInfo.cs" />
- <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyAccessor.cs" />
+ <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyValue.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\PropertyAnalysis.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleEventTypes.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\SimpleTypeInfos.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingEventTypes.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingMetadataCollector.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingTypeInfo.cs" />
- <DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TraceLoggingTypeInfo_T.cs" />
<DiagnosticsSources Include="$(BclSourcesRoot)\System\Diagnostics\Eventing\TraceLogging\TypeAnalysis.cs" />
</ItemGroup>
<ItemGroup>
#if ES_BUILD_STANDALONE
namespace Microsoft.Diagnostics.Tracing
-#else
+#else
using System.Threading.Tasks;
namespace System.Diagnostics.Tracing
#endif
/// Called on work item begins. The activity name = providerName + activityName without 'Start' suffix.
/// It updates CurrentActivityId to track.
///
- /// It returns true if the Start should be logged, otherwise (if it is illegal recurision) it return false.
+ /// It returns true if the Start should be logged, otherwise (if it is illegal recursion) it return false.
///
/// The start event should use as its activity ID the CurrentActivityId AFTER calling this routine and its
/// RelatedActivityID the CurrentActivityId BEFORE calling this routine (the creator).
if (m_checkedForEnable)
return;
m_checkedForEnable = true;
-#if ES_BUILD_STANDALONE
- Enable(); // Enable it unconditionally.
-#else
- if (System.Threading.Tasks.TplEtwProvider.Log.IsEnabled(EventLevel.Informational, System.Threading.Tasks.TplEtwProvider.Keywords.TasksFlowActivityIds))
- Enable();
-#endif
+ if (TplEtwProvider.Log.IsEnabled(EventLevel.Informational, TplEtwProvider.Keywords.TasksFlowActivityIds))
+ Enable();
+ if (m_current == null)
+ return;
}
// Remember the current ID so we can log it
activityId = newActivity.ActivityId;
-
+
if (etwLog.Debug)
{
etwLog.DebugFacilityMessage("OnStartRetActivityState", ActivityInfo.LiveActivities(newActivity));
return;
var fullActivityName = NormalizeActivityName(providerName, activityName, task);
-
+
var etwLog = TplEtwProvider.Log;
if (etwLog.Debug)
{
}
return;
}
- // We failed to stop it. We must have hit a race condition to stop it. Just start over and try again.
+ // We failed to stop it. We must have hit a race to stop it. Just start over and try again.
}
}
{
if (m_current == null)
{
- m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
+ // Catch the not Implemented
+ try
+ {
+ m_current = new AsyncLocal<ActivityInfo>(ActivityChanging);
+ }
+ catch (NotImplementedException) {
+#if (!ES_BUILD_PCL && ! PROJECTN)
+ // send message to debugger without delay
+ System.Diagnostics.Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable");
+#endif
+ }
}
}
{
// TODO FIXME - differentiate between AD inside PCL
int appDomainID = 0;
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
appDomainID = System.Threading.Thread.GetDomainID();
#endif
- // We start with the appdomain number to make this unique among appdomains.
+ // We start with the appdomain number to make this unique among appdomains.
activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID);
}
#endregion
}
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || PROJECTN
/******************************** SUPPORT *****************************/
/// <summary>
/// This is supplied by the framework. It is has the semantics that the value is copied to any new Tasks that is created
/// only get your thread local copy which means that you never have races.
/// </summary>
///
- [EventSource(Name="Microsoft.Tasks.Nuget")]
+#if ES_BUILD_STANDALONE
+ [EventSource(Name = "Microsoft.Tasks.Nuget")]
+#else
+ [EventSource(Name = "System.Diagnostics.Tracing.TplEtwProvider")]
+#endif
internal class TplEtwProvider : EventSource
{
public class Keywords
{
- public const EventKeywords Debug = (EventKeywords) 1;
+ public const EventKeywords TasksFlowActivityIds = (EventKeywords)0x80;
+ public const EventKeywords Debug = (EventKeywords)0x20000;
}
public static TplEtwProvider Log = new TplEtwProvider();
#endif
#if ES_BUILD_AGAINST_DOTNET_V35 || ES_BUILD_PCL || NO_ASYNC_LOCAL
-
+ // In these cases we don't have any Async local support. Do nothing.
internal sealed class AsyncLocalValueChangedArgs<T>
{
- public AsyncLocalValueChangedArgs()
- {
- }
-
public T PreviousValue { get { return default(T); } }
public T CurrentValue { get { return default(T); } }
internal sealed class AsyncLocal<T>
{
- public AsyncLocal()
- {
- }
-
- public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler)
- {
-
+ public AsyncLocal(Action<AsyncLocalValueChangedArgs<T>> valueChangedHandler) {
+ throw new NotImplementedException("AsyncLocal only available on V4.6 and above");
}
-
public T Value
{
- get
- {
- object obj = null; // TODO FIX
- return (obj == null) ? default(T) : (T)obj;
- }
- set
- {
- // TODO FIX
- }
+ get { return default(T); }
+ set { }
}
}
#endif
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+#if ES_BUILD_PCL
+ using System.Threading.Tasks;
+#endif
+
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
+ /// <summary>
+ /// Provides the ability to collect statistics through EventSource
+ /// </summary>
+ public class EventCounter
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EventCounter"/> class.
+ /// </summary>
+ /// <param name="name">The name.</param>
+ /// <param name="eventSource">The event source.</param>
+ public EventCounter(string name, EventSource eventSource)
+ {
+ if (name == null)
+ {
+ throw new ArgumentNullException("name");
+ }
+
+ if (eventSource == null)
+ {
+ throw new ArgumentNullException("eventSource");
+ }
+
+ InitializeBuffer();
+ _name = name;
+ EventCounterGroup.AddEventCounter(eventSource, this);
+ }
+
+ /// <summary>
+ /// Writes the metric.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ public void WriteMetric(float value)
+ {
+ Enqueue(value);
+ }
+
+ #region private implementation
+
+ private readonly string _name;
+
+ #region Buffer Management
+
+ // Values buffering
+ private const int BufferedSize = 10;
+ private const float UnusedBufferSlotValue = float.NegativeInfinity;
+ private const int UnsetIndex = -1;
+ private volatile float[] _bufferedValues;
+ private volatile int _bufferedValuesIndex;
+
+ private void InitializeBuffer()
+ {
+ _bufferedValues = new float[BufferedSize];
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ _bufferedValues[i] = UnusedBufferSlotValue;
+ }
+ }
+
+ private void Enqueue(float value)
+ {
+ // It is possible that two threads read the same bufferedValuesIndex, but only one will be able to write the slot, so that is okay.
+ int i = _bufferedValuesIndex;
+ while (true)
+ {
+ float result = Interlocked.CompareExchange(ref _bufferedValues[i], value, UnusedBufferSlotValue);
+ i++;
+ if (_bufferedValues.Length <= i)
+ {
+ // It is possible that two threads both think the buffer is full, but only one get to actually flush it, the other
+ // will eventually enter this code path and potentially calling Flushing on a buffer that is not full, and that's okay too.
+ lock (_bufferedValues)
+ {
+ Flush();
+ }
+ i = 0;
+ }
+
+ if (result == UnusedBufferSlotValue)
+ {
+ // CompareExchange succeeded
+ _bufferedValuesIndex = i;
+ return;
+ }
+ }
+ }
+
+ private void Flush()
+ {
+ for (int i = 0; i < _bufferedValues.Length; i++)
+ {
+ var value = Interlocked.Exchange(ref _bufferedValues[i], UnusedBufferSlotValue);
+ if (value != UnusedBufferSlotValue)
+ {
+ OnMetricWritten(value);
+ }
+ }
+
+ _bufferedValuesIndex = 0;
+ }
+
+ #endregion // Buffer Management
+
+ #region Statistics Calculation
+
+ // Statistics
+ private int _count;
+ private float _sum;
+ private float _sumSquared;
+ private float _min;
+ private float _max;
+
+ private void OnMetricWritten(float value)
+ {
+ _sum += value;
+ _sumSquared += value * value;
+ if (_count == 0 || value > _max)
+ {
+ _max = value;
+ }
+
+ if (_count == 0 || value < _min)
+ {
+ _min = value;
+ }
+
+ _count++;
+ }
+
+ internal EventCounterPayload GetEventCounterPayload()
+ {
+ lock (_bufferedValues)
+ {
+ Flush();
+ EventCounterPayload result = new EventCounterPayload();
+ result.Name = _name;
+ result.Count = _count;
+ result.Mean = _sum / _count;
+ result.StandardDerivation = (float)Math.Sqrt(_sumSquared / _count - _sum * _sum / _count / _count);
+ result.Min = _min;
+ result.Max = _max;
+ ResetStatistics();
+ return result;
+ }
+ }
+
+ private void ResetStatistics()
+ {
+ _count = 0;
+ _sum = 0;
+ _sumSquared = 0;
+ _min = 0;
+ _max = 0;
+ }
+
+ #endregion // Statistics Calculation
+
+ #endregion // private implementation
+ }
+
+ #region internal supporting classes
+
+ [EventData]
+ internal class EventCounterPayload : IEnumerable<KeyValuePair<string, object>>
+ {
+ public string Name { get; set; }
+
+ public float Mean { get; set; }
+
+ public float StandardDerivation { get; set; }
+
+ public int Count { get; set; }
+
+ public float Min { get; set; }
+
+ public float Max { get; set; }
+
+ public float IntervalSec { get; internal set; }
+
+ #region Implementation of the IEnumerable interface
+
+ public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return ForEnumeration.GetEnumerator();
+ }
+
+ private IEnumerable<KeyValuePair<string, object>> ForEnumeration
+ {
+ get
+ {
+ yield return new KeyValuePair<string, object>("Name", Name);
+ yield return new KeyValuePair<string, object>("Mean", Mean);
+ yield return new KeyValuePair<string, object>("StandardDerivation", StandardDerivation);
+ yield return new KeyValuePair<string, object>("Count", Count);
+ yield return new KeyValuePair<string, object>("Min", Min);
+ yield return new KeyValuePair<string, object>("Max", Max);
+ }
+ }
+
+ #endregion // Implementation of the IEnumerable interface
+ }
+
+ internal class EventCounterGroup : IDisposable
+ {
+ private readonly EventSource _eventSource;
+ private readonly int _eventSourceIndex;
+ private readonly List<EventCounter> _eventCounters;
+
+ internal EventCounterGroup(EventSource eventSource, int eventSourceIndex)
+ {
+ _eventSource = eventSource;
+ _eventSourceIndex = eventSourceIndex;
+ _eventCounters = new List<EventCounter>();
+ RegisterCommandCallback();
+ }
+
+ private void Add(EventCounter eventCounter)
+ {
+ _eventCounters.Add(eventCounter);
+ }
+
+ #region EventSource Command Processing
+
+ private void RegisterCommandCallback()
+ {
+ _eventSource.EventCommandExecuted += OnEventSourceCommand;
+ }
+
+ private void OnEventSourceCommand(object sender, EventCommandEventArgs e)
+ {
+ if (e.Command == EventCommand.Enable || e.Command == EventCommand.Update)
+ {
+ string valueStr;
+ float value;
+ if (e.Arguments.TryGetValue("EventCounterIntervalSec", out valueStr) && float.TryParse(valueStr, out value))
+ {
+ EnableTimer(value);
+ }
+ }
+ }
+
+ #endregion // EventSource Command Processing
+
+ #region Global EventCounterGroup Array management
+
+ private static EventCounterGroup[] s_eventCounterGroups;
+
+ internal static void AddEventCounter(EventSource eventSource, EventCounter eventCounter)
+ {
+ int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+
+ EventCounterGroup.EnsureEventSourceIndexAvailable(eventSourceIndex);
+ EventCounterGroup eventCounterGroup = GetEventCounterGroup(eventSource);
+ eventCounterGroup.Add(eventCounter);
+ }
+
+ private static void EnsureEventSourceIndexAvailable(int eventSourceIndex)
+ {
+ if (EventCounterGroup.s_eventCounterGroups == null)
+ {
+ EventCounterGroup.s_eventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+ }
+ else if (eventSourceIndex >= EventCounterGroup.s_eventCounterGroups.Length)
+ {
+ EventCounterGroup[] newEventCounterGroups = new EventCounterGroup[eventSourceIndex + 1];
+ Array.Copy(EventCounterGroup.s_eventCounterGroups, newEventCounterGroups, EventCounterGroup.s_eventCounterGroups.Length);
+ EventCounterGroup.s_eventCounterGroups = newEventCounterGroups;
+ }
+ }
+
+ private static EventCounterGroup GetEventCounterGroup(EventSource eventSource)
+ {
+ int eventSourceIndex = EventListener.EventSourceIndex(eventSource);
+ EventCounterGroup result = EventCounterGroup.s_eventCounterGroups[eventSourceIndex];
+ if (result == null)
+ {
+ result = new EventCounterGroup(eventSource, eventSourceIndex);
+ EventCounterGroup.s_eventCounterGroups[eventSourceIndex] = result;
+ }
+
+ return result;
+ }
+
+ #endregion // Global EventCounterGroup Array management
+
+ #region Timer Processing
+
+ private DateTime _timeStampSinceCollectionStarted;
+ private int _pollingIntervalInMilliseconds;
+ private Timer _pollingTimer;
+
+ private void EnableTimer(float pollingIntervalInSeconds)
+ {
+ if (pollingIntervalInSeconds == 0)
+ {
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+
+ _pollingIntervalInMilliseconds = 0;
+ }
+ else if (_pollingIntervalInMilliseconds == 0 || pollingIntervalInSeconds < _pollingIntervalInMilliseconds)
+ {
+ _pollingIntervalInMilliseconds = (int)(pollingIntervalInSeconds * 1000);
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+
+ _timeStampSinceCollectionStarted = DateTime.Now;
+ _pollingTimer = new Timer(OnTimer, null, _pollingIntervalInMilliseconds, _pollingIntervalInMilliseconds);
+ }
+ }
+
+ private void OnTimer(object state)
+ {
+ if (_eventSource.IsEnabled())
+ {
+ DateTime now = DateTime.Now;
+ TimeSpan elapsed = now - _timeStampSinceCollectionStarted;
+ lock (_pollingTimer)
+ {
+ foreach (var eventCounter in _eventCounters)
+ {
+ EventCounterPayload payload = eventCounter.GetEventCounterPayload();
+ payload.IntervalSec = (float)elapsed.TotalSeconds;
+ _eventSource.Write("EventCounters", new EventSourceOptions() { Level = EventLevel.LogAlways }, new { Payload = payload });
+ }
+
+
+ _timeStampSinceCollectionStarted = now;
+ }
+ }
+ else
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ EventCounterGroup.s_eventCounterGroups[_eventSourceIndex] = null;
+ }
+ }
+
+ #region PCL timer hack
+
+#if ES_BUILD_PCL
+ internal delegate void TimerCallback(object state);
+
+ internal sealed class Timer : CancellationTokenSource, IDisposable
+ {
+ private int _period;
+ private TimerCallback _callback;
+ private object _state;
+
+ internal Timer(TimerCallback callback, object state, int dueTime, int period)
+ {
+ _callback = callback;
+ _state = state;
+ _period = period;
+ Schedule(dueTime);
+ }
+
+ private void Schedule(int dueTime)
+ {
+ Task.Delay(dueTime, Token).ContinueWith(OnTimer, null, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
+ }
+
+ private void OnTimer(Task t, object s)
+ {
+ Schedule(_period);
+ _callback(_state);
+ }
+
+ public new void Dispose() { base.Cancel(); }
+ }
+#endif
+ #endregion // PCL timer hack
+
+ #endregion // Timer Processing
+
+ #region Implementation of the IDisposable interface
+
+ private bool _disposed = false;
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
+ {
+ if (_pollingTimer != null)
+ {
+ _pollingTimer.Dispose();
+ _pollingTimer = null;
+ }
+ }
+
+ _disposed = true;
+ }
+
+ #endregion // Implementation of the IDisposable interface
+ }
+
+ #endregion // internal supporting classes
+}
{
if (id < 0)
{
- throw new ArgumentOutOfRangeException("id", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ throw new ArgumentOutOfRangeException("id", Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if (id > ushort.MaxValue)
{
- throw new ArgumentOutOfRangeException("id", Environment.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+ throw new ArgumentOutOfRangeException("id", Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
}
m_traceloggingId = 0;
if (task < 0)
{
- throw new ArgumentOutOfRangeException("task", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
+ throw new ArgumentOutOfRangeException("task", Resources.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
}
if (task > ushort.MaxValue)
{
- throw new ArgumentOutOfRangeException("task", Environment.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
+ throw new ArgumentOutOfRangeException("task", Resources.GetResourceString("ArgumentOutOfRange_NeedValidId", 1, ushort.MaxValue));
}
m_task = (ushort)task;
}
- public int EventId {
- get {
+ public int EventId
+ {
+ get
+ {
return m_id;
}
}
public override int GetHashCode()
{
- return m_id ^ m_version ^ m_channel ^ m_level ^ m_opcode ^ m_task ^ (int)m_keywords;
+ return m_id ^ m_version ^ m_channel ^ m_level ^ m_opcode ^ m_task ^ (int)m_keywords;
}
public bool Equals(EventDescriptor other)
public static bool operator !=(EventDescriptor event1, EventDescriptor event2)
{
return !event1.Equals(event2);
- }
+ }
}
}
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Win32;
+
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
#endif
+#if ES_BUILD_STANDALONE
+using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
+#endif
+
+
#if ES_BUILD_AGAINST_DOTNET_V35
using Microsoft.Internal; // for Tuple (can't define alias for open generic types so we "use" the whole namespace)
#endif
/// controller callback)
/// </summary>
[System.Security.Permissions.HostProtection(MayLeakOnAbort = true)]
- internal class EventProvider : IDisposable
+ internal partial class EventProvider : IDisposable
{
// This is the windows EVENT_DATA_DESCRIPTOR structure. We expose it because this is what
// subclasses of EventProvider use when creating efficient (but unsafe) version of
private byte m_level; // Tracing Level
private long m_anyKeywordMask; // Trace Enable Flags
private long m_allKeywordMask; // Match all keyword
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
private List<SessionInfo> m_liveSessions; // current live sessions (Tuple<sessionIdBit, etwSessionId>)
+#endif
private bool m_enabled; // Enabled flag from Trace callback
private Guid m_providerId; // Control Guid
internal bool m_disposed; // when true provider has unregistered
EventTooBig = 2,
NullInput = 3,
TooManyArgs = 4,
- Other = 5,
+ Other = 5,
};
// Because callbacks happen on registration, and we need the callbacks for those setup
// we can't call Register in the constructor.
- //
+ //
// Note that EventProvider should ONLY be used by EventSource. In particular because
// it registers a callback from native code you MUST dispose it BEFORE shutdown, otherwise
// you may get native callbacks during shutdown when we have destroyed the delegate.
uint status;
m_etwCallback = new UnsafeNativeMethods.ManifestEtw.EtwEnableCallback(EtwEnableCallBack);
- status = EventRegister(ref m_providerId, m_etwCallback);
+ status = EventRegister(ref m_providerId, m_etwCallback);
if (status != 0)
{
throw new ArgumentException(Win32Native.GetMessage(unchecked((int)status)));
}
}
- [System.Security.SecurityCritical]
- internal unsafe int SetInformation(
- UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
- void* data,
- int dataSize)
- {
- int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
-
- if (!m_setInformationMissing)
- {
- try
- {
- status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
- m_regHandle,
- eventInfoClass,
- data,
- dataSize);
- }
- catch (TypeLoadException)
- {
- m_setInformationMissing = true;
- }
- }
-
- return status;
- }
-
//
// implement Dispose Pattern to early deregister from ETW insted of waiting for
// the finalizer to call deregistration.
m_regHandle = 0;
}
}
-
- // <SecurityKernel Critical="True" Ring="0">
- // <UsesUnsafeCode Name="Parameter filterData of type: Void*" />
- // <UsesUnsafeCode Name="Parameter callbackContext of type: Void*" />
- // </SecurityKernel>
+
[System.Security.SecurityCritical]
unsafe void EtwEnableCallBack(
- [In] ref System.Guid sourceId,
- [In] int controlCode,
- [In] byte setLevel,
- [In] long anyKeyword,
- [In] long allKeyword,
- [In] UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
- [In] void* callbackContext
+ ref System.Guid sourceId,
+ int controlCode,
+ byte setLevel,
+ long anyKeyword,
+ long allKeyword,
+ UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+ void* callbackContext
)
{
// This is an optional callback API. We will therefore ignore any failures that happen as a
ControllerCommand command = ControllerCommand.Update;
IDictionary<string, string> args = null;
bool skipFinalOnControllerCommand = false;
+
if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_ENABLE_PROVIDER)
{
m_enabled = true;
// today we use FEATURE_ACTIVITYSAMPLING to determine if this code is there or not.
// However we put it in the #if so that we don't lose the fact that this feature
// switch is at least partially independent of FEATURE_ACTIVITYSAMPLING
-
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
List<Tuple<SessionInfo, bool>> sessionsChanged = GetSessions();
foreach (var session in sessionsChanged)
{
// execute OnControllerCommand once for every session that has changed.
OnControllerCommand(command, args, (bEnabling ? sessionChanged : -sessionChanged), etwSessionId);
}
+#endif
}
else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_DISABLE_PROVIDER)
{
m_level = 0;
m_anyKeywordMask = 0;
m_allKeywordMask = 0;
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
m_liveSessions = null;
+#endif
}
else if (controlCode == UnsafeNativeMethods.ManifestEtw.EVENT_CONTROL_CODE_CAPTURE_STATE)
{
return idx;
}
+#if ES_SESSION_INFO || FEATURE_ACTIVITYSAMPLING
/// <summary>
/// Determines the ETW sessions that have been added and/or removed to the set of
/// sessions interested in the current provider. It does so by (1) enumerating over all
return -1;
}
+#endif
/// <summary>
/// Gets any data to be passed from the controller to the provider. It starts with what is passed
/// starts, and the command being issued associated with that data.
/// </summary>
[System.Security.SecurityCritical]
- private unsafe bool GetDataFromController(int etwSessionId,
- UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData, out ControllerCommand command, out byte[] data, out int dataStart)
+ private unsafe bool GetDataFromController(int etwSessionId,
+ UnsafeNativeMethods.ManifestEtw.EVENT_FILTER_DESCRIPTOR* filterData,
+ out ControllerCommand command, out byte[] data, out int dataStart)
{
data = null;
dataStart = 0;
if (filterData == null)
{
-#if !ES_BUILD_PCL && !FEATURE_PAL
+#if (!ES_BUILD_PCL && !PROJECTN && !FEATURE_PAL)
string regKey = @"\Microsoft\Windows\CurrentVersion\Winevt\Publishers\{" + m_providerId + "}";
if (System.Runtime.InteropServices.Marshal.SizeOf(typeof(IntPtr)) == 8)
regKey = @"HKEY_LOCAL_MACHINE\Software" + @"\Wow6432Node" + regKey;
--*/
{
- Again:
+ Again:
dataDescriptor->Reserved = 0;
string sRet = data as string;
dataRefObj.Add(null);
++refObjIndex;
}
-
+
//
// now fix any string arguments and set the pointer on the data descriptor
//
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Start ||
(EventOpcode)eventDescriptor.Opcode == EventOpcode.Stop);
}
-
+
int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(m_regHandle, ref eventDescriptor, activityID, childActivityID, dataCount, (EventData*)data);
if (status != 0)
int dataCount,
IntPtr data)
{
- int status;
-
- status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
+ int status = UnsafeNativeMethods.ManifestEtw.EventWriteTransferWrapper(
m_regHandle,
ref eventDescriptor,
activityID,
return true;
}
-
// These are look-alikes to the Manifest based ETW OS APIs that have been shimmed to work
// either with Manifest ETW or Classic ETW (if Manifest based ETW is not available).
[SecurityCritical]
m_etwCallback = enableCallback;
return UnsafeNativeMethods.ManifestEtw.EventRegister(ref providerId, enableCallback, null, ref m_regHandle);
}
-
+
[SecurityCritical]
private uint EventUnregister()
{
using System.Resources;
using System.Security;
using System.Security.Permissions;
+
using System.Text;
using System.Threading;
using Microsoft.Win32;
#if ES_BUILD_STANDALONE
-using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
#else
using System.Threading.Tasks;
-using EventDescriptor = System.Diagnostics.Tracing.EventDescriptor;
#endif
using Microsoft.Reflection;
}
if (name == null)
- throw new ArgumentException(Environment.GetResourceString("Argument_InvalidTypeName"), "eventSourceType");
-
+ {
+ throw new ArgumentException(Resources.GetResourceString("Argument_InvalidTypeName"), "eventSourceType");
+ }
return GenerateGuidFromName(name.ToUpperInvariant()); // Make it case insensitive.
}
/// <summary>
// User-defined EventCommands should not conflict with the reserved commands.
if ((int)command <= (int)EventCommand.Update && (int)command != (int)EventCommand.SendManifest)
- throw new ArgumentException(Environment.GetResourceString("EventSource_InvalidCommand"), "command");
-
- eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
- }
-
- // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
- /// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
- /// thread or network request) it should mark the thread as working on that other work.
- /// This API marks the current thread as working on activity 'activityID'. This API
- /// should be used when the caller knows the thread's current activity (the one being
- /// overwritten) has completed. Otherwise, callers should prefer the overload that
- /// return the oldActivityThatWillContinue (below).
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
- /// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
- /// started.
- /// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
- /// the current thread</param>
- [System.Security.SecuritySafeCritical]
- public static void SetCurrentThreadActivityId(Guid activityId)
- {
-#if FEATURE_MANAGED_ETW
-#if FEATURE_ACTIVITYSAMPLING
- Guid newId = activityId;
-#endif // FEATURE_ACTIVITYSAMPLING
- // We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
- if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
- ref activityId) == 0)
{
-#if FEATURE_ACTIVITYSAMPLING
- var activityDying = s_activityDying;
- if (activityDying != null && newId != activityId)
- {
- if (activityId == Guid.Empty)
- {
- activityId = FallbackActivityId;
- }
- // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
- activityDying(activityId); // This is actually the OLD activity ID.
- }
-#endif // FEATURE_ACTIVITYSAMPLING
+ throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidCommand"), "command");
}
-#endif // FEATURE_MANAGED_ETW
- if (TplEtwProvider.Log != null)
- TplEtwProvider.Log.SetActivityId(activityId);
- }
-
- /// <summary>
- /// When a thread starts work that is on behalf of 'something else' (typically another
- /// thread or network request) it should mark the thread as working on that other work.
- /// This API marks the current thread as working on activity 'activityID'. It returns
- /// whatever activity the thread was previously marked with. There is a convention that
- /// callers can assume that callees restore this activity mark before the callee returns.
- /// To encourage this this API returns the old activity, so that it can be restored later.
- ///
- /// All events created with the EventSource on this thread are also tagged with the
- /// activity ID of the thread.
- ///
- /// It is common, and good practice after setting the thread to an activity to log an event
- /// with a 'start' opcode to indicate that precise time/thread where the new activity
- /// started.
- /// </summary>
- /// <param name="activityId">A Guid that represents the new activity with which to mark
- /// the current thread</param>
- /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
- /// which will continue at some point in the future, on the current thread</param>
- [System.Security.SecuritySafeCritical]
- public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
- {
- oldActivityThatWillContinue = activityId;
-#if FEATURE_MANAGED_ETW
- // We ignore errors to keep with the convention that EventSources do not throw errors.
- // Note we can't access m_throwOnWrites because this is a static method.
- UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
- ref oldActivityThatWillContinue);
-#endif // FEATURE_MANAGED_ETW
-
- // We don't call the activityDying callback here because the caller has declared that
- // it is not dying.
- if (TplEtwProvider.Log != null)
- TplEtwProvider.Log.SetActivityId(activityId);
- }
- /// <summary>
- /// Retrieves the ETW activity ID associated with the current thread.
- /// </summary>
- public static Guid CurrentThreadActivityId
- {
- [System.Security.SecuritySafeCritical]
- get
- {
- // We ignore errors to keep with the convention that EventSources do not throw
- // errors. Note we can't access m_throwOnWrites because this is a static method.
- Guid retVal = new Guid();
-#if FEATURE_MANAGED_ETW
- UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
- UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
- ref retVal);
-#endif // FEATURE_MANAGED_ETW
- return retVal;
- }
+ eventSource.SendCommand(null, 0, 0, command, true, EventLevel.LogAlways, EventKeywords.None, commandArguments);
}
#if !ES_BUILD_STANDALONE
get
{
#pragma warning disable 612, 618
+ int threadID = AppDomain.GetCurrentThreadId();
+
// Managed thread IDs are more aggressively re-used than native thread IDs,
// so we'll use the latter...
- return new Guid(unchecked((uint)AppDomain.GetCurrentThreadId()),
+ return new Guid(unchecked((uint)threadID),
unchecked((ushort)s_currentPid), unchecked((ushort)(s_currentPid >> 16)),
0x94, 0x1b, 0x87, 0xd5, 0xa6, 0x5c, 0x36, 0x64);
#pragma warning restore 612, 618
/// <summary>
/// Displays the name and GUID for the eventSource for debugging purposes.
/// </summary>
- public override string ToString() { return Environment.GetResourceString("EventSource_ToString", Name, Guid); }
+ public override string ToString()
+ {
+ return Resources.GetResourceString("EventSource_ToString", Name, Guid);
+ }
/// <summary>
/// Fires when a Command (e.g. Enable) comes from a an EventListener.
{
add
{
- lock (this)
- {
- m_eventCommandExecuted += value;
- }
-
+ m_eventCommandExecuted += value;
+
// If we have an EventHandler<EventCommandEventArgs> attached to the EventSource before the first command arrives
// It should get a chance to handle the deferred commands.
EventCommandEventArgs deferredCommands = m_deferredCommands;
}
remove
{
- lock (this)
- {
- m_eventCommandExecuted -= value;
- }
+ m_eventCommandExecuted -= value;
}
}
protected EventSource(EventSourceSettings settings, params string[] traits)
{
m_config = ValidateSettings(settings);
- var myType = this.GetType();
- Initialize(GetGuid(myType), GetName(myType), traits);
+
+ Guid eventSourceGuid;
+ string eventSourceName;
+
+ EventMetadata[] eventDescriptors;
+ byte[] manifest;
+ GetMetadata(out eventSourceGuid, out eventSourceName, out eventDescriptors, out manifest);
+
+ if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null)
+ {
+ var myType = this.GetType();
+ eventSourceGuid = GetGuid(myType);
+ eventSourceName = GetName(myType);
+ }
+
+ Initialize(eventSourceGuid, eventSourceName, traits);
}
+ internal virtual void GetMetadata(out Guid eventSourceGuid, out string eventSourceName, out EventMetadata[] eventData, out byte[] manifestBytes)
+ {
+ //
+ // In ProjectN subclasses need to override this method, and return the data from their EventSourceAttribute and EventAttribute annotations.
+ // On other architectures it is a no-op.
+ //
+ // eventDescriptors needs to contain one EventDescriptor for each event; the event's ID should be the same as its index in this array.
+ // manifestBytes is a UTF-8 encoding of the ETW manifest for the type.
+ //
+ // This will be implemented by an IL rewriter, so we can't make this method abstract or the initial build of the subclass would fail.
+ //
+ eventSourceGuid = Guid.Empty;
+ eventSourceName = null;
+ eventData = null;
+ manifestBytes = null;
+
+ return;
+ }
+
/// <summary>
/// This method is called when the eventSource is updated by the controller.
/// </summary>
{
Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
if (relatedActivityId != null)
- ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
+ ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
#if FEATURE_MANAGED_ETW
if (m_eventData[eventId].EnabledForETW)
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
else
{
unchecked((long)etwSessions.ToEventKeywords() | origKwd));
if (!m_provider.WriteEvent(ref desc, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
}
else
if (!SelfDescribingEvents)
{
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, relatedActivityId, eventDataCount, (IntPtr)data))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
else
{
if (ex is EventSourceException)
throw;
else
- ThrowEventSourceException(ex);
+ ThrowEventSourceException(m_eventData[eventId].Name, ex);
}
}
}
}
}
#endif
+
[SecurityCritical]
private unsafe void WriteEventRaw(
+ string eventName,
ref EventDescriptor eventDescriptor,
Guid* activityID,
Guid* relatedActivityID,
#if FEATURE_MANAGED_ETW
if (m_provider == null)
{
- ThrowEventSourceException();
+ ThrowEventSourceException(eventName);
}
else
{
if (!m_provider.WriteEventRaw(ref eventDescriptor, activityID, relatedActivityID, dataCount, data))
- ThrowEventSourceException();
+ ThrowEventSourceException(eventName);
}
#endif // FEATURE_MANAGED_ETW
}
{
m_traits = traits;
if (m_traits != null && m_traits.Length % 2 != 0)
- throw new ArgumentException(Environment.GetResourceString("TraitEven"), "traits");
+ {
+ throw new ArgumentException(Resources.GetResourceString("TraitEven"), "traits");
+ }
if (eventSourceGuid == Guid.Empty)
- throw new ArgumentException(Environment.GetResourceString("EventSource_NeedGuid"));
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NeedGuid"));
+ }
if (eventSourceName == null)
- throw new ArgumentException(Environment.GetResourceString("EventSource_NeedName"));
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NeedName"));
+ }
m_name = eventSourceName;
m_guid = eventSourceGuid;
// Set m_provider, which allows this.
m_provider = provider;
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
// API available on OS >= Win 8 and patched Win 7.
// Disable only for FrameworkEventSource to avoid recursion inside exception handling.
var osVer = Environment.OSVersion.Version.Major * 10 + Environment.OSVersion.Version.Minor;
#endif
{
int setInformationResult;
- fixed (void* providerMetadata = this.providerMetadata)
- {
- setInformationResult = m_provider.SetInformation(
- UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
- providerMetadata,
- this.providerMetadata.Length);
- }
+ System.Runtime.InteropServices.GCHandle metadataHandle =
+ System.Runtime.InteropServices.GCHandle.Alloc(this.providerMetadata, System.Runtime.InteropServices.GCHandleType.Pinned);
+ IntPtr providerMetadata = metadataHandle.AddrOfPinnedObject();
+
+ setInformationResult = m_provider.SetInformation(
+ UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS.SetTraits,
+ providerMetadata,
+ (uint)this.providerMetadata.Length);
+
+ metadataHandle.Free();
}
#endif // FEATURE_MANAGED_ETW
// advance to next EventData in array
++data;
- Type dataType = m_eventData[eventId].Parameters[parameterId].ParameterType;
+ Type dataType = GetDataType(m_eventData[eventId], parameterId);
Again:
if (dataType == typeof(IntPtr))
}
else
{
- if (dataType.IsEnum())
+ if (m_EventSourcePreventRecursion && m_EventSourceInDecodeObject)
{
- dataType = Enum.GetUnderlyingType(dataType);
- goto Again;
+ return null;
}
- // TODO FIX NOW Assuming that it is a string at this point is really likely to be fragile
- // We should do something better.
+ try
+ {
+ m_EventSourceInDecodeObject = true;
- // Everything else is marshaled as a string.
- // ETW strings are NULL-terminated, so marshal everything up to the first
- // null in the string.
- return System.Runtime.InteropServices.Marshal.PtrToStringUni(dataPointer);
+ if (dataType.IsEnum())
+ {
+ dataType = Enum.GetUnderlyingType(dataType);
+ goto Again;
+ }
+
+
+ // Everything else is marshaled as a string.
+ // ETW strings are NULL-terminated, so marshal everything up to the first
+ // null in the string.
+ return System.Runtime.InteropServices.Marshal.PtrToStringUni(dataPointer);
+
+ }
+ finally
+ {
+ m_EventSourceInDecodeObject = false;
+ }
}
}
Contract.Assert(m_eventData != null); // You must have initialized this if you enabled the source.
if (childActivityID != null)
{
- ValidateEventOpcodeForTransfer(ref m_eventData[eventId]);
+ ValidateEventOpcodeForTransfer(ref m_eventData[eventId], m_eventData[eventId].Name);
// If you use WriteEventWithRelatedActivityID you MUST declare the first argument to be a GUID
// with the name 'relatedActivityID, and NOT pass this argument to the WriteEvent method.
// which would cause a cryptic IndexOutOfRangeException later if we don't catch it here.
if (!m_eventData[eventId].HasRelatedActivityID)
{
- throw new ArgumentException(Environment.GetResourceString("EventSource_NoRelatedActivityId"));
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NoRelatedActivityId"));
}
}
// mask set to 0x0f so, when all ETW sessions want the event we don't need to
// synthesize a new one
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
else
{
unchecked((long)(ulong)etwSessions | origKwd));
if (!m_provider.WriteEvent(ref desc, pActivityId, childActivityID, args))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
}
else
if (!SelfDescribingEvents)
{
if (!m_provider.WriteEvent(ref m_eventData[eventId].Descriptor, pActivityId, childActivityID, args))
- ThrowEventSourceException();
+ ThrowEventSourceException(m_eventData[eventId].Name);
}
else
{
#endif // FEATURE_MANAGED_ETW
if (m_Dispatchers != null && m_eventData[eventId].EnabledForAnyListener)
{
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
// Maintain old behavior - object identity is preserved
if (AppContextSwitches.PreserveEventListnerObjectIdentity)
{
if (ex is EventSourceException)
throw;
else
- ThrowEventSourceException(ex);
+ ThrowEventSourceException(m_eventData[eventId].Name, ex);
}
}
}
/// <param name="args"></param>
private void LogEventArgsMismatches(ParameterInfo[] infos, object[] args)
{
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
// It would be nice to have this on PCL builds, but it would be pointless since there isn't support for
// writing to the debugger log on PCL.
bool typesMatch = args.Length == infos.Length;
if (!typesMatch)
{
- System.Diagnostics.Debugger.Log(0, null, Environment.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
+ System.Diagnostics.Debugger.Log(0, null, Resources.GetResourceString("EventSource_VarArgsParameterMismatch") + "\r\n");
}
#endif //!ES_BUILD_PCL
}
[SecurityCritical]
unsafe private void WriteToAllListeners(int eventId, Guid* childActivityID, int eventDataCount, EventSource.EventData* data)
{
- int paramCount = m_eventData[eventId].Parameters.Length;
+ int paramCount = GetParameterCount(m_eventData[eventId]);
+
if (eventDataCount != paramCount)
{
- ReportOutOfBandMessage(Environment.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
+ ReportOutOfBandMessage(Resources.GetResourceString("EventSource_EventParametersMismatch", eventId, eventDataCount, paramCount), true);
paramCount = Math.Min(paramCount, eventDataCount);
}
throw new EventSourceException(lastThrownException);
}
}
-
+
[SecuritySafeCritical]
[SuppressMessage("Microsoft.Concurrency", "CA8001", Justification = "This does not need to be correct when racing with other threads")]
private unsafe void WriteEventString(EventLevel level, long keywords, string msgString)
}
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
- private void ThrowEventSourceException(Exception innerEx = null)
+ private void ThrowEventSourceException(string eventName, Exception innerEx = null)
{
// If we fail during out of band logging we may end up trying
// to throw another EventSourceException, thus hitting a StackOverflowException.
try
{
m_EventSourceExceptionRecurenceCount++;
+
+ string errorPrefix = "EventSourceException";
+ if(eventName != null)
+ {
+ errorPrefix += " while processing event \"" + eventName + "\"";
+ }
// TODO Create variations of EventSourceException that indicate more information using the error code.
switch (EventProvider.GetLastWriteEventError())
{
case EventProvider.WriteEventErrorCode.EventTooBig:
- ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_EventTooBig"), true);
- if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_EventTooBig"), innerEx);
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_EventTooBig"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_EventTooBig"), innerEx);
break;
case EventProvider.WriteEventErrorCode.NoFreeBuffers:
- ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NoFreeBuffers"), true);
- if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NoFreeBuffers"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NoFreeBuffers"), innerEx);
break;
case EventProvider.WriteEventErrorCode.NullInput:
- ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_NullInput"), true);
- if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_NullInput"), innerEx);
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_NullInput"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_NullInput"), innerEx);
break;
case EventProvider.WriteEventErrorCode.TooManyArgs:
- ReportOutOfBandMessage("EventSourceException: " + Environment.GetResourceString("EventSource_TooManyArgs"), true);
- if (ThrowOnEventWriteErrors) throw new EventSourceException(Environment.GetResourceString("EventSource_TooManyArgs"), innerEx);
+ ReportOutOfBandMessage(errorPrefix + ": " + Resources.GetResourceString("EventSource_TooManyArgs"), true);
+ if (ThrowOnEventWriteErrors) throw new EventSourceException(Resources.GetResourceString("EventSource_TooManyArgs"), innerEx);
break;
default:
if (innerEx != null)
- ReportOutOfBandMessage("EventSourceException: " + innerEx.GetType() + ":" + innerEx.Message, true);
+ ReportOutOfBandMessage(errorPrefix + ": " + innerEx.GetType() + ":" + innerEx.Message, true);
else
- ReportOutOfBandMessage("EventSourceException", true);
+ ReportOutOfBandMessage(errorPrefix, true);
if (ThrowOnEventWriteErrors) throw new EventSourceException(innerEx);
break;
}
}
}
- private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData)
+ private void ValidateEventOpcodeForTransfer(ref EventMetadata eventData, string eventName)
{
if ((EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Send &&
(EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Receive &&
(EventOpcode)eventData.Descriptor.Opcode != EventOpcode.Start)
{
- ThrowEventSourceException();
+ ThrowEventSourceException(eventName);
}
}
{
if (opcode == EventOpcode.Info && eventName != null)
{
- if (eventName.EndsWith(s_ActivityStartSuffix))
+ if (eventName.EndsWith(s_ActivityStartSuffix, StringComparison.Ordinal))
{
return EventOpcode.Start;
}
- else if (eventName.EndsWith(s_ActivityStopSuffix))
+ else if (eventName.EndsWith(s_ActivityStopSuffix, StringComparison.Ordinal))
{
return EventOpcode.Stop;
}
/// descriptor as well as some stuff we added specifically for EventSource. see the
/// code:m_eventData for where we use this.
/// </summary>
- internal struct EventMetadata
+ internal partial struct EventMetadata
{
public EventDescriptor Descriptor;
public EventTags Tags;
public TraceLoggingEventTypes TraceLoggingEventTypes;
public EventActivityOptions ActivityOptions;
+
+#if PROJECTN
+ public EventParameterType[] ParameterTypes;
+#endif
};
// This is the internal entry point that code:EventListeners call when wanting to send a command to a
// Find the per-EventSource dispatcher corresponding to registered dispatcher
commandArgs.dispatcher = GetDispatcher(commandArgs.listener);
if (commandArgs.dispatcher == null && commandArgs.listener != null) // dispatcher == null means ETW dispatcher
- throw new ArgumentException(Environment.GetResourceString("EventSource_ListenerNotFound"));
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_ListenerNotFound"));
+ }
if (commandArgs.Arguments == null)
commandArgs.Arguments = new Dictionary<string, string>();
if (commandArgs.listener == null && commandArgs.Arguments.Count > 0 && commandArgs.perEventSourceSessionId != sessionIdBit)
{
- throw new ArgumentException(Environment.GetResourceString("EventSource_SessionIdError",
+ throw new ArgumentException(Resources.GetResourceString("EventSource_SessionIdError",
commandArgs.perEventSourceSessionId + SessionMask.SHIFT_SESSION_TO_KEYWORD,
sessionIdBit + SessionMask.SHIFT_SESSION_TO_KEYWORD));
}
#endif
if (m_eventData == null)
{
- Contract.Assert(m_rawManifest == null);
- m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
- Contract.Assert(m_eventData != null);
+ Guid eventSourceGuid = Guid.Empty;
+ string eventSourceName = null;
+ EventMetadata[] eventData = null;
+ byte[] manifest = null;
+
+ // Try the GetMetadata provided by the ILTransform in ProjectN. The default sets all to null, and in that case we fall back
+ // to the reflection approach.
+ GetMetadata(out eventSourceGuid, out eventSourceName, out eventData, out manifest);
+ if (eventSourceGuid.Equals(Guid.Empty) || eventSourceName == null || eventData == null || manifest == null)
+ {
+ // GetMetadata failed, so we have to set it via reflection.
+ Contract.Assert(m_rawManifest == null);
+ m_rawManifest = CreateManifestAndDescriptors(this.GetType(), Name, this);
+ Contract.Assert(m_eventData != null);
+
+ }
+ else
+ {
+ // GetMetadata worked, so set the fields as appropriate.
+ m_name = eventSourceName;
+ m_guid = eventSourceGuid;
+ m_eventData = eventData;
+ m_rawManifest = manifest;
+ }
// TODO Enforce singleton pattern
foreach (WeakReference eventSourceRef in EventListener.s_EventSources)
{
if (eventSource != null && eventSource.Guid == m_guid && !eventSource.IsDisposed)
{
if (eventSource != this)
- throw new ArgumentException(Environment.GetResourceString("EventSource_EventSourceGuidInUse", m_guid));
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_EventSourceGuidInUse", m_guid));
+ }
}
}
envelope.ChunkNumber = 0;
EventProvider.EventData* dataDescrs = stackalloc EventProvider.EventData[2];
+
dataDescrs[0].Ptr = (ulong)&envelope;
dataDescrs[0].Size = (uint)sizeof(ManifestEnvelope);
dataDescrs[0].Reserved = 0;
}
success = false;
if (ThrowOnEventWriteErrors)
- ThrowEventSourceException();
+ ThrowEventSourceException("SendManifest");
break;
}
}
return success;
}
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
internal static Attribute GetCustomAttributeHelper(Type type, Type attributeType, EventManifestOptions flags = EventManifestOptions.None)
{
return GetCustomAttributeHelper(type.GetTypeInfo(), attributeType, flags);
return firstAttribute;
}
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
// In the reflection only context, we have to do things by hand.
string fullTypeNameToFind = attributeType.FullName;
}
return null;
-#else // ES_BUILD_PCL
- throw new ArgumentException(Environment.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection"));
+#else // ES_BUILD_PCL && PROJECTN
+ throw new ArgumentException(Resources.GetResourceString("EventSource", "EventSource_PCLPlatformNotSupportedReflection"));
#endif
}
bool typeMatch = GetEventSourceBaseType(eventSourceType, (flags & EventManifestOptions.AllowEventSourceOverride) != 0, eventSourceType.Assembly().ReflectionOnly()) != null;
if (!typeMatch)
- manifest.ManifestError(Environment.GetResourceString("EventSource_TypeMustDeriveFromEventSource"));
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustDeriveFromEventSource"));
+ }
if (!eventSourceType.IsAbstract() && !eventSourceType.IsSealed())
- manifest.ManifestError(Environment.GetResourceString("EventSource_TypeMustBeSealedOrAbstract"));
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_TypeMustBeSealedOrAbstract"));
+ }
}
// Collect task, opcode, keyword and channel information
{
if (eventSourceType.IsAbstract())
{
- manifest.ManifestError(Environment.GetResourceString("EventSource_AbstractMustNotDeclareKTOC", nestedType.Name));
+ manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareKTOC", nestedType.Name));
}
else
{
if (eventSourceType.IsAbstract())
{
if (eventAttribute != null)
- manifest.ManifestError(Environment.GetResourceString("EventSource_AbstractMustNotDeclareEventMethods", method.Name, eventAttribute.EventId));
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_AbstractMustNotDeclareEventMethods", method.Name, eventAttribute.EventId));
+ }
continue;
}
else if (eventAttribute == null)
}
else if (eventAttribute.EventId <= 0)
{
- manifest.ManifestError(Environment.GetResourceString("EventSource_NeedPositiveId", method.Name), true);
+ manifest.ManifestError(Resources.GetResourceString("EventSource_NeedPositiveId", method.Name), true);
continue; // don't validate anything else for this event
}
if (method.Name.LastIndexOf('.') >= 0)
- manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustNotBeExplicitImplementation", method.Name, eventAttribute.EventId));
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventMustNotBeExplicitImplementation", method.Name, eventAttribute.EventId));
+ }
eventId++;
string eventName = method.Name;
}
}
if (noTask && (flags & EventManifestOptions.Strict) != 0) // Throw an error if we can compatibly.
- throw new ArgumentException(Environment.GetResourceString("EventSource_StopsFollowStarts"));
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_StopsFollowStarts"));
+ }
}
}
}
#endif
return;
Error:
- manifest.ManifestError(Environment.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind));
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EnumKindMismatch", staticField.Name, staticField.FieldType.Name, providerEnumKind));
}
// Helper used by code:CreateManifestAndDescriptors to add a code:EventData descriptor for a method
#if FEATURE_MANAGED_ETW_CHANNELS
(byte)eventAttribute.Channel,
#else
- (byte)0,
+ (byte)0,
#endif
- (byte)eventAttribute.Level,
+ (byte)eventAttribute.Level,
(byte)eventAttribute.Opcode,
(int)eventAttribute.Task,
unchecked((long)((ulong)eventAttribute.Keywords | SessionMask.All.ToEventKeywords())));
eventData = newValues;
}
}
-
+
// Helper used by code:EventListener.AddEventSource and code:EventListener.EventListener
// when a listener gets attached to a eventSource
internal void AddListener(EventListener listener)
int eventArg = GetHelperCallFirstArg(method);
if (eventArg >= 0 && evtId != eventArg)
{
- manifest.ManifestError(Environment.GetResourceString("EventSource_MismatchIdToWriteEvent", evtName, evtId, eventArg), true);
+ manifest.ManifestError(Resources.GetResourceString("EventSource_MismatchIdToWriteEvent", evtName, evtId, eventArg), true);
}
if (evtId < eventData.Length && eventData[evtId].Descriptor.EventId != 0)
{
- manifest.ManifestError(Environment.GetResourceString("EventSource_EventIdReused", evtName, evtId, eventData[evtId].Name), true);
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventIdReused", evtName, evtId, eventData[evtId].Name), true);
}
// We give a task to things if they don't have one.
if (eventData[idx].Descriptor.Task == (int)eventAttribute.Task && eventData[idx].Descriptor.Opcode == (int)eventAttribute.Opcode)
{
- manifest.ManifestError(Environment.GetResourceString("EventSource_TaskOpcodePairReused",
+ manifest.ManifestError(Resources.GetResourceString("EventSource_TaskOpcodePairReused",
evtName, evtId, eventData[idx].Name, idx));
-
// If we are not strict stop on first error. We have had problems with really large providers taking forever. because of many errors.
if ((options & EventManifestOptions.Strict) == 0)
break;
failure = true;
}
if (failure)
- manifest.ManifestError(Environment.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventMustHaveTaskIfNonDefaultOpcode", evtName, evtId));
+ }
}
// If we ever want to enforce the rule: MethodName = TaskName + OpcodeName here's how:
// taskName & opcodeName could be passed in by the caller which has opTab & taskTab handy
// if (!(((int)eventAttribute.Opcode == 0 && evtName == taskName) || (evtName == taskName+opcodeName)))
// {
- // throw new WarningException(Environment.GetResourceString("EventSource_EventNameDoesNotEqualTaskPlusOpcode"));
+ // throw new WarningException(Resources.GetResourceString("EventSource_EventNameDoesNotEqualTaskPlusOpcode"));
// }
if (eventsByName == null)
eventsByName = new Dictionary<string, string>();
if (eventsByName.ContainsKey(evtName))
- manifest.ManifestError(Environment.GetResourceString("EventSource_EventNameReused", evtName), true);
+ {
+ manifest.ManifestError(Resources.GetResourceString("EventSource_EventNameReused", evtName), true);
+ }
eventsByName[evtName] = evtName;
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Switch statement is clearer than alternatives")]
static private int GetHelperCallFirstArg(MethodInfo method)
{
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
// Currently searches for the following pattern
//
// ... // CAN ONLY BE THE INSTRUCTIONS BELOW
{
try
{
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
// send message to debugger without delay
- System.Diagnostics.Debugger.Log(0, null, msg + "\r\n");
+ System.Diagnostics.Debugger.Log(0, null, String.Format("EventSource Error: {0}{1}", msg , Environment.NewLine));
#endif
// Send it to all listeners.
var evtFormatMask = EventSourceSettings.EtwManifestEventFormat |
EventSourceSettings.EtwSelfDescribingEventFormat;
if ((settings & evtFormatMask) == evtFormatMask)
- throw new ArgumentException(Environment.GetResourceString("EventSource_InvalidEventFormat"), "settings");
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_InvalidEventFormat"), "settings");
+ }
// If you did not explicitly ask for manifest, you get self-describing.
if ((settings & evtFormatMask) == 0)
[ThreadStatic]
private static byte m_EventSourceExceptionRecurenceCount = 0; // current recursion count inside ThrowEventSourceException
+ [ThreadStatic]
+ private static bool m_EventSourceInDecodeObject = false;
+
#if FEATURE_MANAGED_ETW_CHANNELS
internal volatile ulong[] m_channelData;
#endif
/// created.
/// </para>
/// </summary>
- public abstract class EventListener : IDisposable
+ public class EventListener : IDisposable
{
private event EventHandler<EventSourceCreatedEventArgs> _EventSourceCreated;
/// Create a new EventListener in which all events start off turned off (use EnableEvents to turn
/// them on).
/// </summary>
- protected EventListener()
+ public EventListener()
{
// This will cause the OnEventSourceCreated callback to fire.
CallBackForExistingEventSources(true, (obj, args) => args.EventSource.AddListener(this) );
if (!s_EventSourceShutdownRegistered)
{
s_EventSourceShutdownRegistered = true;
-#if !ES_BUILD_PCL && !FEATURE_CORECLR
+#if (!ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN)
AppDomain.CurrentDomain.ProcessExit += DisposeOnShutdown;
AppDomain.CurrentDomain.DomainUnload += DisposeOnShutdown;
#endif
{
// Disallow creating EventListener reentrancy.
if (s_CreatingListener)
- throw new InvalidOperationException(Environment.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
+ {
+ throw new InvalidOperationException(Resources.GetResourceString("EventSource_ListenerCreatedInsideCallback"));
+ }
try
{
private uint m_mask;
internal const int SHIFT_SESSION_TO_KEYWORD = 44; // bits 44-47 inclusive are reserved
- internal const uint MASK = 0x0fU; // the mask of 4 reserved bits
- internal const uint MAX = 4; // maximum number of simultaneous ETW sessions supported
+ internal const uint MASK = 0x0fU; // the mask of 4 reserved bits
+ internal const uint MAX = 4; // maximum number of simultaneous ETW sessions supported
}
/// <summary>
/// ManifestBuilder is designed to isolate the details of the message of the event from the
/// rest of EventSource. This one happens to create XML.
/// </summary>
- internal class ManifestBuilder
+ internal partial class ManifestBuilder
{
/// <summary>
/// Build a manifest for 'providerName' with the given GUID, which will be packaged into 'dllName'.
if ((flags & EventManifestOptions.Strict) != 0)
{
if (value <= 10 || value >= 239)
- ManifestError(Environment.GetResourceString("EventSource_IllegalOpcodeValue", name, value));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalOpcodeValue", name, value));
+ }
string prevName;
if (opcodeTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
- ManifestError(Environment.GetResourceString("EventSource_OpcodeCollision", name, prevName, value));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_OpcodeCollision", name, prevName, value));
+ }
}
opcodeTab[value] = name;
}
if ((flags & EventManifestOptions.Strict) != 0)
{
if (value <= 0 || value >= 65535)
- ManifestError(Environment.GetResourceString("EventSource_IllegalTaskValue", name, value));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalTaskValue", name, value));
+ }
string prevName;
if (taskTab != null && taskTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
- ManifestError(Environment.GetResourceString("EventSource_TaskCollision", name, prevName, value));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_TaskCollision", name, prevName, value));
+ }
}
if (taskTab == null)
taskTab = new Dictionary<int, string>();
public void AddKeyword(string name, ulong value)
{
if ((value & (value - 1)) != 0) // Is it a power of 2?
- ManifestError(Environment.GetResourceString("EventSource_KeywordNeedPowerOfTwo", "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
+ {
+ ManifestError(Resources.GetResourceString("EventSource_KeywordNeedPowerOfTwo", "0x" + value.ToString("x", CultureInfo.CurrentCulture), name), true);
+ }
if ((flags & EventManifestOptions.Strict) != 0)
{
if (value >= 0x0000100000000000UL && !name.StartsWith("Session", StringComparison.Ordinal))
- ManifestError(Environment.GetResourceString("EventSource_IllegalKeywordsValue", name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_IllegalKeywordsValue", name, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ }
string prevName;
if (keywordTab != null && keywordTab.TryGetValue(value, out prevName) && !name.Equals(prevName, StringComparison.Ordinal))
- ManifestError(Environment.GetResourceString("EventSource_KeywordCollision", name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ {
+ ManifestError(Resources.GetResourceString("EventSource_KeywordCollision", name, prevName, "0x" + value.ToString("x", CultureInfo.CurrentCulture)));
+ }
}
if (keywordTab == null)
keywordTab = new Dictionary<ulong, string>();
{
EventChannel chValue = (EventChannel)value;
if (value < (int)EventChannel.Admin || value > 255)
- ManifestError(Environment.GetResourceString("EventSource_EventChannelOutOfRange", name, value));
+ ManifestError(Resources.GetResourceString("EventSource_EventChannelOutOfRange", name, value));
else if (chValue >= EventChannel.Admin && chValue <= EventChannel.Debug &&
channelAttribute != null && EventChannelToChannelType(chValue) != channelAttribute.EventChannelType)
{
// we want to ensure developers do not define EventChannels that conflict with the builtin ones,
// but we want to allow them to override the default ones...
- ManifestError(Environment.GetResourceString("EventSource_ChannelTypeDoesNotMatchEventChannelValue",
+ ManifestError(Resources.GetResourceString("EventSource_ChannelTypeDoesNotMatchEventChannelValue",
name, ((EventChannel)value).ToString()));
}
}
if (channelTab.Count == MaxCountChannels)
- ManifestError(Environment.GetResourceString("EventSource_MaxChannelExceeded"));
+ ManifestError(Resources.GetResourceString("EventSource_MaxChannelExceeded"));
ulong channelKeyword;
ChannelInfo info;
cultures = new List<CultureInfo>();
cultures.Add(CultureInfo.CurrentUICulture);
}
-#if ES_BUILD_STANDALONE
+#if ES_BUILD_STANDALONE || PROJECTN
var sortedStrings = new List<string>(stringTab.Keys);
sortedStrings.Sort();
#else
string prevValue;
if (stringTab.TryGetValue(key, out prevValue) && !prevValue.Equals(value))
{
- ManifestError(Environment.GetResourceString("EventSource_DuplicateStringKey", key), true);
+ ManifestError(Resources.GetResourceString("EventSource_DuplicateStringKey", key), true);
return;
}
private static List<CultureInfo> GetSupportedCultures(ResourceManager resources)
{
var cultures = new List<CultureInfo>();
-#if !ES_BUILD_PCL && !FEATURE_CORECLR
+#if !ES_BUILD_PCL && !FEATURE_CORECLR && !PROJECTN
foreach (CultureInfo ci in CultureInfo.GetCultures(CultureTypes.SpecificCultures /*| CultureTypes.NeutralCultures*/))
{
if (resources.GetResourceSet(ci, true, false) != null)
if (channelTab == null || !channelTab.TryGetValue((int)channel, out info))
{
if (channel < EventChannel.Admin) // || channel > EventChannel.Debug)
- ManifestError(Environment.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
// allow channels to be auto-defined. The well known ones get their well known names, and the
// rest get names Channel<N>. This allows users to modify the Manifest if they want more advanced features.
if (channelTab == null)
channelTab = new Dictionary<int, ChannelInfo>(4);
-
+
string channelName = channel.ToString(); // For well know channels this is a nice name, otherwise a number
if (EventChannel.Debug < channel)
channelName = "Channel" + channelName; // Add a 'Channel' prefix for numbers.
AddChannel(channelName, (int)channel, GetDefaultChannelAttribute(channel));
if (!channelTab.TryGetValue((int)channel, out info))
- ManifestError(Environment.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedChannel", channel, eventName));
}
// events that specify admin channels *must* have non-null "Message" attributes
if (resources != null && eventMessage == null)
eventMessage = resources.GetString("event_" + eventName, CultureInfo.InvariantCulture);
if (info.Attribs.EventChannelType == EventChannelType.Admin && eventMessage == null)
- ManifestError(Environment.GetResourceString("EventSource_EventWithAdminChannelMustHaveMessage", eventName, info.Name));
+ ManifestError(Resources.GetResourceString("EventSource_EventWithAdminChannelMustHaveMessage", eventName, info.Name));
return info.Name;
}
#endif
ret = taskTab[(int)task] = eventName;
return ret;
}
+
private string GetOpcodeName(EventOpcode opcode, string eventName)
{
switch (opcode)
string ret;
if (opcodeTab == null || !opcodeTab.TryGetValue((int)opcode, out ret))
{
- ManifestError(Environment.GetResourceString("EventSource_UndefinedOpcode", opcode, eventName), true);
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedOpcode", opcode, eventName), true);
ret = null;
}
return ret;
}
+
private string GetKeywords(ulong keywords, string eventName)
{
string ret = "";
}
if (keyword == null)
{
- ManifestError(Environment.GetResourceString("EventSource_UndefinedKeyword", "0x" + bit.ToString("x", CultureInfo.CurrentCulture), eventName), true);
+ ManifestError(Resources.GetResourceString("EventSource_UndefinedKeyword", "0x" + bit.ToString("x", CultureInfo.CurrentCulture), eventName), true);
keyword = string.Empty;
}
if (ret.Length != 0 && keyword.Length != 0)
}
return ret;
}
+
private string GetTypeName(Type type)
{
if (type.IsEnum())
var typeName = GetTypeName(fields[0].FieldType);
return typeName.Replace("win:Int", "win:UInt"); // ETW requires enums to be unsigned.
}
- switch (type.GetTypeCode())
- {
- case TypeCode.Boolean:
- return "win:Boolean";
- case TypeCode.Byte:
- return "win:UInt8";
- case TypeCode.Char:
- case TypeCode.UInt16:
- return "win:UInt16";
- case TypeCode.UInt32:
- return "win:UInt32";
- case TypeCode.UInt64:
- return "win:UInt64";
- case TypeCode.SByte:
- return "win:Int8";
- case TypeCode.Int16:
- return "win:Int16";
- case TypeCode.Int32:
- return "win:Int32";
- case TypeCode.Int64:
- return "win:Int64";
- case TypeCode.String:
- return "win:UnicodeString";
- case TypeCode.Single:
- return "win:Float";
- case TypeCode.Double:
- return "win:Double";
- case TypeCode.DateTime:
- return "win:FILETIME";
- default:
- if (type == typeof(Guid))
- return "win:GUID";
- else if (type == typeof(IntPtr))
- return "win:Pointer";
- else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
- return "win:Binary";
- ManifestError(Environment.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
- return string.Empty;
- }
+
+ return GetTypeNameHelper(type);
}
private static void UpdateStringBuilder(ref StringBuilder stringBuilder, string eventMessage, int startIndex, int count)
}
else
{
- ManifestError(Environment.GetResourceString("EventSource_UnsupportedMessageProperty", evtName, eventMessage));
+ ManifestError(Resources.GetResourceString("EventSource_UnsupportedMessageProperty", evtName, eventMessage));
}
}
else if ((chIdx = "&<>'\"\r\n\t".IndexOf(eventMessage[i])) >= 0)
/// <summary>
/// Exception that is thrown when an error occurs during EventSource operation.
/// </summary>
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
[Serializable]
#endif
public class EventSourceException : Exception
/// <summary>
/// Initializes a new instance of the EventSourceException class.
/// </summary>
- public EventSourceException() : base(Environment.GetResourceString("EventSource_ListenerWriteFailure")) { }
+ public EventSourceException() :
+ base(Resources.GetResourceString("EventSource_ListenerWriteFailure")) { }
/// <summary>
/// Initializes a new instance of the EventSourceException class with a specified error message.
/// </summary>
public EventSourceException(string message, Exception innerException) : base(message, innerException) { }
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
/// <summary>
/// Initializes a new instance of the EventSourceException class with serialized data.
/// </summary>
protected EventSourceException(SerializationInfo info, StreamingContext context) : base(info, context) { }
#endif
- internal EventSourceException(Exception innerException) : base(Environment.GetResourceString("EventSource_ListenerWriteFailure"), innerException) { }
+ internal EventSourceException(Exception innerException) :
+ base(Resources.GetResourceString("EventSource_ListenerWriteFailure"), innerException) { }
}
}
--- /dev/null
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using Microsoft.Reflection;
+using Microsoft.Win32;
+
+namespace System.Diagnostics.Tracing
+{
+ public partial class EventSource
+ {
+ // ActivityID support (see also WriteEventWithRelatedActivityIdCore)
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. This API
+ /// should be used when the caller knows the thread's current activity (the one being
+ /// overwritten) has completed. Otherwise, callers should prefer the overload that
+ /// return the oldActivityThatWillContinue (below).
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ [System.Security.SecuritySafeCritical]
+ public static void SetCurrentThreadActivityId(Guid activityId)
+ {
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
+#if FEATURE_MANAGED_ETW
+#if FEATURE_ACTIVITYSAMPLING
+ Guid newId = activityId;
+#endif // FEATURE_ACTIVITYSAMPLING
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+
+ if (UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref activityId) == 0)
+ {
+#if FEATURE_ACTIVITYSAMPLING
+ var activityDying = s_activityDying;
+ if (activityDying != null && newId != activityId)
+ {
+ if (activityId == Guid.Empty)
+ {
+ activityId = FallbackActivityId;
+ }
+ // OutputDebugString(string.Format("Activity dying: {0} -> {1}", activityId, newId));
+ activityDying(activityId); // This is actually the OLD activity ID.
+ }
+#endif // FEATURE_ACTIVITYSAMPLING
+ }
+#endif // FEATURE_MANAGED_ETW
+ }
+
+ /// <summary>
+ /// When a thread starts work that is on behalf of 'something else' (typically another
+ /// thread or network request) it should mark the thread as working on that other work.
+ /// This API marks the current thread as working on activity 'activityID'. It returns
+ /// whatever activity the thread was previously marked with. There is a convention that
+ /// callers can assume that callees restore this activity mark before the callee returns.
+ /// To encourage this this API returns the old activity, so that it can be restored later.
+ ///
+ /// All events created with the EventSource on this thread are also tagged with the
+ /// activity ID of the thread.
+ ///
+ /// It is common, and good practice after setting the thread to an activity to log an event
+ /// with a 'start' opcode to indicate that precise time/thread where the new activity
+ /// started.
+ /// </summary>
+ /// <param name="activityId">A Guid that represents the new activity with which to mark
+ /// the current thread</param>
+ /// <param name="oldActivityThatWillContinue">The Guid that represents the current activity
+ /// which will continue at some point in the future, on the current thread</param>
+ [System.Security.SecuritySafeCritical]
+ public static void SetCurrentThreadActivityId(Guid activityId, out Guid oldActivityThatWillContinue)
+ {
+ oldActivityThatWillContinue = activityId;
+#if FEATURE_MANAGED_ETW
+ // We ignore errors to keep with the convention that EventSources do not throw errors.
+ // Note we can't access m_throwOnWrites because this is a static method.
+
+ UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_SET_ID,
+ ref oldActivityThatWillContinue);
+#endif // FEATURE_MANAGED_ETW
+
+ // We don't call the activityDying callback here because the caller has declared that
+ // it is not dying.
+ if (TplEtwProvider.Log != null)
+ TplEtwProvider.Log.SetActivityId(activityId);
+ }
+
+ /// <summary>
+ /// Retrieves the ETW activity ID associated with the current thread.
+ /// </summary>
+ public static Guid CurrentThreadActivityId
+ {
+ [System.Security.SecuritySafeCritical]
+ get
+ {
+ // We ignore errors to keep with the convention that EventSources do not throw
+ // errors. Note we can't access m_throwOnWrites because this is a static method.
+ Guid retVal = new Guid();
+#if FEATURE_MANAGED_ETW
+ UnsafeNativeMethods.ManifestEtw.EventActivityIdControl(
+ UnsafeNativeMethods.ManifestEtw.ActivityControl.EVENT_ACTIVITY_CTRL_GET_ID,
+ ref retVal);
+#endif // FEATURE_MANAGED_ETW
+ return retVal;
+ }
+ }
+
+ private int GetParameterCount(EventMetadata eventData)
+ {
+ return eventData.Parameters.Length;
+ }
+
+ private Type GetDataType(EventMetadata eventData, int parameterId)
+ {
+ return eventData.Parameters[parameterId].ParameterType;
+ }
+
+ private static string GetResourceString(string key, params object[] args)
+ {
+ return Environment.GetResourceString(key, args);
+ }
+
+ private static readonly bool m_EventSourcePreventRecursion = false;
+ }
+
+ internal partial class ManifestBuilder
+ {
+ private string GetTypeNameHelper(Type type)
+ {
+ switch (type.GetTypeCode())
+ {
+ case TypeCode.Boolean:
+ return "win:Boolean";
+ case TypeCode.Byte:
+ return "win:UInt8";
+ case TypeCode.Char:
+ case TypeCode.UInt16:
+ return "win:UInt16";
+ case TypeCode.UInt32:
+ return "win:UInt32";
+ case TypeCode.UInt64:
+ return "win:UInt64";
+ case TypeCode.SByte:
+ return "win:Int8";
+ case TypeCode.Int16:
+ return "win:Int16";
+ case TypeCode.Int32:
+ return "win:Int32";
+ case TypeCode.Int64:
+ return "win:Int64";
+ case TypeCode.String:
+ return "win:UnicodeString";
+ case TypeCode.Single:
+ return "win:Float";
+ case TypeCode.Double:
+ return "win:Double";
+ case TypeCode.DateTime:
+ return "win:FILETIME";
+ default:
+ if (type == typeof(Guid))
+ return "win:GUID";
+ else if (type == typeof(IntPtr))
+ return "win:Pointer";
+ else if ((type.IsArray || type.IsPointer) && type.GetElementType() == typeof(byte))
+ return "win:Binary";
+
+ ManifestError(Environment.GetResourceString("EventSource_UnsupportedEventTypeInManifest", type.Name), true);
+ return string.Empty;
+ }
+ }
+ }
+
+ internal partial class EventProvider
+ {
+ [System.Security.SecurityCritical]
+ internal unsafe int SetInformation(
+ UnsafeNativeMethods.ManifestEtw.EVENT_INFO_CLASS eventInfoClass,
+ IntPtr data,
+ uint dataSize)
+ {
+ int status = UnsafeNativeMethods.ManifestEtw.ERROR_NOT_SUPPORTED;
+
+ if (!m_setInformationMissing)
+ {
+ try
+ {
+ status = UnsafeNativeMethods.ManifestEtw.EventSetInformation(
+ m_regHandle,
+ eventInfoClass,
+ (void *)data,
+ (int)dataSize);
+ }
+ catch (TypeLoadException)
+ {
+ m_setInformationMissing = true;
+ }
+ }
+
+ return status;
+ }
+ }
+
+ internal static class Resources
+ {
+ internal static string GetResourceString(string key, params object[] args)
+ {
+ return Environment.GetResourceString(key, args);
+ }
+ }
+}
sargs += ", ";
sargs += arg.ToString();
}
-
+
return key + " (" + sargs + ")";
}
{
using System.Reflection;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
[Flags]
public enum BindingFlags
{
#endif
static class ReflectionExtensions
{
-#if !ES_BUILD_PCL
-
+#if (!ES_BUILD_PCL && !PROJECTN)
+
//
// Type extension methods
//
public static bool IsEnum(this Type type) { return type.IsEnum; }
public static bool IsAbstract(this Type type) { return type.IsAbstract; }
public static bool IsSealed(this Type type) { return type.IsSealed; }
+ public static bool IsValueType(this Type type) { return type.IsValueType; }
+ public static bool IsGenericType(this Type type) { return type.IsGenericType; }
public static Type BaseType(this Type type) { return type.BaseType; }
public static Assembly Assembly(this Type type) { return type.Assembly; }
public static TypeCode GetTypeCode(this Type type) { return Type.GetTypeCode(type); }
public static bool IsEnum(this Type type) { return type.GetTypeInfo().IsEnum; }
public static bool IsAbstract(this Type type) { return type.GetTypeInfo().IsAbstract; }
public static bool IsSealed(this Type type) { return type.GetTypeInfo().IsSealed; }
+ public static bool IsValueType(this Type type) { return type.GetTypeInfo().IsValueType; }
+ public static bool IsGenericType(this Type type) { return type.IsConstructedGenericType; }
public static Type BaseType(this Type type) { return type.GetTypeInfo().BaseType; }
public static Assembly Assembly(this Type type) { return type.GetTypeInfo().Assembly; }
-
+ public static IEnumerable<PropertyInfo> GetProperties(this Type type) { return type.GetTypeInfo().DeclaredProperties; }
+ public static MethodInfo GetGetMethod(this PropertyInfo propInfo) { return propInfo.GetMethod; }
+ public static Type[] GetGenericArguments(this Type type) { return type.GenericTypeArguments; }
+
public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
{
// Minimal implementation to cover only the cases we need
}
// Defining some no-ops in PCL builds
-#if ES_BUILD_PCL
+#if ES_BUILD_PCL || PROJECTN
namespace System.Security
{
class SuppressUnmanagedCodeSecurityAttribute : Attribute { }
public bool Unrestricted { get; set; }
}
}
-#endif
\ No newline at end of file
+#endif
+
+#if PROJECTN
+namespace System
+{
+ public static class AppDomain
+ {
+ public static int GetCurrentThreadId()
+ {
+ return (int)Interop.mincore.GetCurrentThreadId();
+ }
+ }
+}
+#endif
namespace System.Diagnostics.Tracing
#endif
{
- internal sealed class ArrayTypeInfo<ElementType>
- : TraceLoggingTypeInfo<ElementType[]>
+ internal sealed class ArrayTypeInfo : TraceLoggingTypeInfo
{
- private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
+ private readonly TraceLoggingTypeInfo elementInfo;
- public ArrayTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
+ public ArrayTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+ : base(type)
{
this.elementInfo = elementInfo;
}
collector.EndBufferedArray();
}
- public override void WriteData(
- TraceLoggingDataCollector collector,
- ref ElementType[] value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
var bookmark = collector.BeginBufferedArray();
var count = 0;
- if (value != null)
+ Array array = (Array)value.ReferenceValue;
+ if (array != null)
{
- count = value.Length;
- for (int i = 0; i < value.Length; i++)
+ count = array.Length;
+ for (int i = 0; i < array.Length; i++)
{
- this.elementInfo.WriteData(collector, ref value[i]);
+ this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(array.GetValue(i)));
}
}
public override object GetData(object value)
{
- var array = (ElementType[])value;
+ var array = (Array)value;
var serializedArray = new object[array.Length];
for (int i = 0; i < array.Length; i++)
{
- serializedArray[i] = this.elementInfo.GetData(array[i]);
+ serializedArray[i] = this.elementInfo.GetData(array.GetValue(i));
}
return serializedArray;
}
var scratchNew = scratchOld + size;
if (this.scratchEnd < scratchNew)
{
- throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_AddScalarOutOfRange"));
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_AddScalarOutOfRange"));
}
this.ScalarsBegin();
var pinsTemp = this.pins;
if (this.pinsEnd <= pinsTemp)
{
- throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_PinArrayOutOfRange"));
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_PinArrayOutOfRange"));
}
var datasTemp = this.datas;
if (this.datasEnd <= datasTemp)
{
- throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
}
this.pins = pinsTemp + 1;
var datasTemp = this.datas;
if (this.datasEnd <= datasTemp)
{
- throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
+ throw new IndexOutOfRangeException(Resources.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
}
datasTemp->m_Ptr = (long)(ulong)(UIntPtr)this.scratch;
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
+#if EVENTSOURCE_GENERICS
+?using System;
using System.Reflection;
#if ES_BUILD_STANDALONE
/// </typeparam>
internal static class EnumHelper<UnderlyingType>
{
- private delegate UnderlyingType Transformer<ValueType>(ValueType value);
-
- private static readonly MethodInfo IdentityInfo =
- Statics.GetDeclaredStaticMethod(typeof(EnumHelper<UnderlyingType>), "Identity");
-
public static UnderlyingType Cast<ValueType>(ValueType value)
{
- return Caster<ValueType>.Instance(value);
- }
-
- internal static UnderlyingType Identity(UnderlyingType value)
- {
- return value;
- }
-
- private static class Caster<ValueType>
- {
- public static readonly Transformer<ValueType> Instance =
- (Transformer<ValueType>)Statics.CreateDelegate(
- typeof(Transformer<ValueType>),
- IdentityInfo);
+ return (UnderlyingType)(object)value;
}
}
+
}
+#endif
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections;
using System.Collections.Generic;
#if ES_BUILD_STANDALONE
namespace System.Diagnostics.Tracing
#endif
{
- internal sealed class EnumerableTypeInfo<IterableType, ElementType>
- : TraceLoggingTypeInfo<IterableType>
- where IterableType : IEnumerable<ElementType>
+ internal sealed class EnumerableTypeInfo : TraceLoggingTypeInfo
{
- private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
+ private readonly TraceLoggingTypeInfo elementInfo;
- public EnumerableTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
+ public EnumerableTypeInfo(Type type, TraceLoggingTypeInfo elementInfo)
+ : base(type)
{
this.elementInfo = elementInfo;
}
collector.EndBufferedArray();
}
- public override void WriteData(
- TraceLoggingDataCollector collector,
- ref IterableType value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
var bookmark = collector.BeginBufferedArray();
var count = 0;
- if (value != null)
+ IEnumerable enumerable = (IEnumerable)value.ReferenceValue;
+ if (enumerable != null)
{
- foreach (var element in value)
+ foreach (var element in enumerable)
{
- var el = element;
- this.elementInfo.WriteData(collector, ref el);
+ this.elementInfo.WriteData(collector, elementInfo.PropertyValueFactory(element));
count++;
}
}
public override object GetData(object value)
{
- var iterType = (IterableType)value;
+ var iterType = (IEnumerable)value;
List<object> serializedEnumerable = new List<object>();
foreach (var element in iterType)
{
/// Field should not be displayed.
/// </summary>
NoPrint = 1,
-#endif
+#endif
/// <summary>
/// Field should be formatted as character or string data.
/// Typically applied to 8-bit or 16-bit integers.
/// Field should be formatted as a SOCKADDR. Typically applied to byte[] types.
/// </summary>
SocketAddress = 10,
-#endif
+#endif
/// <summary>
/// Field should be formatted as XML string data. Typically applied to
/// strings or arrays of 8-bit or 16-bit integers.
newActivity.startStopOptions.Opcode = EventOpcode.Start;
this.eventSource.Write(eventName, ref newActivity.startStopOptions, ref newActivity.activityId, ref relatedActivityId, ref data);
}
- else
+ else
{
// If we are not active, we don't set the eventName, which basically also turns off the Stop event as well.
newActivity.activityId = this.Id;
/// <summary>
/// If eventName is non-null then we logged a start event
/// </summary>
- private bool StartEventWasFired { get { return eventName != null; }}
+ private bool StartEventWasFired { get { return eventName != null; } }
private readonly EventSource eventSource;
private EventSourceOptions startStopOptions;
- internal Guid activityId;
+ internal Guid activityId;
// internal Guid relatedActivityId;
private State state;
private string eventName;
{
if (coreType == (int)TraceLoggingDataType.Nil)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNil"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNil"));
}
if (coreType == (int)TraceLoggingDataType.Binary)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
}
#if !BROKEN_UNTIL_M3
if (coreType == (int)TraceLoggingDataType.Utf16String ||
coreType == (int)TraceLoggingDataType.MbcsString)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
}
#endif
}
this.outType++;
if ((this.outType & Statics.OutTypeMask) == 0)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_TooManyFields"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_TooManyFields"));
}
}
/// <summary>
/// TraceLogging: An implementation of TraceLoggingTypeInfo that works
/// for arbitrary types. It writes all public instance properties of
- /// the type. Implemented using Delegate.CreateDelegate(property.Getter).
+ /// the type.
/// </summary>
/// <typeparam name="ContainerType">
/// Type from which to read values.
/// </typeparam>
- internal sealed class InvokeTypeInfo<ContainerType>
- : TraceLoggingTypeInfo<ContainerType>
+ internal sealed class InvokeTypeInfo : TraceLoggingTypeInfo
{
private readonly PropertyAnalysis[] properties;
- private readonly PropertyAccessor<ContainerType>[] accessors;
public InvokeTypeInfo(
+ Type type,
TypeAnalysis typeAnalysis)
: base(
+ type,
typeAnalysis.name,
typeAnalysis.level,
typeAnalysis.opcode,
typeAnalysis.tags)
{
if (typeAnalysis.properties.Length != 0)
- {
this.properties = typeAnalysis.properties;
- this.accessors = new PropertyAccessor<ContainerType>[this.properties.Length];
- for (int i = 0; i < this.accessors.Length; i++)
- {
- this.accessors[i] = PropertyAccessor<ContainerType>.Create(this.properties[i]);
- }
- }
}
public override void WriteMetadata(
}
}
- public override void WriteData(
- TraceLoggingDataCollector collector,
- ref ContainerType value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- if (this.accessors != null)
+ if (this.properties != null)
{
- foreach (var accessor in this.accessors)
+ foreach (var property in this.properties)
{
- accessor.Write(collector, ref value);
+ property.typeInfo.WriteData(collector, property.getter(value));
}
}
}
var memebersValues = new List<object>();
for (int i = 0; i < this.properties.Length; i++)
{
- var propertyValue = accessors[i].GetData((ContainerType)value);
+ var propertyValue = properties[i].propertyInfo.GetValue(value);
membersNames.Add(properties[i].name);
memebersValues.Add(properties[i].typeInfo.GetData(propertyValue));
}
return null;
}
-
- public override void WriteObjectData(
- TraceLoggingDataCollector collector,
- object valueObj)
- {
- if (this.accessors != null)
- {
- var value = valueObj == null
- ? default(ContainerType)
- : (ContainerType)valueObj;
- this.WriteData(collector, ref value);
- }
- }
}
}
{
for(;;)
{
- int snapshot =lastIdentity;
+ int snapshot = lastIdentity;
int newIdentity = (lastIdentity & ~0xFFFFFF) + eventId;
newIdentity = Math.Max(newIdentity, snapshot); // Should be redundant. as we only create descriptors once.
if (Interlocked.CompareExchange(ref lastIdentity, newIdentity, snapshot) == snapshot)
break;
}
}
-
+
private static int lastIdentity = Statics.TraceLoggingChannel << 24;
internal readonly string name;
internal readonly EventTags tags;
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Reflection;
-
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
- /// <summary>
- /// TraceLogging: Each PropertyAccessor instance encapsulates the information
- /// needed to read a particular property from an instance of ContainerType
- /// and write the value to a DataCollector. Used by InvokeTypeInfo.
- /// </summary>
- /// <typeparam name="ContainerType">
- /// The type of the object from which properties are read.
- /// </typeparam>
- internal abstract class PropertyAccessor<ContainerType>
- {
- public abstract void Write(TraceLoggingDataCollector collector, ref ContainerType value);
- public abstract object GetData(ContainerType value);
-
- public static PropertyAccessor<ContainerType> Create(PropertyAnalysis property)
- {
- // Due to current Project N limitations on handling generic instantiations with
- // 2 generic parameters we have to explicitly create the instantiations that we consider
- // important to EventSource performance (we have considered int, long, string for the moment).
- // Everything else is handled by NonGenericPropertyWriter that ends up boxing the container object.
- var retType = property.getterInfo.ReturnType;
- if (!Statics.IsValueType(typeof(ContainerType)))
- {
- if (retType == typeof(int))
- return new ClassPropertyWriter<ContainerType, int>(property);
- else if (retType == typeof(long))
- return new ClassPropertyWriter<ContainerType, long>(property);
- else if (retType == typeof(string))
- return new ClassPropertyWriter<ContainerType, string>(property);
- }
- else
- {
- // Handle the case if it is a struct (DD 1027919)
- }
-
- // Otherwise use the boxing one.
- return new NonGenericProperytWriter<ContainerType>(property);
- }
- }
-
- /// <summary>
- /// The type specific version of the property writers uses generics in a way
- /// that Project N can't handle at the moment. To avoid this we simply
- /// use reflection completely.
- /// </summary>
- internal class NonGenericProperytWriter<ContainerType> : PropertyAccessor<ContainerType>
- {
- public NonGenericProperytWriter(PropertyAnalysis property)
- {
- getterInfo = property.getterInfo;
- typeInfo = property.typeInfo;
- }
-
- public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
- {
- object value = container == null
- ? null
- : getterInfo.Invoke((object)container, null);
- this.typeInfo.WriteObjectData(collector, value);
- }
-
- public override object GetData(ContainerType container)
- {
- return container == null
- ? default(ValueType)
- : getterInfo.Invoke((object)container, null);
- }
-
- private readonly TraceLoggingTypeInfo typeInfo;
- private readonly MethodInfo getterInfo;
- }
-
- /// <summary>
- /// Implementation of PropertyAccessor for use when ContainerType is a
- /// value type.
- /// </summary>
- /// <typeparam name="ContainerType">The type of the object from which properties are read.</typeparam>
- /// <typeparam name="ValueType">Type of the property being read.</typeparam>
- internal class StructPropertyWriter<ContainerType, ValueType>
- : PropertyAccessor<ContainerType>
- {
- private delegate ValueType Getter(ref ContainerType container);
- private readonly TraceLoggingTypeInfo<ValueType> valueTypeInfo;
- private readonly Getter getter;
-
- public StructPropertyWriter(PropertyAnalysis property)
- {
- this.valueTypeInfo = (TraceLoggingTypeInfo<ValueType>)property.typeInfo;
- this.getter = (Getter)Statics.CreateDelegate(
- typeof(Getter),
- property.getterInfo);
- }
-
- public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
- {
- var value = container == null
- ? default(ValueType)
- : getter(ref container);
- this.valueTypeInfo.WriteData(collector, ref value);
- }
-
- public override object GetData(ContainerType container)
- {
- return container == null
- ? default(ValueType)
- : getter(ref container);
- }
- }
-
- /// <summary>
- /// Implementation of PropertyAccessor for use when ContainerType is a
- /// reference type.
- /// </summary>
- /// <typeparam name="ContainerType">The type of the object from which properties are read.</typeparam>
- /// <typeparam name="ValueType">Type of the property being read.</typeparam>
- internal class ClassPropertyWriter<ContainerType, ValueType>
- : PropertyAccessor<ContainerType>
- {
- private delegate ValueType Getter(ContainerType container);
- private readonly TraceLoggingTypeInfo<ValueType> valueTypeInfo;
- private readonly Getter getter;
-
- public ClassPropertyWriter(PropertyAnalysis property)
- {
- this.valueTypeInfo = (TraceLoggingTypeInfo<ValueType>)property.typeInfo;
- this.getter = (Getter)Statics.CreateDelegate(
- typeof(Getter),
- property.getterInfo);
- }
-
- public override void Write(TraceLoggingDataCollector collector, ref ContainerType container)
- {
- var value = container == null
- ? default(ValueType)
- : getter(container);
- this.valueTypeInfo.WriteData(collector, ref value);
- }
-
- public override object GetData(ContainerType container)
- {
- return container == null
- ? default(ValueType)
- : getter(container);
- }
- }
-}
internal sealed class PropertyAnalysis
{
internal readonly string name;
- internal readonly MethodInfo getterInfo;
+ internal readonly PropertyInfo propertyInfo;
+ internal readonly Func<PropertyValue, PropertyValue> getter;
internal readonly TraceLoggingTypeInfo typeInfo;
internal readonly EventFieldAttribute fieldAttribute;
public PropertyAnalysis(
string name,
- MethodInfo getterInfo,
+ PropertyInfo propertyInfo,
TraceLoggingTypeInfo typeInfo,
EventFieldAttribute fieldAttribute)
{
this.name = name;
- this.getterInfo = getterInfo;
+ this.propertyInfo = propertyInfo;
+ this.getter = PropertyValue.GetPropertyGetter(propertyInfo);
this.typeInfo = typeInfo;
this.fieldAttribute = fieldAttribute;
}
--- /dev/null
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+
+namespace System.Diagnostics.Tracing
+{
+ /// <summary>
+ /// Holds property values of any type. For common value types, we have inline storage so that we don't need
+ /// to box the values. For all other types, we store the value in a single object reference field.
+ ///
+ /// To get the value of a property quickly, use a delegate produced by <see cref="PropertyValue.GetPropertyGetter(PropertyInfo)"/>.
+ /// </summary>
+ internal unsafe struct PropertyValue
+ {
+ /// <summary>
+ /// Union of well-known value types, to avoid boxing those types.
+ /// </summary>
+ [StructLayout(LayoutKind.Explicit)]
+ public struct Scalar
+ {
+ [FieldOffset(0)]
+ public Boolean AsBoolean;
+ [FieldOffset(0)]
+ public Byte AsByte;
+ [FieldOffset(0)]
+ public SByte AsSByte;
+ [FieldOffset(0)]
+ public Char AsChar;
+ [FieldOffset(0)]
+ public Int16 AsInt16;
+ [FieldOffset(0)]
+ public UInt16 AsUInt16;
+ [FieldOffset(0)]
+ public Int32 AsInt32;
+ [FieldOffset(0)]
+ public UInt32 AsUInt32;
+ [FieldOffset(0)]
+ public Int64 AsInt64;
+ [FieldOffset(0)]
+ public UInt64 AsUInt64;
+ [FieldOffset(0)]
+ public IntPtr AsIntPtr;
+ [FieldOffset(0)]
+ public UIntPtr AsUIntPtr;
+ [FieldOffset(0)]
+ public Single AsSingle;
+ [FieldOffset(0)]
+ public Double AsDouble;
+ [FieldOffset(0)]
+ public Guid AsGuid;
+ [FieldOffset(0)]
+ public DateTime AsDateTime;
+ [FieldOffset(0)]
+ public DateTimeOffset AsDateTimeOffset;
+ [FieldOffset(0)]
+ public TimeSpan AsTimeSpan;
+ [FieldOffset(0)]
+ public Decimal AsDecimal;
+ }
+
+ // Anything not covered by the Scalar union gets stored in this reference.
+ readonly object _reference;
+ readonly Scalar _scalar;
+ readonly int _scalarLength;
+
+ private PropertyValue(object value)
+ {
+ _reference = value;
+ _scalar = default(Scalar);
+ _scalarLength = 0;
+ }
+
+ private PropertyValue(Scalar scalar, int scalarLength)
+ {
+ _reference = null;
+ _scalar = scalar;
+ _scalarLength = scalarLength;
+ }
+
+ private PropertyValue(Boolean value) : this(new Scalar() { AsBoolean = value }, sizeof(Boolean)) { }
+ private PropertyValue(Byte value) : this(new Scalar() { AsByte = value }, sizeof(Byte)) { }
+ private PropertyValue(SByte value) : this(new Scalar() { AsSByte = value }, sizeof(SByte)) { }
+ private PropertyValue(Char value) : this(new Scalar() { AsChar = value }, sizeof(Char)) { }
+ private PropertyValue(Int16 value) : this(new Scalar() { AsInt16 = value }, sizeof(Int16)) { }
+ private PropertyValue(UInt16 value) : this(new Scalar() { AsUInt16 = value }, sizeof(UInt16)) { }
+ private PropertyValue(Int32 value) : this(new Scalar() { AsInt32 = value }, sizeof(Int32)) { }
+ private PropertyValue(UInt32 value) : this(new Scalar() { AsUInt32 = value }, sizeof(UInt32)) { }
+ private PropertyValue(Int64 value) : this(new Scalar() { AsInt64 = value }, sizeof(Int64)) { }
+ private PropertyValue(UInt64 value) : this(new Scalar() { AsUInt64 = value }, sizeof(UInt64)) { }
+ private PropertyValue(IntPtr value) : this(new Scalar() { AsIntPtr = value }, sizeof(IntPtr)) { }
+ private PropertyValue(UIntPtr value) : this(new Scalar() { AsUIntPtr = value }, sizeof(UIntPtr)) { }
+ private PropertyValue(Single value) : this(new Scalar() { AsSingle = value }, sizeof(Single)) { }
+ private PropertyValue(Double value) : this(new Scalar() { AsDouble = value }, sizeof(Double)) { }
+ private PropertyValue(Guid value) : this(new Scalar() { AsGuid = value }, sizeof(Guid)) { }
+ private PropertyValue(DateTime value) : this(new Scalar() { AsDateTime = value }, sizeof(DateTime)) { }
+ private PropertyValue(DateTimeOffset value) : this(new Scalar() { AsDateTimeOffset = value }, sizeof(DateTimeOffset)) { }
+ private PropertyValue(TimeSpan value) : this(new Scalar() { AsTimeSpan = value }, sizeof(TimeSpan)) { }
+ private PropertyValue(Decimal value) : this(new Scalar() { AsDecimal = value }, sizeof(Decimal)) { }
+
+ public static Func<object, PropertyValue> GetFactory(Type type)
+ {
+ if (type == typeof(Boolean)) return value => new PropertyValue((Boolean)value);
+ if (type == typeof(Byte)) return value => new PropertyValue((Byte)value);
+ if (type == typeof(SByte)) return value => new PropertyValue((SByte)value);
+ if (type == typeof(Char)) return value => new PropertyValue((Char)value);
+ if (type == typeof(Int16)) return value => new PropertyValue((Int16)value);
+ if (type == typeof(UInt16)) return value => new PropertyValue((UInt16)value);
+ if (type == typeof(Int32)) return value => new PropertyValue((Int32)value);
+ if (type == typeof(UInt32)) return value => new PropertyValue((UInt32)value);
+ if (type == typeof(Int64)) return value => new PropertyValue((Int64)value);
+ if (type == typeof(UInt64)) return value => new PropertyValue((UInt64)value);
+ if (type == typeof(IntPtr)) return value => new PropertyValue((IntPtr)value);
+ if (type == typeof(UIntPtr)) return value => new PropertyValue((UIntPtr)value);
+ if (type == typeof(Single)) return value => new PropertyValue((Single)value);
+ if (type == typeof(Double)) return value => new PropertyValue((Double)value);
+ if (type == typeof(Guid)) return value => new PropertyValue((Guid)value);
+ if (type == typeof(DateTime)) return value => new PropertyValue((DateTime)value);
+ if (type == typeof(DateTimeOffset)) return value => new PropertyValue((DateTimeOffset)value);
+ if (type == typeof(TimeSpan)) return value => new PropertyValue((TimeSpan)value);
+ if (type == typeof(Decimal)) return value => new PropertyValue((Decimal)value);
+
+ return value => new PropertyValue(value);
+ }
+
+
+ public object ReferenceValue
+ {
+ get
+ {
+ Contract.Assert(_scalarLength == 0, "This ReflectedValue refers to an unboxed value type, not a reference type or boxed value type.");
+ return _reference;
+ }
+ }
+
+ public Scalar ScalarValue
+ {
+ get
+ {
+ Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+ return _scalar;
+ }
+ }
+
+ public int ScalarLength
+ {
+ get
+ {
+ Contract.Assert(_scalarLength > 0, "This ReflectedValue refers to a reference type or boxed value type, not an unboxed value type");
+ return _scalarLength;
+ }
+ }
+
+ /// <summary>
+ /// Gets a delegate that gets the value of a given property.
+ /// </summary>
+ public static Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+ {
+ if (property.DeclaringType.GetTypeInfo().IsValueType)
+ return GetBoxedValueTypePropertyGetter(property);
+ else
+ return GetReferenceTypePropertyGetter(property);
+ }
+
+ /// <summary>
+ /// Gets a delegate that gets the value of a property of a value type. We unfortunately cannot avoid boxing the value type,
+ /// without making this generic over the value type. That would result in a large number of generic instantiations, and furthermore
+ /// does not work correctly on .Net Native (we cannot express the needed instantiations in an rd.xml file). We expect that user-defined
+ /// value types will be rare, and in any case the boxing only happens for events that are actually enabled.
+ /// </summary>
+ private static Func<PropertyValue, PropertyValue> GetBoxedValueTypePropertyGetter(PropertyInfo property)
+ {
+ var type = property.PropertyType;
+
+ if (type.GetTypeInfo().IsEnum)
+ type = Enum.GetUnderlyingType(type);
+
+ var factory = GetFactory(type);
+
+ return container => factory(property.GetValue(container.ReferenceValue));
+ }
+
+ /// <summary>
+ /// For properties of reference types, we use a generic helper class to get the value. This enables us to use MethodInfo.CreateDelegate
+ /// to build a fast getter. We can get away with this on .Net Native, because we really only need one runtime instantiation of the
+ /// generic type, since it's only instantiated over reference types (and thus all instances are shared).
+ /// </summary>
+ /// <param name="property"></param>
+ /// <returns></returns>
+ private static Func<PropertyValue, PropertyValue> GetReferenceTypePropertyGetter(PropertyInfo property)
+ {
+ var helper = (TypeHelper)Activator.CreateInstance(typeof(ReferenceTypeHelper<>).MakeGenericType(property.DeclaringType));
+ return helper.GetPropertyGetter(property);
+ }
+
+ private abstract class TypeHelper
+ {
+ public abstract Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property);
+
+ protected Delegate GetGetMethod(PropertyInfo property, Type propertyType)
+ {
+ return property.GetMethod.CreateDelegate(typeof(Func<,>).MakeGenericType(property.DeclaringType, propertyType));
+ }
+ }
+
+ private sealed class ReferenceTypeHelper<TContainer> : TypeHelper where TContainer : class
+ {
+ public override Func<PropertyValue, PropertyValue> GetPropertyGetter(PropertyInfo property)
+ {
+ var type = property.PropertyType;
+
+ if (!Statics.IsValueType(type))
+ {
+ var getter = (Func<TContainer, object>)GetGetMethod(property, type);
+ return container => new PropertyValue(getter((TContainer)container.ReferenceValue));
+ }
+ else
+ {
+ if (type.GetTypeInfo().IsEnum)
+ type = Enum.GetUnderlyingType(type);
+
+ if (type == typeof(Boolean)) { var f = (Func<TContainer, Boolean>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Byte)) { var f = (Func<TContainer, Byte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(SByte)) { var f = (Func<TContainer, SByte>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Char)) { var f = (Func<TContainer, Char>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int16)) { var f = (Func<TContainer, Int16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt16)) { var f = (Func<TContainer, UInt16>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int32)) { var f = (Func<TContainer, Int32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt32)) { var f = (Func<TContainer, UInt32>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Int64)) { var f = (Func<TContainer, Int64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UInt64)) { var f = (Func<TContainer, UInt64>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(IntPtr)) { var f = (Func<TContainer, IntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(UIntPtr)) { var f = (Func<TContainer, UIntPtr>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Single)) { var f = (Func<TContainer, Single>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Double)) { var f = (Func<TContainer, Double>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Guid)) { var f = (Func<TContainer, Guid>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(DateTime)) { var f = (Func<TContainer, DateTime>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(DateTimeOffset)) { var f = (Func<TContainer, DateTimeOffset>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(TimeSpan)) { var f = (Func<TContainer, TimeSpan>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+ if (type == typeof(Decimal)) { var f = (Func<TContainer, Decimal>)GetGetMethod(property, type); return container => new PropertyValue(f((TContainer)container.ReferenceValue)); }
+
+ return container => new PropertyValue(property.GetValue(container.ReferenceValue));
+ }
+ }
+ }
+ }
+}
/// Type of the top-level payload object. Should be EmptyStruct if the
/// event has no payload.
/// </typeparam>
- internal class SimpleEventTypes<T>
- : TraceLoggingEventTypes
+ internal static class SimpleEventTypes<T>
{
- private static SimpleEventTypes<T> instance;
+ private static TraceLoggingEventTypes instance;
- internal readonly TraceLoggingTypeInfo<T> typeInfo;
-
- private SimpleEventTypes(TraceLoggingTypeInfo<T> typeInfo)
- : base(
- typeInfo.Name,
- typeInfo.Tags,
- new TraceLoggingTypeInfo[] { typeInfo })
- {
- this.typeInfo = typeInfo;
- }
-
- public static SimpleEventTypes<T> Instance
+ public static TraceLoggingEventTypes Instance
{
get { return instance ?? InitInstance(); }
}
- private static SimpleEventTypes<T> InitInstance()
+ private static TraceLoggingEventTypes InitInstance()
{
- var newInstance = new SimpleEventTypes<T>(TraceLoggingTypeInfo<T>.Instance);
+ var info = TraceLoggingTypeInfo.GetInstance(typeof(T), null);
+ var newInstance = new TraceLoggingEventTypes(info.Name, info.Tags, new TraceLoggingTypeInfo[] { info });
Interlocked.CompareExchange(ref instance, newInstance, null);
return instance;
}
using System;
using System.Collections.Generic;
+using System.Reflection;
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
- #region NullTypeInfo
-
- /// <summary>
- /// TraceLogging: Type handler for empty or unsupported types.
- /// </summary>
- /// <typeparam name="DataType">The type to handle.</typeparam>
- internal sealed class NullTypeInfo<DataType>
- : TraceLoggingTypeInfo<DataType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddGroup(name);
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref DataType value)
- {
- return;
- }
-
- public override object GetData(object value)
- {
- return null;
- }
- }
-
- #endregion
-
- #region Primitive scalars
-
- /// <summary>
- /// TraceLogging: Type handler for Boolean.
- /// </summary>
- internal sealed class BooleanTypeInfo
- : TraceLoggingTypeInfo<Boolean>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Boolean8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Boolean value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Byte.
- /// </summary>
- internal sealed class ByteTypeInfo
- : TraceLoggingTypeInfo<Byte>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.UInt8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Byte value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for SByte.
- /// </summary>
- internal sealed class SByteTypeInfo
- : TraceLoggingTypeInfo<SByte>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Int8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref SByte value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int16.
- /// </summary>
- internal sealed class Int16TypeInfo
- : TraceLoggingTypeInfo<Int16>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Int16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int16 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt16.
- /// </summary>
- internal sealed class UInt16TypeInfo
- : TraceLoggingTypeInfo<UInt16>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt16 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int32.
- /// </summary>
- internal sealed class Int32TypeInfo
- : TraceLoggingTypeInfo<Int32>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Int32));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int32 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt32.
- /// </summary>
- internal sealed class UInt32TypeInfo
- : TraceLoggingTypeInfo<UInt32>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt32 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int64.
- /// </summary>
- internal sealed class Int64TypeInfo
- : TraceLoggingTypeInfo<Int64>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Int64));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int64 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt64.
- /// </summary>
- internal sealed class UInt64TypeInfo
- : TraceLoggingTypeInfo<UInt64>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt64 value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for IntPtr.
- /// </summary>
- internal sealed class IntPtrTypeInfo
- : TraceLoggingTypeInfo<IntPtr>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.FormatPtr(format, Statics.IntPtrType));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref IntPtr value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UIntPtr.
- /// </summary>
- internal sealed class UIntPtrTypeInfo
- : TraceLoggingTypeInfo<UIntPtr>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.FormatPtr(format, Statics.UIntPtrType));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UIntPtr value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Double.
- /// </summary>
- internal sealed class DoubleTypeInfo
- : TraceLoggingTypeInfo<Double>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Double));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Double value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Single.
- /// </summary>
- internal sealed class SingleTypeInfo
- : TraceLoggingTypeInfo<Single>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Float));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Single value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Char.
- /// </summary>
- internal sealed class CharTypeInfo
- : TraceLoggingTypeInfo<Char>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Char16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Char value)
- {
- collector.AddScalar(value);
- }
- }
-
- #endregion
-
- #region Primitive arrays
-
- /// <summary>
- /// TraceLogging: Type handler for Boolean[].
- /// </summary>
- internal sealed class BooleanArrayTypeInfo
- : TraceLoggingTypeInfo<Boolean[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format8(format, TraceLoggingDataType.Boolean8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Boolean[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Byte[].
- /// </summary>
- internal sealed class ByteArrayTypeInfo
- : TraceLoggingTypeInfo<Byte[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- switch (format)
- {
- default:
- collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.Binary, format));
- break;
- case EventFieldFormat.String:
- collector.AddBinary(name, TraceLoggingDataType.CountedMbcsString);
- break;
- case EventFieldFormat.Xml:
- collector.AddBinary(name, TraceLoggingDataType.CountedMbcsXml);
- break;
- case EventFieldFormat.Json:
- collector.AddBinary(name, TraceLoggingDataType.CountedMbcsJson);
- break;
- case EventFieldFormat.Boolean:
- collector.AddArray(name, TraceLoggingDataType.Boolean8);
- break;
- case EventFieldFormat.Hexadecimal:
- collector.AddArray(name, TraceLoggingDataType.HexInt8);
- break;
-#if false
- case EventSourceFieldFormat.Signed:
- collector.AddArray(name, TraceLoggingDataType.Int8);
- break;
- case EventSourceFieldFormat.Unsigned:
- collector.AddArray(name, TraceLoggingDataType.UInt8);
- break;
-#endif
- }
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Byte[] value)
- {
- collector.AddBinary(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for SByte[].
- /// </summary>
- internal sealed class SByteArrayTypeInfo
- : TraceLoggingTypeInfo<SByte[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format8(format, TraceLoggingDataType.Int8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref SByte[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int16[].
- /// </summary>
- internal sealed class Int16ArrayTypeInfo
- : TraceLoggingTypeInfo<Int16[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.Int16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int16[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt16[].
- /// </summary>
- internal sealed class UInt16ArrayTypeInfo
- : TraceLoggingTypeInfo<UInt16[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt16[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int32[].
- /// </summary>
- internal sealed class Int32ArrayTypeInfo
- : TraceLoggingTypeInfo<Int32[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.Int32));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int32[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt32[].
- /// </summary>
- internal sealed class UInt32ArrayTypeInfo
- : TraceLoggingTypeInfo<UInt32[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt32[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Int64[].
- /// </summary>
- internal sealed class Int64ArrayTypeInfo
- : TraceLoggingTypeInfo<Int64[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.Int64));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Int64[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for UInt64[].
- /// </summary>
- internal sealed class UInt64ArrayTypeInfo
- : TraceLoggingTypeInfo<UInt64[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UInt64[] value)
- {
- collector.AddArray(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for IntPtr[].
- /// </summary>
- internal sealed class IntPtrArrayTypeInfo
- : TraceLoggingTypeInfo<IntPtr[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.FormatPtr(format, Statics.IntPtrType));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref IntPtr[] value)
- {
- collector.AddArray(value);
- }
- }
+#if !ES_BUILD_AGAINST_DOTNET_V35
+using Contract = System.Diagnostics.Contracts.Contract;
+#else
+using Contract = Microsoft.Diagnostics.Contracts.Internal.Contract;
+#endif
+#if ES_BUILD_STANDALONE
+namespace Microsoft.Diagnostics.Tracing
+#else
+namespace System.Diagnostics.Tracing
+#endif
+{
/// <summary>
- /// TraceLogging: Type handler for UIntPtr[].
+ /// TraceLogging: Type handler for empty or unsupported types.
/// </summary>
- internal sealed class UIntPtrArrayTypeInfo
- : TraceLoggingTypeInfo<UIntPtr[]>
+ internal sealed class NullTypeInfo : TraceLoggingTypeInfo
{
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.FormatPtr(format, Statics.UIntPtrType));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref UIntPtr[] value)
- {
- collector.AddArray(value);
- }
- }
+ public NullTypeInfo() : base(typeof(EmptyStruct)) { }
- /// <summary>
- /// TraceLogging: Type handler for Char[].
- /// </summary>
- internal sealed class CharArrayTypeInfo
- : TraceLoggingTypeInfo<Char[]>
- {
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
string name,
EventFieldFormat format)
{
- collector.AddArray(name, Statics.Format16(format, TraceLoggingDataType.Char16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Char[] value)
- {
- collector.AddArray(value);
+ collector.AddGroup(name);
}
- }
- /// <summary>
- /// TraceLogging: Type handler for Double[].
- /// </summary>
- internal sealed class DoubleArrayTypeInfo
- : TraceLoggingTypeInfo<Double[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddArray(name, Statics.Format64(format, TraceLoggingDataType.Double));
+ return;
}
- public override void WriteData(TraceLoggingDataCollector collector, ref Double[] value)
+ public override object GetData(object value)
{
- collector.AddArray(value);
+ return null;
}
}
/// <summary>
- /// TraceLogging: Type handler for Single[].
+ /// Type handler for simple scalar types.
/// </summary>
- internal sealed class SingleArrayTypeInfo
- : TraceLoggingTypeInfo<Single[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.Format32(format, TraceLoggingDataType.Float));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Single[] value)
- {
- collector.AddArray(value);
- }
- }
-
- #endregion
-
- #region Enum scalars
-
- internal sealed class EnumByteTypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.UInt8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<Byte>.Cast(value));
- }
-
- public override object GetData(object value)
- {
- return value;
- }
- }
-
- internal sealed class EnumSByteTypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format8(format, TraceLoggingDataType.Int8));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<SByte>.Cast(value));
- }
-
- public override object GetData(object value)
- {
- return value;
- }
- }
-
- internal sealed class EnumInt16TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.Int16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<Int16>.Cast(value));
- }
-
- public override object GetData(object value)
- {
- return value;
- }
- }
-
- internal sealed class EnumUInt16TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
+ sealed class ScalarTypeInfo : TraceLoggingTypeInfo
{
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format16(format, TraceLoggingDataType.UInt16));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<UInt16>.Cast(value));
- }
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+ TraceLoggingDataType nativeFormat;
- public override object GetData(object value)
+ private ScalarTypeInfo(
+ Type type,
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+ TraceLoggingDataType nativeFormat)
+ : base(type)
{
- return value;
+ this.formatFunc = formatFunc;
+ this.nativeFormat = nativeFormat;
}
- }
- internal sealed class EnumInt32TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
+ public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
{
- collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.Int32));
+ collector.AddScalar(name, formatFunc(format, nativeFormat));
}
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddScalar(EnumHelper<Int32>.Cast(value));
+ collector.AddScalar(value);
}
- public override object GetData(object value)
- {
- return value;
- }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarTypeInfo(typeof(Boolean), Statics.Format8, TraceLoggingDataType.Boolean8); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarTypeInfo(typeof(Byte), Statics.Format8, TraceLoggingDataType.UInt8); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarTypeInfo(typeof(SByte), Statics.Format8, TraceLoggingDataType.Int8); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarTypeInfo(typeof(Char), Statics.Format16, TraceLoggingDataType.Char16); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarTypeInfo(typeof(Int16), Statics.Format16, TraceLoggingDataType.Int16); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarTypeInfo(typeof(UInt16), Statics.Format16, TraceLoggingDataType.UInt16); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarTypeInfo(typeof(Int32), Statics.Format32, TraceLoggingDataType.Int32); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarTypeInfo(typeof(UInt32), Statics.Format32, TraceLoggingDataType.UInt32); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarTypeInfo(typeof(Int64), Statics.Format64, TraceLoggingDataType.Int64); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarTypeInfo(typeof(UInt64), Statics.Format64, TraceLoggingDataType.UInt64); }
+ public static TraceLoggingTypeInfo IntPtr() { return new ScalarTypeInfo(typeof(IntPtr), Statics.FormatPtr, Statics.IntPtrType); }
+ public static TraceLoggingTypeInfo UIntPtr() { return new ScalarTypeInfo(typeof(UIntPtr), Statics.FormatPtr, Statics.UIntPtrType); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarTypeInfo(typeof(Single), Statics.Format32, TraceLoggingDataType.Float); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarTypeInfo(typeof(Double), Statics.Format64, TraceLoggingDataType.Double); }
+ public static TraceLoggingTypeInfo Guid() { return new ScalarTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid); }
}
- internal sealed class EnumUInt32TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format32(format, TraceLoggingDataType.UInt32));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<UInt32>.Cast(value));
- }
-
- public override object GetData(object value)
- {
- return value;
- }
- }
- internal sealed class EnumInt64TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
+ /// <summary>
+ /// Type handler for arrays of scalars
+ /// </summary>
+ internal sealed class ScalarArrayTypeInfo : TraceLoggingTypeInfo
{
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.Int64));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
- {
- collector.AddScalar(EnumHelper<Int64>.Cast(value));
- }
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc;
+ TraceLoggingDataType nativeFormat;
+ int elementSize;
- public override object GetData(object value)
+ private ScalarArrayTypeInfo(
+ Type type,
+ Func<EventFieldFormat, TraceLoggingDataType, TraceLoggingDataType> formatFunc,
+ TraceLoggingDataType nativeFormat,
+ int elementSize)
+ : base(type)
{
- return value;
+ this.formatFunc = formatFunc;
+ this.nativeFormat = nativeFormat;
+ this.elementSize = elementSize;
}
- }
- internal sealed class EnumUInt64TypeInfo<EnumType>
- : TraceLoggingTypeInfo<EnumType>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
+ public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
{
- collector.AddScalar(name, Statics.Format64(format, TraceLoggingDataType.UInt64));
+ collector.AddArray(name, formatFunc(format, nativeFormat));
}
- public override void WriteData(TraceLoggingDataCollector collector, ref EnumType value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddScalar(EnumHelper<UInt64>.Cast(value));
+ collector.AddArray(value, elementSize);
}
- public override object GetData(object value)
- {
- return value;
- }
+ public static TraceLoggingTypeInfo Boolean() { return new ScalarArrayTypeInfo(typeof(Boolean[]), Statics.Format8, TraceLoggingDataType.Boolean8, sizeof(Boolean)); }
+ public static TraceLoggingTypeInfo Byte() { return new ScalarArrayTypeInfo(typeof(Byte[]), Statics.Format8, TraceLoggingDataType.UInt8, sizeof(Byte)); }
+ public static TraceLoggingTypeInfo SByte() { return new ScalarArrayTypeInfo(typeof(SByte[]), Statics.Format8, TraceLoggingDataType.Int8, sizeof(SByte)); }
+ public static TraceLoggingTypeInfo Char() { return new ScalarArrayTypeInfo(typeof(Char[]), Statics.Format16, TraceLoggingDataType.Char16, sizeof(Char)); }
+ public static TraceLoggingTypeInfo Int16() { return new ScalarArrayTypeInfo(typeof(Int16[]), Statics.Format16, TraceLoggingDataType.Int16, sizeof(Int16)); }
+ public static TraceLoggingTypeInfo UInt16() { return new ScalarArrayTypeInfo(typeof(UInt16[]), Statics.Format16, TraceLoggingDataType.UInt16, sizeof(UInt16)); }
+ public static TraceLoggingTypeInfo Int32() { return new ScalarArrayTypeInfo(typeof(Int32[]), Statics.Format32, TraceLoggingDataType.Int32, sizeof(Int32)); }
+ public static TraceLoggingTypeInfo UInt32() { return new ScalarArrayTypeInfo(typeof(UInt32[]), Statics.Format32, TraceLoggingDataType.UInt32, sizeof(UInt32)); }
+ public static TraceLoggingTypeInfo Int64() { return new ScalarArrayTypeInfo(typeof(Int64[]), Statics.Format64, TraceLoggingDataType.Int64, sizeof(Int64)); }
+ public static TraceLoggingTypeInfo UInt64() { return new ScalarArrayTypeInfo(typeof(UInt64[]), Statics.Format64, TraceLoggingDataType.UInt64, sizeof(UInt64)); }
+ public static TraceLoggingTypeInfo IntPtr() { return new ScalarArrayTypeInfo(typeof(IntPtr[]), Statics.FormatPtr, Statics.IntPtrType, System.IntPtr.Size); }
+ public static TraceLoggingTypeInfo UIntPtr() { return new ScalarArrayTypeInfo(typeof(UIntPtr[]), Statics.FormatPtr, Statics.UIntPtrType, System.IntPtr.Size); }
+ public static TraceLoggingTypeInfo Single() { return new ScalarArrayTypeInfo(typeof(Single[]), Statics.Format32, TraceLoggingDataType.Float, sizeof(Single)); }
+ public static TraceLoggingTypeInfo Double() { return new ScalarArrayTypeInfo(typeof(Double[]), Statics.Format64, TraceLoggingDataType.Double, sizeof(Double)); }
+ public unsafe static TraceLoggingTypeInfo Guid() { return new ScalarArrayTypeInfo(typeof(Guid), (f, t) => Statics.MakeDataType(TraceLoggingDataType.Guid, f), TraceLoggingDataType.Guid, sizeof(Guid)); }
}
- #endregion
-
- #region Other built-in types
-
/// <summary>
/// TraceLogging: Type handler for String.
/// </summary>
- internal sealed class StringTypeInfo
- : TraceLoggingTypeInfo<String>
+ internal sealed class StringTypeInfo : TraceLoggingTypeInfo
{
+ public StringTypeInfo() : base(typeof(string)) { }
+
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
string name,
collector.AddBinary(name, Statics.MakeDataType(TraceLoggingDataType.CountedUtf16String, format));
}
- public override void WriteData(TraceLoggingDataCollector collector, ref String value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddBinary(value);
+ collector.AddBinary((string)value.ReferenceValue);
}
public override object GetData(object value)
{
- object val = base.GetData(value);
- if (null == val)
- val = "";
-
- return val;
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Guid.
- /// </summary>
- internal sealed class GuidTypeInfo
- : TraceLoggingTypeInfo<Guid>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Guid, format));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Guid value)
- {
- collector.AddScalar(value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for Guid[].
- /// </summary>
- internal sealed class GuidArrayTypeInfo
- : TraceLoggingTypeInfo<Guid[]>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddArray(name, Statics.MakeDataType(TraceLoggingDataType.Guid, format));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref Guid[] value)
- {
- collector.AddArray(value);
+ if(value == null)
+ {
+ return "";
+ }
+
+ return value;
}
}
/// <summary>
/// TraceLogging: Type handler for DateTime.
/// </summary>
- internal sealed class DateTimeTypeInfo
- : TraceLoggingTypeInfo<DateTime>
+ internal sealed class DateTimeTypeInfo : TraceLoggingTypeInfo
{
+ public DateTimeTypeInfo() : base(typeof(DateTime)) { }
+
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
string name,
collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.FileTime, format));
}
- public override void WriteData(TraceLoggingDataCollector collector, ref DateTime value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- var ticks = value.Ticks;
+ var ticks = value.ScalarValue.AsDateTime.Ticks;
collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
}
}
/// <summary>
/// TraceLogging: Type handler for DateTimeOffset.
/// </summary>
- internal sealed class DateTimeOffsetTypeInfo
- : TraceLoggingTypeInfo<DateTimeOffset>
+ internal sealed class DateTimeOffsetTypeInfo : TraceLoggingTypeInfo
{
+ public DateTimeOffsetTypeInfo() : base(typeof(DateTimeOffset)) { }
+
public override void WriteMetadata(TraceLoggingMetadataCollector collector, string name, EventFieldFormat format)
{
var group = collector.AddGroup(name);
group.AddScalar("Offset", TraceLoggingDataType.Int64);
}
- public override void WriteData(TraceLoggingDataCollector collector, ref DateTimeOffset value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- var ticks = value.Ticks;
+ var dateTimeOffset = value.ScalarValue.AsDateTimeOffset;
+ var ticks = dateTimeOffset.Ticks;
collector.AddScalar(ticks < 504911232000000000 ? 0 : ticks - 504911232000000000);
- collector.AddScalar(value.Offset.Ticks);
+ collector.AddScalar(dateTimeOffset.Offset.Ticks);
}
}
/// <summary>
/// TraceLogging: Type handler for TimeSpan.
/// </summary>
- internal sealed class TimeSpanTypeInfo
- : TraceLoggingTypeInfo<TimeSpan>
+ internal sealed class TimeSpanTypeInfo : TraceLoggingTypeInfo
{
+ public TimeSpanTypeInfo() : base(typeof(TimeSpan)) { }
+
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
string name,
collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Int64, format));
}
- public override void WriteData(TraceLoggingDataCollector collector, ref TimeSpan value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- collector.AddScalar(value.Ticks);
+ collector.AddScalar(value.ScalarValue.AsTimeSpan.Ticks);
}
}
/// <summary>
/// TraceLogging: Type handler for Decimal. (Note: not full-fidelity, exposed as Double.)
/// </summary>
- internal sealed class DecimalTypeInfo
- : TraceLoggingTypeInfo<Decimal>
- {
- public override void WriteMetadata(
- TraceLoggingMetadataCollector collector,
- string name,
- EventFieldFormat format)
- {
- collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Double, format));
- }
-
- public override void WriteData(TraceLoggingDataCollector collector, ref decimal value)
- {
- collector.AddScalar((double)value);
- }
- }
-
- /// <summary>
- /// TraceLogging: Type handler for KeyValuePair.
- /// </summary>
- /// <typeparam name="K">Type of the KeyValuePair's Key property.</typeparam>
- /// <typeparam name="V">Type of the KeyValuePair's Value property.</typeparam>
- internal sealed class KeyValuePairTypeInfo<K, V>
- : TraceLoggingTypeInfo<KeyValuePair<K, V>>
+ internal sealed class DecimalTypeInfo : TraceLoggingTypeInfo
{
- private readonly TraceLoggingTypeInfo<K> keyInfo;
- private readonly TraceLoggingTypeInfo<V> valueInfo;
-
- public KeyValuePairTypeInfo(List<Type> recursionCheck)
- {
- this.keyInfo = TraceLoggingTypeInfo<K>.GetInstance(recursionCheck);
- this.valueInfo = TraceLoggingTypeInfo<V>.GetInstance(recursionCheck);
- }
+ public DecimalTypeInfo() : base(typeof(Decimal)) { }
public override void WriteMetadata(
TraceLoggingMetadataCollector collector,
string name,
EventFieldFormat format)
{
- var group = collector.AddGroup(name);
- this.keyInfo.WriteMetadata(group, "Key", EventFieldFormat.Default);
- this.valueInfo.WriteMetadata(group, "Value", format);
- }
-
- public override void WriteData(
- TraceLoggingDataCollector collector,
- ref KeyValuePair<K, V> value)
- {
- var key = value.Key;
- var val = value.Value;
- this.keyInfo.WriteData(collector, ref key);
- this.valueInfo.WriteData(collector, ref val);
+ collector.AddScalar(name, Statics.MakeDataType(TraceLoggingDataType.Double, format));
}
- public override object GetData(object value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- var serializedType = new Dictionary<string, object>();
- var keyValuePair = (KeyValuePair<K, V>) value;
- serializedType.Add("Key", this.keyInfo.GetData(keyValuePair.Key));
- serializedType.Add("Value", this.valueInfo.GetData(keyValuePair.Value));
- return serializedType;
+ collector.AddScalar((double)value.ScalarValue.AsDecimal);
}
}
/// <summary>
/// TraceLogging: Type handler for Nullable.
/// </summary>
- /// <typeparam name="T">Type of the Nullable's Value property.</typeparam>
- internal sealed class NullableTypeInfo<T>
- : TraceLoggingTypeInfo<Nullable<T>>
- where T : struct
+ internal sealed class NullableTypeInfo : TraceLoggingTypeInfo
{
- private readonly TraceLoggingTypeInfo<T> valueInfo;
+ private readonly TraceLoggingTypeInfo valueInfo;
+ private readonly Func<PropertyValue, PropertyValue> hasValueGetter;
+ private readonly Func<PropertyValue, PropertyValue> valueGetter;
- public NullableTypeInfo(List<Type> recursionCheck)
+ public NullableTypeInfo(Type type, List<Type> recursionCheck)
+ : base(type)
{
- this.valueInfo = TraceLoggingTypeInfo<T>.GetInstance(recursionCheck);
+ var typeArgs = type.GenericTypeArguments;
+ Contract.Assert(typeArgs.Length == 1);
+ this.valueInfo = TraceLoggingTypeInfo.GetInstance(typeArgs[0], recursionCheck);
+ this.hasValueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("HasValue"));
+ this.valueGetter = PropertyValue.GetPropertyGetter(type.GetTypeInfo().GetDeclaredProperty("Value"));
}
public override void WriteMetadata(
this.valueInfo.WriteMetadata(group, "Value", format);
}
- public override void WriteData(
- TraceLoggingDataCollector collector,
- ref Nullable<T> value)
+ public override void WriteData(TraceLoggingDataCollector collector, PropertyValue value)
{
- var hasValue = value.HasValue;
+ var hasValue = hasValueGetter(value);
collector.AddScalar(hasValue);
- var val = hasValue ? value.Value : default(T);
- this.valueInfo.WriteData(collector, ref val);
+ var val = hasValue.ScalarValue.AsBoolean ? valueGetter(value) : valueInfo.PropertyValueFactory(Activator.CreateInstance(valueInfo.DataType));
+ this.valueInfo.WriteData(collector, val);
}
}
-
- #endregion
}
using System.Runtime.CompilerServices;
using Encoding = System.Text.Encoding;
+using Microsoft.Reflection;
+
#if ES_BUILD_STANDALONE
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
namespace Microsoft.Diagnostics.Tracing
return TraceLoggingDataType.Int8;
case EventSourceFieldFormat.Unsigned:
return TraceLoggingDataType.UInt8;
-#endif
+#endif
default:
return MakeDataType(native, format);
}
return IntPtrType;
case EventSourceFieldFormat.Unsigned:
return UIntPtrType;
-#endif
+#endif
default:
return MakeDataType(native, format);
}
public static bool IsValueType(Type type)
{
- bool result;
-#if ES_BUILD_PCL
- result = type.GetTypeInfo().IsValueType;
-#else
- result = type.IsValueType;
-#endif
+ bool result = type.IsValueType();
return result;
}
public static bool IsEnum(Type type)
{
- bool result;
-#if ES_BUILD_PCL
- result = type.GetTypeInfo().IsEnum;
-#else
- result = type.IsEnum;
-#endif
+ bool result = type.IsEnum();
return result;
}
public static IEnumerable<PropertyInfo> GetProperties(Type type)
{
- IEnumerable<PropertyInfo> result;
-#if ES_BUILD_PCL
- result = type.GetRuntimeProperties();
-#else
- result = type.GetProperties();
-#endif
+ IEnumerable<PropertyInfo> result = type.GetProperties();
return result;
}
public static MethodInfo GetGetMethod(PropertyInfo propInfo)
{
- MethodInfo result;
-#if ES_BUILD_PCL
- result = propInfo.GetMethod;
-#else
- result = propInfo.GetGetMethod();
-#endif
+ MethodInfo result = propInfo.GetGetMethod();
return result;
}
public static MethodInfo GetDeclaredStaticMethod(Type declaringType, string name)
{
MethodInfo result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
result = declaringType.GetTypeInfo().GetDeclaredMethod(name);
#else
result = declaringType.GetMethod(
Type attributeType)
{
bool result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
result = propInfo.IsDefined(attributeType);
#else
var attributes = propInfo.GetCustomAttributes(
where AttributeType : Attribute
{
AttributeType result = null;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
foreach (var attrib in propInfo.GetCustomAttributes<AttributeType>(false))
{
result = attrib;
where AttributeType : Attribute
{
AttributeType result = null;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
foreach (var attrib in type.GetTypeInfo().GetCustomAttributes<AttributeType>(false))
{
result = attrib;
public static Type[] GetGenericArguments(Type type)
{
-#if ES_BUILD_PCL
- return type.GenericTypeArguments;
-#else
return type.GetGenericArguments();
-#endif
}
public static Type FindEnumerableElementType(Type type)
}
else
{
-#if ES_BUILD_PCL
- var ifaceTypes = type.GetTypeInfo().ImplementedInterfaces;
+#if (ES_BUILD_PCL || PROJECTN)
+ var ifaceTypes = type.GetTypeInfo().ImplementedInterfaces;
#else
var ifaceTypes = type.FindInterfaces(IsGenericMatch, typeof(IEnumerable<>));
#endif
foreach (var ifaceType in ifaceTypes)
{
-#if ES_BUILD_PCL
- if (!IsGenericMatch(ifaceType, typeof(IEnumerable<>)))
- {
- continue;
- }
+#if (ES_BUILD_PCL || PROJECTN)
+ if (!IsGenericMatch(ifaceType, typeof(IEnumerable<>)))
+ {
+ continue;
+ }
#endif
if (elementType != null)
public static bool IsGenericMatch(Type type, object openType)
{
- bool isGeneric;
-#if ES_BUILD_PCL
- isGeneric = type.IsConstructedGenericType;
-#else
- isGeneric = type.IsGenericType;
-#endif
- return isGeneric && type.GetGenericTypeDefinition() == (Type)openType;
+ return type.IsGenericType() && type.GetGenericTypeDefinition() == (Type)openType;
}
public static Delegate CreateDelegate(Type delegateType, MethodInfo methodInfo)
{
Delegate result;
-#if ES_BUILD_PCL
+#if (ES_BUILD_PCL || PROJECTN)
result = methodInfo.CreateDelegate(
delegateType);
#else
return result;
}
- public static TraceLoggingTypeInfo GetTypeInfoInstance(Type dataType, List<Type> recursionCheck)
- {
- TraceLoggingTypeInfo result;
-
- if (dataType == typeof(Int32))
- {
- result = TraceLoggingTypeInfo<Int32>.Instance;
- }
- else if (dataType == typeof(Int64))
- {
- result = TraceLoggingTypeInfo<Int64>.Instance;
- }
- else if (dataType == typeof(String))
- {
- result = TraceLoggingTypeInfo<String>.Instance;
- }
- else
- {
- var getInstanceInfo = Statics.GetDeclaredStaticMethod(
- typeof(TraceLoggingTypeInfo<>).MakeGenericType(dataType),
- "GetInstance");
- var typeInfoObj = getInstanceInfo.Invoke(null, new object[] { recursionCheck });
- result = (TraceLoggingTypeInfo)typeInfoObj;
- }
-
- return result;
- }
-
- public static TraceLoggingTypeInfo<DataType> CreateDefaultTypeInfo<DataType>(
+ public static TraceLoggingTypeInfo CreateDefaultTypeInfo(
+ Type dataType,
List<Type> recursionCheck)
{
TraceLoggingTypeInfo result;
- var dataType = typeof(DataType);
if (recursionCheck.Contains(dataType))
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_RecursiveTypeDefinition"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_RecursiveTypeDefinition"));
}
recursionCheck.Add(dataType);
var eventAttrib = Statics.GetCustomAttribute<EventDataAttribute>(dataType);
if (eventAttrib != null ||
- Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null)
+ Statics.GetCustomAttribute<CompilerGeneratedAttribute>(dataType) != null ||
+ IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
{
var analysis = new TypeAnalysis(dataType, eventAttrib, recursionCheck);
- result = new InvokeTypeInfo<DataType>(analysis);
+ result = new InvokeTypeInfo(dataType, analysis);
}
else if (dataType.IsArray)
{
var elementType = dataType.GetElementType();
if (elementType == typeof(Boolean))
{
- result = new BooleanArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Boolean();
}
else if (elementType == typeof(Byte))
{
- result = new ByteArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Byte();
}
else if (elementType == typeof(SByte))
{
- result = new SByteArrayTypeInfo();
+ result = ScalarArrayTypeInfo.SByte();
}
else if (elementType == typeof(Int16))
{
- result = new Int16ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Int16();
}
else if (elementType == typeof(UInt16))
{
- result = new UInt16ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.UInt16();
}
else if (elementType == typeof(Int32))
{
- result = new Int32ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Int32();
}
else if (elementType == typeof(UInt32))
{
- result = new UInt32ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.UInt32();
}
else if (elementType == typeof(Int64))
{
- result = new Int64ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Int64();
}
else if (elementType == typeof(UInt64))
{
- result = new UInt64ArrayTypeInfo();
+ result = ScalarArrayTypeInfo.UInt64();
}
else if (elementType == typeof(Char))
{
- result = new CharArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Char();
}
else if (elementType == typeof(Double))
{
- result = new DoubleArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Double();
}
else if (elementType == typeof(Single))
{
- result = new SingleArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Single();
}
else if (elementType == typeof(IntPtr))
{
- result = new IntPtrArrayTypeInfo();
+ result = ScalarArrayTypeInfo.IntPtr();
}
else if (elementType == typeof(UIntPtr))
{
- result = new UIntPtrArrayTypeInfo();
+ result = ScalarArrayTypeInfo.UIntPtr();
}
else if (elementType == typeof(Guid))
{
- result = new GuidArrayTypeInfo();
+ result = ScalarArrayTypeInfo.Guid();
}
else
{
- result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
- typeof(ArrayTypeInfo<>).MakeGenericType(elementType),
- GetTypeInfoInstance(elementType, recursionCheck));
+ result = new ArrayTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
}
}
- else if (Statics.IsEnum(dataType))
+ else
{
- var underlyingType = Enum.GetUnderlyingType(dataType);
- if (underlyingType == typeof(Int32))
+ if (Statics.IsEnum(dataType))
+ dataType = Enum.GetUnderlyingType(dataType);
+
+ if (dataType == typeof(String))
{
- result = new EnumInt32TypeInfo<DataType>();
+ result = new StringTypeInfo();
}
- else if (underlyingType == typeof(UInt32))
+ else if (dataType == typeof(Boolean))
{
- result = new EnumUInt32TypeInfo<DataType>();
+ result = ScalarTypeInfo.Boolean();
}
- else if (underlyingType == typeof(Byte))
+ else if (dataType == typeof(Byte))
{
- result = new EnumByteTypeInfo<DataType>();
+ result = ScalarTypeInfo.Byte();
}
- else if (underlyingType == typeof(SByte))
+ else if (dataType == typeof(SByte))
{
- result = new EnumSByteTypeInfo<DataType>();
+ result = ScalarTypeInfo.SByte();
}
- else if (underlyingType == typeof(Int16))
+ else if (dataType == typeof(Int16))
{
- result = new EnumInt16TypeInfo<DataType>();
+ result = ScalarTypeInfo.Int16();
}
- else if (underlyingType == typeof(UInt16))
+ else if (dataType == typeof(UInt16))
{
- result = new EnumUInt16TypeInfo<DataType>();
+ result = ScalarTypeInfo.UInt16();
}
- else if (underlyingType == typeof(Int64))
+ else if (dataType == typeof(Int32))
{
- result = new EnumInt64TypeInfo<DataType>();
+ result = ScalarTypeInfo.Int32();
}
- else if (underlyingType == typeof(UInt64))
+ else if (dataType == typeof(UInt32))
{
- result = new EnumUInt64TypeInfo<DataType>();
+ result = ScalarTypeInfo.UInt32();
}
- else
+ else if (dataType == typeof(Int64))
{
- // Unexpected
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedEnumType", dataType.Name, underlyingType.Name));
+ result = ScalarTypeInfo.Int64();
}
- }
- else if (dataType == typeof(String))
- {
- result = new StringTypeInfo();
- }
- else if (dataType == typeof(Boolean))
- {
- result = new BooleanTypeInfo();
- }
- else if (dataType == typeof(Byte))
- {
- result = new ByteTypeInfo();
- }
- else if (dataType == typeof(SByte))
- {
- result = new SByteTypeInfo();
- }
- else if (dataType == typeof(Int16))
- {
- result = new Int16TypeInfo();
- }
- else if (dataType == typeof(UInt16))
- {
- result = new UInt16TypeInfo();
- }
- else if (dataType == typeof(Int32))
- {
- result = new Int32TypeInfo();
- }
- else if (dataType == typeof(UInt32))
- {
- result = new UInt32TypeInfo();
- }
- else if (dataType == typeof(Int64))
- {
- result = new Int64TypeInfo();
- }
- else if (dataType == typeof(UInt64))
- {
- result = new UInt64TypeInfo();
- }
- else if (dataType == typeof(Char))
- {
- result = new CharTypeInfo();
- }
- else if (dataType == typeof(Double))
- {
- result = new DoubleTypeInfo();
- }
- else if (dataType == typeof(Single))
- {
- result = new SingleTypeInfo();
- }
- else if (dataType == typeof(DateTime))
- {
- result = new DateTimeTypeInfo();
- }
- else if (dataType == typeof(Decimal))
- {
- result = new DecimalTypeInfo();
- }
- else if (dataType == typeof(IntPtr))
- {
- result = new IntPtrTypeInfo();
- }
- else if (dataType == typeof(UIntPtr))
- {
- result = new UIntPtrTypeInfo();
- }
- else if (dataType == typeof(Guid))
- {
- result = new GuidTypeInfo();
- }
- else if (dataType == typeof(TimeSpan))
- {
- result = new TimeSpanTypeInfo();
- }
- else if (dataType == typeof(DateTimeOffset))
- {
- result = new DateTimeOffsetTypeInfo();
- }
- else if (dataType == typeof(EmptyStruct))
- {
- result = new NullTypeInfo<EmptyStruct>();
- }
- else if (IsGenericMatch(dataType, typeof(KeyValuePair<,>)))
- {
- var args = GetGenericArguments(dataType);
- result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
- typeof(KeyValuePairTypeInfo<,>).MakeGenericType(args[0], args[1]),
- recursionCheck);
- }
- else if (IsGenericMatch(dataType, typeof(Nullable<>)))
- {
- var args = GetGenericArguments(dataType);
- result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
- typeof(NullableTypeInfo<>).MakeGenericType(args[0]),
- recursionCheck);
- }
- else
- {
- var elementType = FindEnumerableElementType(dataType);
- if (elementType != null)
+ else if (dataType == typeof(UInt64))
{
- result = (TraceLoggingTypeInfo<DataType>)CreateInstance(
- typeof(EnumerableTypeInfo<,>).MakeGenericType(dataType, elementType),
- GetTypeInfoInstance(elementType, recursionCheck));
+ result = ScalarTypeInfo.UInt64();
+ }
+ else if (dataType == typeof(Char))
+ {
+ result = ScalarTypeInfo.Char();
+ }
+ else if (dataType == typeof(Double))
+ {
+ result = ScalarTypeInfo.Double();
+ }
+ else if (dataType == typeof(Single))
+ {
+ result = ScalarTypeInfo.Single();
+ }
+ else if (dataType == typeof(DateTime))
+ {
+ result = new DateTimeTypeInfo();
+ }
+ else if (dataType == typeof(Decimal))
+ {
+ result = new DecimalTypeInfo();
+ }
+ else if (dataType == typeof(IntPtr))
+ {
+ result = ScalarTypeInfo.IntPtr();
+ }
+ else if (dataType == typeof(UIntPtr))
+ {
+ result = ScalarTypeInfo.UIntPtr();
+ }
+ else if (dataType == typeof(Guid))
+ {
+ result = ScalarTypeInfo.Guid();
+ }
+ else if (dataType == typeof(TimeSpan))
+ {
+ result = new TimeSpanTypeInfo();
+ }
+ else if (dataType == typeof(DateTimeOffset))
+ {
+ result = new DateTimeOffsetTypeInfo();
+ }
+ else if (dataType == typeof(EmptyStruct))
+ {
+ result = new NullTypeInfo();
+ }
+ else if (IsGenericMatch(dataType, typeof(Nullable<>)))
+ {
+ result = new NullableTypeInfo(dataType, recursionCheck);
}
else
{
- throw new ArgumentException(Environment.GetResourceString("EventSource_NonCompliantTypeError", dataType.Name));
+ var elementType = FindEnumerableElementType(dataType);
+ if (elementType != null)
+ {
+ result = new EnumerableTypeInfo(dataType, TraceLoggingTypeInfo.GetInstance(elementType, recursionCheck));
+ }
+ else
+ {
+ throw new ArgumentException(Resources.GetResourceString("EventSource_NonCompliantTypeError", dataType.Name));
+ }
}
}
- return (TraceLoggingTypeInfo<DataType>)result;
+ return result;
}
#endregion
return this;
}
- /// <summary>
- /// Adds a Boolean value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(bool value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(bool));
- }
-
- /// <summary>
- /// Adds an SByte value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- //[CLSCompliant(false)]
- public void AddScalar(sbyte value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(sbyte));
- }
-
- /// <summary>
- /// Adds a Byte value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(byte value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(byte));
- }
-
- /// <summary>
- /// Adds an Int16 value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(short value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(short));
- }
-
- /// <summary>
- /// Adds a UInt16 value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- //[CLSCompliant(false)]
- public void AddScalar(ushort value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(ushort));
- }
-
- /// <summary>
- /// Adds an Int32 value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(int value)
+ public void AddScalar(PropertyValue value)
{
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(int));
- }
-
- /// <summary>
- /// Adds a UInt32 value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- //[CLSCompliant(false)]
- public void AddScalar(uint value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(uint));
+ var scalar = value.ScalarValue;
+ DataCollector.ThreadInstance.AddScalar(&scalar, value.ScalarLength);
}
/// <summary>
}
/// <summary>
- /// Adds a UInt64 value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- //[CLSCompliant(false)]
- public void AddScalar(ulong value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(ulong));
- }
-
- /// <summary>
- /// Adds an IntPtr value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(IntPtr value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, IntPtr.Size);
- }
-
- /// <summary>
- /// Adds a UIntPtr value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- //[CLSCompliant(false)]
- public void AddScalar(UIntPtr value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, UIntPtr.Size);
- }
-
- /// <summary>
- /// Adds a Single value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(float value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(float));
- }
-
- /// <summary>
/// Adds a Double value to the event payload.
/// </summary>
/// <param name="value">Value to be added.</param>
}
/// <summary>
- /// Adds a Char value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(char value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, sizeof(char));
- }
-
- /// <summary>
- /// Adds a Guid value to the event payload.
- /// </summary>
- /// <param name="value">Value to be added.</param>
- public void AddScalar(Guid value)
- {
- DataCollector.ThreadInstance.AddScalar(&value, 16);
- }
-
- /// <summary>
/// Adds a counted String value to the event payload.
/// </summary>
/// <param name="value">
DataCollector.ThreadInstance.AddBinary(value, value == null ? 0 : value.Length * 2);
}
- /// <summary>
- /// Adds an array of Byte values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddBinary(byte[] value)
- {
- DataCollector.ThreadInstance.AddBinary(value, value == null ? 0 : value.Length);
- }
-
- /// <summary>
- /// Adds an array of Boolean values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(bool[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(bool));
- }
-
- /// <summary>
- /// Adds an array of SByte values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- //[CLSCompliant(false)]
- public void AddArray(sbyte[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(sbyte));
- }
-
- /// <summary>
- /// Adds an array of Int16 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(short[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(short));
- }
-
- /// <summary>
- /// Adds an array of UInt16 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- //[CLSCompliant(false)]
- public void AddArray(ushort[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(ushort));
- }
-
- /// <summary>
- /// Adds an array of Int32 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(int[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(int));
- }
-
- /// <summary>
- /// Adds an array of UInt32 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- //[CLSCompliant(false)]
- public void AddArray(uint[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(uint));
- }
-
- /// <summary>
- /// Adds an array of Int64 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(long[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(long));
- }
-
- /// <summary>
- /// Adds an array of UInt64 values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- //[CLSCompliant(false)]
- public void AddArray(ulong[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(ulong));
- }
-
- /// <summary>
- /// Adds an array of IntPtr values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(IntPtr[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, IntPtr.Size);
- }
-
- /// <summary>
- /// Adds an array of UIntPtr values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- //[CLSCompliant(false)]
- public void AddArray(UIntPtr[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, UIntPtr.Size);
- }
-
- /// <summary>
- /// Adds an array of Single values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(float[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(float));
- }
-
- /// <summary>
- /// Adds an array of Double values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(double[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(double));
- }
-
- /// <summary>
- /// Adds an array of Char values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(char[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(char));
- }
-
- /// <summary>
- /// Adds an array of Guid values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddArray(Guid[] value)
- {
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, 16);
- }
-
- /// <summary>
- /// Adds an array of Byte values to the event payload.
- /// </summary>
- /// <param name="value">
- /// Value to be added. A null value is treated as a zero-length array.
- /// </param>
- public void AddCustom(byte[] value)
+ public void AddArray(PropertyValue value, int elementSize)
{
- DataCollector.ThreadInstance.AddArray(value, value == null ? 0 : value.Length, sizeof(byte));
+ Array array = (Array)value.ReferenceValue;
+ DataCollector.ThreadInstance.AddArray(array, array == null ? 0 : array.Length, elementSize);
}
}
}
#if ES_BUILD_STANDALONE
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
+using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
#endif
using System;
}
var options = new EventSourceOptions();
- var data = new EmptyStruct();
- this.WriteImpl(eventName, ref options, ref data, null, null);
+ this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
}
/// <summary>
return;
}
- var data = new EmptyStruct();
- this.WriteImpl(eventName, ref options, ref data, null, null);
+ this.WriteImpl(eventName, ref options, null, null, null, SimpleEventTypes<EmptyStruct>.Instance);
}
/// <summary>
}
var options = new EventSourceOptions();
- this.WriteImpl(eventName, ref options, ref data, null, null);
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
}
/// <summary>
return;
}
- this.WriteImpl(eventName, ref options, ref data, null, null);
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
}
/// <summary>
return;
}
- this.WriteImpl(eventName, ref options, ref data, null, null);
+ this.WriteImpl(eventName, ref options, data, null, null, SimpleEventTypes<T>.Instance);
}
/// <summary>
this.WriteImpl(
eventName,
ref options,
- ref data,
+ data,
pActivity,
- relatedActivityId == Guid.Empty ? null : pRelated);
+ relatedActivityId == Guid.Empty ? null : pRelated,
+ SimpleEventTypes<T>.Instance);
}
}
string eventName,
ref EventSourceOptions options,
TraceLoggingEventTypes eventTypes,
- Guid* activityID,
+ Guid* activityID,
Guid* childActivityID,
params object[] values)
{
/// </param>
[SecuritySafeCritical]
private unsafe void WriteMultiMergeInner(
- string eventName,
- ref EventSourceOptions options,
- TraceLoggingEventTypes eventTypes,
- Guid* activityID,
- Guid* childActivityID,
- params object[] values)
+ string eventName,
+ ref EventSourceOptions options,
+ TraceLoggingEventTypes eventTypes,
+ Guid* activityID,
+ Guid* childActivityID,
+ params object[] values)
{
int identity = 0;
byte level = (options.valuesSet & EventSourceOptions.levelSet) != 0
descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif
try
for (int i = 0; i < eventTypes.typeInfos.Length; i++)
{
- eventTypes.typeInfos[i].WriteObjectData(TraceLoggingDataCollector.Instance, values[i]);
+ var info = eventTypes.typeInfos[i];
+ info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(values[i]));
}
this.WriteEventRaw(
+ eventName,
ref descriptor,
activityID,
childActivityID,
}
this.WriteEventRaw(
+ eventName,
ref descriptor,
activityID,
childActivityID,
}
[SecuritySafeCritical]
- private unsafe void WriteImpl<T>(
+ private unsafe void WriteImpl(
string eventName,
ref EventSourceOptions options,
- ref T data,
+ object data,
Guid* pActivityId,
- Guid* pRelatedActivityId)
+ Guid* pRelatedActivityId,
+ TraceLoggingEventTypes eventTypes)
{
try
{
- var eventTypes = SimpleEventTypes<T>.Instance;
-
fixed (EventSourceOptions* pOptions = &options)
{
EventDescriptor descriptor;
descriptors[1].SetMetadata(pMetadata1, nameInfo.nameMetadata.Length, 1);
descriptors[2].SetMetadata(pMetadata2, eventTypes.typeMetadata.Length, 1);
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
System.Runtime.CompilerServices.RuntimeHelpers.PrepareConstrainedRegions();
#endif
EventOpcode opcode = (EventOpcode)descriptor.Opcode;
pins,
pinCount);
- eventTypes.typeInfo.WriteData(TraceLoggingDataCollector.Instance, ref data);
-
+ var info = eventTypes.typeInfos[0];
+ info.WriteData(TraceLoggingDataCollector.Instance, info.PropertyValueFactory(data));
+
this.WriteEventRaw(
+ eventName,
ref descriptor,
pActivityId,
pRelatedActivityId,
// TODO enable filtering for listeners.
if (m_Dispatchers != null)
{
- var eventData = (EventPayload)(eventTypes.typeInfo.GetData(data));
+ var eventData = (EventPayload)(eventTypes.typeInfos[0].GetData(data));
WriteToAllListeners(eventName, ref descriptor, nameInfo.tags, pActivityId, eventData);
}
}
- catch(Exception ex)
+ catch (Exception ex)
{
if (ex is EventSourceException)
throw;
else
- ThrowEventSourceException(ex);
+ ThrowEventSourceException(eventName, ex);
}
finally
{
if (ex is EventSourceException)
throw;
else
- ThrowEventSourceException(ex);
+ ThrowEventSourceException(eventName, ex);
}
}
DispatchToAllListeners(-1, pActivityId, eventCallbackArgs);
}
-#if !ES_BUILD_PCL
+#if (!ES_BUILD_PCL && !PROJECTN)
[System.Runtime.ConstrainedExecution.ReliabilityContract(
System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState,
System.Runtime.ConstrainedExecution.Cer.Success)]
if (!byte.TryParse(etwTrait, out traitNum))
{
if (etwTrait == "GROUP")
+ {
traitNum = 1;
+ }
else
- throw new ArgumentException(Environment.GetResourceString("UnknownEtwTrait", etwTrait), "traits");
+ {
+ throw new ArgumentException(Resources.GetResourceString("UnknownEtwTrait", etwTrait), "traits");
+ }
}
string value = m_traits[i + 1];
int lenPos = traitMetaData.Count;
}
}
providerMetadata = Statics.MetadataForString(this.Name, 0, traitMetaData.Count, 0);
- int startPos = providerMetadata.Length-traitMetaData.Count;
+ int startPos = providerMetadata.Length - traitMetaData.Count;
foreach (var b in traitMetaData)
providerMetadata[startPos++] = b;
}
if (value[i] != ' ') // Skip spaces between bytes.
{
if (!(i + 1 < value.Length))
- throw new ArgumentException(Environment.GetResourceString("EvenHexDigits"), "traits");
+ {
+ throw new ArgumentException(Resources.GetResourceString("EvenHexDigits"), "traits");
+ }
metaData.Add((byte)(HexDigit(value[i]) * 16 + HexDigit(value[i + 1])));
i++;
}
}
}
else if ('A' <= firstChar || ' ' == firstChar) // Is it alphabetic or space (excludes digits and most punctuation).
+ {
metaData.AddRange(Encoding.UTF8.GetBytes(value));
+ }
else
- throw new ArgumentException(Environment.GetResourceString("IllegalValue", value), "traits");
+ {
+ throw new ArgumentException(Resources.GetResourceString("IllegalValue", value), "traits");
+ }
return metaData.Count - startPos;
}
private static int HexDigit(char c)
{
if ('0' <= c && c <= '9')
+ {
return (c - '0');
+ }
if ('a' <= c)
- c = unchecked((char) (c - ('a' - 'A'))); // Convert to lower case
+ {
+ c = unchecked((char)(c - ('a' - 'A'))); // Convert to lower case
+ }
if ('A' <= c && c <= 'F')
+ {
return (c - 'A' + 10);
- throw new ArgumentException(Environment.GetResourceString("BadHexDigit", c), "traits");
+ }
+
+ throw new ArgumentException(Resources.GetResourceString("BadHexDigit", c), "traits");
}
private NameInfo UpdateDescriptor(
/// TraceLogging: Used when calling EventSource.WriteMultiMerge.
/// Stores the type information to use when writing the event fields.
/// </summary>
- internal class TraceLoggingEventTypes
+ public class TraceLoggingEventTypes
{
internal readonly TraceLoggingTypeInfo[] typeInfos;
internal readonly string name;
var result = new TraceLoggingTypeInfo[paramInfos.Length];
for (int i = 0; i < paramInfos.Length; ++i)
{
- result[i] = Statics.GetTypeInfoInstance(paramInfos[i].ParameterType, recursionCheck);
+ result[i] = TraceLoggingTypeInfo.GetInstance(paramInfos[i].ParameterType, recursionCheck);
}
return result;
var result = new TraceLoggingTypeInfo[types.Length];
for (int i = 0; i < types.Length; i++)
{
- result[i] = Statics.GetTypeInfoInstance(types[i], recursionCheck);
+ result[i] = TraceLoggingTypeInfo.GetInstance(types[i], recursionCheck);
}
return result;
if (this.BeginningBufferedArray)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
}
this.impl.AddScalar(2);
{
if (this.bufferedArrayFieldCount >= 0)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedNestedArraysEnums"));
}
this.bufferedArrayFieldCount = 0;
{
if (this.bufferedArrayFieldCount != 1)
{
- throw new InvalidOperationException(Environment.GetResourceString("EventSource_IncorrentlyAuthoredTypeInfo"));
+ throw new InvalidOperationException(Resources.GetResourceString("EventSource_IncorrentlyAuthoredTypeInfo"));
}
this.bufferedArrayFieldCount = int.MinValue;
{
if (this.BeginningBufferedArray)
{
- throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedCustomSerializedData"));
+ throw new NotSupportedException(Resources.GetResourceString("EventSource_NotSupportedCustomSerializedData"));
}
this.impl.AddScalar(2);
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
+using System.Collections.Generic;
#if !ES_BUILD_AGAINST_DOTNET_V35
using Contract = System.Diagnostics.Contracts.Contract;
private readonly EventOpcode opcode = (EventOpcode)(-1);
private readonly EventTags tags;
private readonly Type dataType;
+ private readonly Func<object, PropertyValue> propertyValueFactory;
internal TraceLoggingTypeInfo(Type dataType)
{
this.name = dataType.Name;
this.dataType = dataType;
+ this.propertyValueFactory = PropertyValue.GetFactory(dataType);
}
internal TraceLoggingTypeInfo(
this.opcode = opcode;
this.tags = tags;
this.dataType = dataType;
+ this.propertyValueFactory = PropertyValue.GetFactory(dataType);
}
/// <summary>
get { return this.dataType; }
}
+ internal Func<object, PropertyValue> PropertyValueFactory
+ {
+ get { return this.propertyValueFactory; }
+ }
+
/// <summary>
/// When overridden by a derived class, writes the metadata (schema) for
/// this type. Note that the sequence of operations in WriteMetadata should be
/// Refer to TraceLoggingTypeInfo.WriteObjectData for information about this
/// method.
/// </param>
- public abstract void WriteObjectData(
+ public abstract void WriteData(
TraceLoggingDataCollector collector,
- object value);
+ PropertyValue value);
/// <summary>
/// Fetches the event parameter data for internal serialization.
{
return value;
}
+
+ [ThreadStatic] // per-thread cache to avoid synchronization
+ private static Dictionary<Type, TraceLoggingTypeInfo> threadCache;
+
+ public static TraceLoggingTypeInfo GetInstance(Type type, List<Type> recursionCheck)
+ {
+ var cache = threadCache ?? (threadCache = new Dictionary<Type, TraceLoggingTypeInfo>());
+
+ TraceLoggingTypeInfo instance;
+ if (!cache.TryGetValue(type, out instance))
+ {
+ if (recursionCheck == null)
+ recursionCheck = new List<Type>();
+ var recursionCheckCount = recursionCheck.Count;
+ instance = Statics.CreateDefaultTypeInfo(type, recursionCheck);
+ cache[type] = instance;
+ recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
+ }
+ return instance;
+ }
}
}
+++ /dev/null
-// Copyright (c) Microsoft. All rights reserved.
-// Licensed under the MIT license. See LICENSE file in the project root for full license information.
-
-using System;
-using System.Collections.Generic;
-using Interlocked = System.Threading.Interlocked;
-
-#if ES_BUILD_STANDALONE
-namespace Microsoft.Diagnostics.Tracing
-#else
-namespace System.Diagnostics.Tracing
-#endif
-{
- /// <summary>
- /// TraceLogging: used when implementing a custom TraceLoggingTypeInfo.
- /// Implementations of this type provide the behaviors that TraceLogging
- /// uses to turn objects into event data. TraceLogging provides default
- /// implementations of this type, but custom implementations can be used
- /// when the default TraceLogging implementation is insufficient.
- /// </summary>
- /// <typeparam name="DataType">
- /// The type of object that is handled by this implementation.
- /// </typeparam>
- internal abstract class TraceLoggingTypeInfo<DataType>
- : TraceLoggingTypeInfo
- {
- private static TraceLoggingTypeInfo<DataType> instance;
-
- /// <summary>
- /// Initializes a new instance of the TraceLoggingTypeInfo class with
- /// default settings. Uses typeof(DataType).Name for EventName and FieldName.
- /// Marks Level and Opcode as unset. Sets Keywords and Traits to 0.
- /// </summary>
- protected TraceLoggingTypeInfo()
- : base(typeof(DataType))
- {
- return;
- }
-
- /// <summary>
- /// Initializes a new instance of the TraceLoggingTypeInfo class, using
- /// the specified values for the EventName, Level, Opcode, Keywords,
- /// FieldName, and Traits properties.
- /// </summary>
- /// <param name="name">
- /// The value for the Name property. Must not contain '\0' characters.
- /// Must not be null.
- /// </param>
- /// <param name="level">
- /// The value for the Level property, or -1 to mark Level as unset.
- /// </param>
- /// <param name="opcode">
- /// The value for the Opcode property, or -1 to mark Opcode as unset.
- /// </param>
- /// <param name="keywords">
- /// The value for the Keywords property.
- /// </param>
- /// <param name="tags">
- /// The value for the Tags property.
- /// </param>
- protected TraceLoggingTypeInfo(
- string name,
- EventLevel level,
- EventOpcode opcode,
- EventKeywords keywords,
- EventTags tags)
- : base(
- typeof(DataType),
- name,
- level,
- opcode,
- keywords,
- tags)
- {
- return;
- }
-
- /// <summary>
- /// Gets the type info that will be used for handling instances of
- /// DataType. If the instance has not already been set, this will
- /// call TrySetInstance(automaticSerializer) to set one, where
- /// automaticSerializer is the value returned from CreateDefault(),
- /// or a do-nothing serializer if CreateDefault() fails.
- /// </summary>
- public static TraceLoggingTypeInfo<DataType> Instance
- {
- get
- {
- return instance ?? InitInstance();
- }
- }
-
- /// <summary>
- /// When overridden by a derived class, writes the data (fields) for an instance
- /// of DataType. Note that the sequence of operations in WriteData should be
- /// essentially identical to the sequence of operations in WriteMetadata. Otherwise,
- /// the metadata and data will not match, which may cause trouble when decoding the
- /// event.
- /// </summary>
- /// <param name="collector">
- /// The object that collects the data for the instance. Data is written by calling
- /// methods on the collector object. Note that if the type contains sub-objects,
- /// the implementation of this method may need to call the WriteData method
- /// for the sub-object, e.g. by calling
- /// TraceLoggingTypeInfo<SubType>.Instance.WriteData(...).
- /// </param>
- /// <param name="value">
- /// The value for which data is to be written.
- /// </param>
- public abstract void WriteData(
- TraceLoggingDataCollector collector,
- ref DataType value);
-
- /// <summary>
- /// When overridden in a derived class, writes the data (fields) for an instance
- /// of DataType. The default implementation of WriteObjectData calls
- /// WriteData(collector, (DataType)value). Normally, you will override WriteData
- /// and not WriteObjectData. However, if your implementation of WriteData has to
- /// cast the value to object, it may be more efficient to reverse this calling
- /// pattern, i.e. to implement WriteObjectData, and then implement WriteData as a
- /// call to WriteObjectData.
- /// </summary>
- /// <param name="collector">
- /// The object that collects the data for the instance. Data is written by calling
- /// methods on the collector object. Note that if the type contains sub-objects,
- /// the implementation of this method may need to call the WriteData method
- /// for the sub-object, e.g. by calling
- /// TraceLoggingTypeInfo<SubType>.Instance.WriteData(...).
- /// </param>
- /// <param name="value">
- /// The value for which data is to be written. Note that this value may be null
- /// (even for value types) if the property from which the value was read is
- /// missing or null.
- /// </param>
- public override void WriteObjectData(
- TraceLoggingDataCollector collector,
- object value)
- {
- var val = value == null ? default(DataType) : (DataType)value;
- this.WriteData(collector, ref val);
- }
-
- internal static TraceLoggingTypeInfo<DataType> GetInstance(List<Type> recursionCheck)
- {
- if (instance == null)
- {
- var recursionCheckCount = recursionCheck.Count;
- var newInstance = Statics.CreateDefaultTypeInfo<DataType>(recursionCheck);
- Interlocked.CompareExchange(ref instance, newInstance, null);
- recursionCheck.RemoveRange(recursionCheckCount, recursionCheck.Count - recursionCheckCount);
- }
-
- return instance;
- }
-
- private static TraceLoggingTypeInfo<DataType> InitInstance()
- {
- return GetInstance(new List<Type>());
- }
- }
-}
}
var propertyType = propertyInfo.PropertyType;
- var propertyTypeInfo = Statics.GetTypeInfoInstance(propertyType, recursionCheck);
+ var propertyTypeInfo = TraceLoggingTypeInfo.GetInstance(propertyType, recursionCheck);
var fieldAttribute = Statics.GetCustomAttribute<EventFieldAttribute>(propertyInfo);
string propertyName =
: propertyInfo.Name;
propertyList.Add(new PropertyAnalysis(
propertyName,
- getterInfo,
+ propertyInfo,
propertyTypeInfo,
fieldAttribute));
}
/// <summary>
/// WindowsEventLevel. Custom values must be in the range from 16 through 255
/// </summary>
- public enum EventLevel {
+ public enum EventLevel
+ {
/// <summary>
/// Log always
/// </summary>
/// <summary>
/// WindowsEventTask. Custom values must be in the range from 1 through 65534
/// </summary>
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
[System.Runtime.CompilerServices.FriendAccessAllowed]
#endif
- public enum EventTask {
+ public enum EventTask
+ {
/// <summary>
/// Undefined task
/// </summary>
/// <summary>
/// EventOpcode. Custom values must be in the range from 11 through 239
/// </summary>
-#if !ES_BUILD_STANDALONE
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
[System.Runtime.CompilerServices.FriendAccessAllowed]
#endif
public enum EventOpcode
/// <summary>
/// EventChannel. Custom values must be in the range from 16 through 255. Currently only predefined values allowed.
/// </summary>
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification="Backwards compatibility")]
-#if !ES_BUILD_STANDALONE
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Backwards compatibility")]
+#if (!ES_BUILD_STANDALONE && !PROJECTN)
[System.Runtime.CompilerServices.FriendAccessAllowed]
#endif
- public enum EventChannel : byte
- {
+ public enum EventChannel : byte
+ {
/// <summary>
/// No channel
/// </summary>
/// EventOpcode
/// </summary>
[Flags]
- public enum EventKeywords : long {
+ public enum EventKeywords : long
+ {
/// <summary>
/// No events.
/// </summary>