You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
350
external/referencesource/mscorlib/system/diagnostics/eventing/StubEnvironment.cs
vendored
Normal file
350
external/referencesource/mscorlib/system/diagnostics/eventing/StubEnvironment.cs
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing.Internal
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing.Internal
|
||||
#endif
|
||||
{
|
||||
#if ES_BUILD_AGAINST_DOTNET_V35
|
||||
using Microsoft.Internal;
|
||||
#endif
|
||||
using Microsoft.Reflection;
|
||||
using System.Reflection;
|
||||
|
||||
internal static class Environment
|
||||
{
|
||||
public static readonly string NewLine = System.Environment.NewLine;
|
||||
|
||||
public static int TickCount
|
||||
{ get { return System.Environment.TickCount; } }
|
||||
|
||||
public static string GetResourceString(string key, params object[] args)
|
||||
{
|
||||
string fmt = rm.GetString(key);
|
||||
if (fmt != null)
|
||||
return string.Format(fmt, args);
|
||||
|
||||
string sargs = String.Empty;
|
||||
foreach(var arg in args)
|
||||
{
|
||||
if (sargs != String.Empty)
|
||||
sargs += ", ";
|
||||
sargs += arg.ToString();
|
||||
}
|
||||
|
||||
return key + " (" + sargs + ")";
|
||||
}
|
||||
|
||||
public static string GetRuntimeResourceString(string key, params object[] args)
|
||||
{
|
||||
return GetResourceString(key, args);
|
||||
}
|
||||
|
||||
private static System.Resources.ResourceManager rm = new System.Resources.ResourceManager("Microsoft.Diagnostics.Tracing.Messages", typeof(Environment).Assembly());
|
||||
}
|
||||
}
|
||||
|
||||
#if ES_BUILD_AGAINST_DOTNET_V35
|
||||
|
||||
namespace Microsoft.Diagnostics.Contracts.Internal
|
||||
{
|
||||
internal class Contract
|
||||
{
|
||||
public static void Assert(bool invariant)
|
||||
{
|
||||
Assert(invariant, string.Empty);
|
||||
}
|
||||
public static void Assert(bool invariant, string message)
|
||||
{
|
||||
if (!invariant)
|
||||
{
|
||||
if (System.Diagnostics.Debugger.IsAttached)
|
||||
System.Diagnostics.Debugger.Break();
|
||||
throw new Exception("Assertion failed: " + message);
|
||||
}
|
||||
}
|
||||
public static void EndContractBlock()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Microsoft.Internal
|
||||
{
|
||||
using System.Text;
|
||||
|
||||
internal static class Tuple
|
||||
{
|
||||
public static Tuple<T1> Create<T1>(T1 item1)
|
||||
{
|
||||
return new Tuple<T1>(item1);
|
||||
}
|
||||
|
||||
public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2)
|
||||
{
|
||||
return new Tuple<T1, T2>(item1, item2);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
internal class Tuple<T1>
|
||||
{
|
||||
private readonly T1 m_Item1;
|
||||
|
||||
public T1 Item1 { get { return m_Item1; } }
|
||||
|
||||
public Tuple(T1 item1)
|
||||
{
|
||||
m_Item1 = item1;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("(");
|
||||
sb.Append(m_Item1);
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class Tuple<T1, T2>
|
||||
{
|
||||
private readonly T1 m_Item1;
|
||||
private readonly T2 m_Item2;
|
||||
|
||||
public T1 Item1 { get { return m_Item1; } }
|
||||
public T2 Item2 { get { return m_Item2; } }
|
||||
|
||||
public Tuple(T1 item1, T2 item2)
|
||||
{
|
||||
m_Item1 = item1;
|
||||
m_Item2 = item2;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append("(");
|
||||
sb.Append(m_Item1);
|
||||
sb.Append(", ");
|
||||
sb.Append(m_Item2);
|
||||
sb.Append(")");
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Microsoft.Reflection
|
||||
{
|
||||
using System.Reflection;
|
||||
|
||||
#if ES_BUILD_PCL
|
||||
[Flags]
|
||||
public enum BindingFlags
|
||||
{
|
||||
DeclaredOnly = 0x02, // Only look at the members declared on the Type
|
||||
Instance = 0x04, // Include Instance members in search
|
||||
Static = 0x08, // Include Static members in search
|
||||
Public = 0x10, // Include Public members in search
|
||||
NonPublic = 0x20, // Include Non-Public members in search
|
||||
}
|
||||
|
||||
public enum TypeCode {
|
||||
Empty = 0, // Null reference
|
||||
Object = 1, // Instance that isn't a value
|
||||
DBNull = 2, // Database null value
|
||||
Boolean = 3, // Boolean
|
||||
Char = 4, // Unicode character
|
||||
SByte = 5, // Signed 8-bit integer
|
||||
Byte = 6, // Unsigned 8-bit integer
|
||||
Int16 = 7, // Signed 16-bit integer
|
||||
UInt16 = 8, // Unsigned 16-bit integer
|
||||
Int32 = 9, // Signed 32-bit integer
|
||||
UInt32 = 10, // Unsigned 32-bit integer
|
||||
Int64 = 11, // Signed 64-bit integer
|
||||
UInt64 = 12, // Unsigned 64-bit integer
|
||||
Single = 13, // IEEE 32-bit float
|
||||
Double = 14, // IEEE 64-bit double
|
||||
Decimal = 15, // Decimal
|
||||
DateTime = 16, // DateTime
|
||||
String = 18, // Unicode character string
|
||||
}
|
||||
#endif
|
||||
static class ReflectionExtensions
|
||||
{
|
||||
#if !ES_BUILD_PCL
|
||||
|
||||
//
|
||||
// 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 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 ReflectionOnly(this Assembly assm) { return assm.ReflectionOnly; }
|
||||
|
||||
#else // ES_BUILD_PCL
|
||||
|
||||
//
|
||||
// Type extension methods
|
||||
//
|
||||
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 Type BaseType(this Type type) { return type.GetTypeInfo().BaseType; }
|
||||
public static Assembly Assembly(this Type type) { return type.GetTypeInfo().Assembly; }
|
||||
|
||||
public static MethodInfo[] GetMethods(this Type type, BindingFlags flags)
|
||||
{
|
||||
// Minimal implementation to cover only the cases we need
|
||||
System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
|
||||
System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic)) == 0);
|
||||
Func<MethodInfo, bool> visFilter;
|
||||
Func<MethodInfo, bool> instFilter;
|
||||
switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
case 0: visFilter = mi => false; break;
|
||||
case BindingFlags.Public: visFilter = mi => mi.IsPublic; break;
|
||||
case BindingFlags.NonPublic: visFilter = mi => !mi.IsPublic; break;
|
||||
default: visFilter = mi => true; break;
|
||||
}
|
||||
switch (flags & (BindingFlags.Instance | BindingFlags.Static))
|
||||
{
|
||||
case 0: instFilter = mi => false; break;
|
||||
case BindingFlags.Instance: instFilter = mi => !mi.IsStatic; break;
|
||||
case BindingFlags.Static: instFilter = mi => mi.IsStatic; break;
|
||||
default: instFilter = mi => true; break;
|
||||
}
|
||||
List<MethodInfo> methodInfos = new List<MethodInfo>();
|
||||
foreach (var declaredMethod in type.GetTypeInfo().DeclaredMethods)
|
||||
{
|
||||
if (visFilter(declaredMethod) && instFilter(declaredMethod))
|
||||
methodInfos.Add(declaredMethod);
|
||||
}
|
||||
return methodInfos.ToArray();
|
||||
}
|
||||
public static FieldInfo[] GetFields(this Type type, BindingFlags flags)
|
||||
{
|
||||
// Minimal implementation to cover only the cases we need
|
||||
System.Diagnostics.Debug.Assert((flags & BindingFlags.DeclaredOnly) != 0);
|
||||
System.Diagnostics.Debug.Assert((flags & ~(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) == 0);
|
||||
Func<FieldInfo, bool> visFilter;
|
||||
Func<FieldInfo, bool> instFilter;
|
||||
switch (flags & (BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
case 0: visFilter = fi => false; break;
|
||||
case BindingFlags.Public: visFilter = fi => fi.IsPublic; break;
|
||||
case BindingFlags.NonPublic: visFilter = fi => !fi.IsPublic; break;
|
||||
default: visFilter = fi => true; break;
|
||||
}
|
||||
switch (flags & (BindingFlags.Instance | BindingFlags.Static))
|
||||
{
|
||||
case 0: instFilter = fi => false; break;
|
||||
case BindingFlags.Instance: instFilter = fi => !fi.IsStatic; break;
|
||||
case BindingFlags.Static: instFilter = fi => fi.IsStatic; break;
|
||||
default: instFilter = fi => true; break;
|
||||
}
|
||||
List<FieldInfo> fieldInfos = new List<FieldInfo>();
|
||||
foreach (var declaredField in type.GetTypeInfo().DeclaredFields)
|
||||
{
|
||||
if (visFilter(declaredField) && instFilter(declaredField))
|
||||
fieldInfos.Add(declaredField);
|
||||
}
|
||||
return fieldInfos.ToArray();
|
||||
}
|
||||
public static Type GetNestedType(this Type type, string nestedTypeName)
|
||||
{
|
||||
TypeInfo ti = null;
|
||||
foreach(var nt in type.GetTypeInfo().DeclaredNestedTypes)
|
||||
{
|
||||
if (nt.Name == nestedTypeName)
|
||||
{
|
||||
ti = nt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ti == null ? null : ti.AsType();
|
||||
}
|
||||
public static TypeCode GetTypeCode(this Type type)
|
||||
{
|
||||
if (type == typeof(bool)) return TypeCode.Boolean;
|
||||
else if (type == typeof(byte)) return TypeCode.Byte;
|
||||
else if (type == typeof(char)) return TypeCode.Char;
|
||||
else if (type == typeof(ushort)) return TypeCode.UInt16;
|
||||
else if (type == typeof(uint)) return TypeCode.UInt32;
|
||||
else if (type == typeof(ulong)) return TypeCode.UInt64;
|
||||
else if (type == typeof(sbyte)) return TypeCode.SByte;
|
||||
else if (type == typeof(short)) return TypeCode.Int16;
|
||||
else if (type == typeof(int)) return TypeCode.Int32;
|
||||
else if (type == typeof(long)) return TypeCode.Int64;
|
||||
else if (type == typeof(string)) return TypeCode.String;
|
||||
else if (type == typeof(float)) return TypeCode.Single;
|
||||
else if (type == typeof(double)) return TypeCode.Double;
|
||||
else if (type == typeof(DateTime)) return TypeCode.DateTime;
|
||||
else if (type == (typeof(Decimal))) return TypeCode.Decimal;
|
||||
else return TypeCode.Object;
|
||||
}
|
||||
|
||||
//
|
||||
// FieldInfo extension methods
|
||||
//
|
||||
public static object GetRawConstantValue(this FieldInfo fi)
|
||||
{ return fi.GetValue(null); }
|
||||
|
||||
//
|
||||
// Assembly extension methods
|
||||
//
|
||||
public static bool ReflectionOnly(this Assembly assm)
|
||||
{
|
||||
// In PCL we can't load in reflection-only context
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Defining some no-ops in PCL builds
|
||||
#if ES_BUILD_PCL
|
||||
namespace System.Security
|
||||
{
|
||||
class SuppressUnmanagedCodeSecurityAttribute : Attribute { }
|
||||
|
||||
enum SecurityAction { Demand }
|
||||
}
|
||||
namespace System.Security.Permissions
|
||||
{
|
||||
class HostProtectionAttribute : Attribute { public bool MayLeakOnAbort { get; set; } }
|
||||
class PermissionSetAttribute : Attribute
|
||||
{
|
||||
public PermissionSetAttribute(System.Security.SecurityAction action) { }
|
||||
public bool Unrestricted { get; set; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
60
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ArrayTypeInfo.cs
vendored
Normal file
60
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ArrayTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
internal sealed class ArrayTypeInfo<ElementType>
|
||||
: TraceLoggingTypeInfo<ElementType[]>
|
||||
{
|
||||
private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
|
||||
|
||||
public ArrayTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
|
||||
{
|
||||
this.elementInfo = elementInfo;
|
||||
}
|
||||
|
||||
public override void WriteMetadata(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
collector.BeginBufferedArray();
|
||||
this.elementInfo.WriteMetadata(collector, name, format);
|
||||
collector.EndBufferedArray();
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref ElementType[] value)
|
||||
{
|
||||
var bookmark = collector.BeginBufferedArray();
|
||||
|
||||
var count = 0;
|
||||
if (value != null)
|
||||
{
|
||||
count = value.Length;
|
||||
for (int i = 0; i < value.Length; i++)
|
||||
{
|
||||
this.elementInfo.WriteData(collector, ref value[i]);
|
||||
}
|
||||
}
|
||||
|
||||
collector.EndBufferedArray(bookmark, count);
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
var array = (ElementType[])value;
|
||||
var serializedArray = new object[array.Length];
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
serializedArray[i] = this.elementInfo.GetData(array[i]);
|
||||
}
|
||||
return serializedArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
123
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSet.cs
vendored
Normal file
123
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSet.cs
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using Interlocked = System.Threading.Interlocked;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: A very simple lock-free add-only dictionary.
|
||||
/// Warning: this is a copy-by-value type. Copying performs a snapshot.
|
||||
/// Accessing a readonly field always makes a copy of the field, so the
|
||||
/// GetOrAdd method will not work as expected if called on a readonly field.
|
||||
/// </summary>
|
||||
/// <typeparam name="KeyType">
|
||||
/// The type of the key, used for TryGet.
|
||||
/// </typeparam>
|
||||
/// <typeparam name="ItemType">
|
||||
/// The type of the item, used for GetOrAdd.
|
||||
/// </typeparam>
|
||||
internal struct ConcurrentSet<KeyType, ItemType>
|
||||
where ItemType : ConcurrentSetItem<KeyType, ItemType>
|
||||
{
|
||||
private ItemType[] items;
|
||||
|
||||
public ItemType TryGet(KeyType key)
|
||||
{
|
||||
ItemType item;
|
||||
var oldItems = this.items;
|
||||
|
||||
if (oldItems != null)
|
||||
{
|
||||
var lo = 0;
|
||||
var hi = oldItems.Length;
|
||||
do
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
item = oldItems[i];
|
||||
|
||||
int cmp = item.Compare(key);
|
||||
if (cmp == 0)
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
lo = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = i;
|
||||
}
|
||||
}
|
||||
while (lo != hi);
|
||||
}
|
||||
|
||||
item = null;
|
||||
|
||||
Done:
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public ItemType GetOrAdd(ItemType newItem)
|
||||
{
|
||||
ItemType item;
|
||||
var oldItems = this.items;
|
||||
ItemType[] newItems;
|
||||
|
||||
Retry:
|
||||
|
||||
if (oldItems == null)
|
||||
{
|
||||
newItems = new ItemType[] { newItem };
|
||||
}
|
||||
else
|
||||
{
|
||||
var lo = 0;
|
||||
var hi = oldItems.Length;
|
||||
do
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
item = oldItems[i];
|
||||
|
||||
int cmp = item.Compare(newItem);
|
||||
if (cmp == 0)
|
||||
{
|
||||
goto Done;
|
||||
}
|
||||
else if (cmp < 0)
|
||||
{
|
||||
lo = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = i;
|
||||
}
|
||||
}
|
||||
while (lo != hi);
|
||||
|
||||
int oldLength = oldItems.Length;
|
||||
newItems = new ItemType[oldLength + 1];
|
||||
Array.Copy(oldItems, 0, newItems, 0, lo);
|
||||
newItems[lo] = newItem;
|
||||
Array.Copy(oldItems, lo, newItems, lo + 1, oldLength - lo);
|
||||
}
|
||||
|
||||
newItems = Interlocked.CompareExchange(ref this.items, newItems, oldItems);
|
||||
if (oldItems != newItems)
|
||||
{
|
||||
oldItems = newItems;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
item = newItem;
|
||||
|
||||
Done:
|
||||
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSetItem.cs
vendored
Normal file
21
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/ConcurrentSetItem.cs
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Abstract base class that must be inherited by items in a
|
||||
/// ConcurrentSet.
|
||||
/// </summary>
|
||||
/// <typeparam name="KeyType">Type of the set's key.</typeparam>
|
||||
/// <typeparam name="ItemType">Type of the derived class.</typeparam>
|
||||
internal abstract class ConcurrentSetItem<KeyType, ItemType>
|
||||
where ItemType : ConcurrentSetItem<KeyType, ItemType>
|
||||
{
|
||||
public abstract int Compare(ItemType other);
|
||||
public abstract int Compare(KeyType key);
|
||||
}
|
||||
}
|
||||
315
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/DataCollector.cs
vendored
Normal file
315
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/DataCollector.cs
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: This is the implementation of the DataCollector
|
||||
/// functionality. To enable safe access to the DataCollector from
|
||||
/// untrusted code, there is one thread-local instance of this structure
|
||||
/// per thread. The instance must be Enabled before any data is written to
|
||||
/// it. The instance must be Finished before the data is passed to
|
||||
/// EventWrite. The instance must be Disabled before the arrays referenced
|
||||
/// by the pointers are freed or unpinned.
|
||||
/// </summary>
|
||||
[SecurityCritical]
|
||||
internal unsafe struct DataCollector
|
||||
{
|
||||
[ThreadStatic]
|
||||
internal static DataCollector ThreadInstance;
|
||||
|
||||
private byte* scratchEnd;
|
||||
private EventSource.EventData* datasEnd;
|
||||
private GCHandle* pinsEnd;
|
||||
private EventSource.EventData* datasStart;
|
||||
private byte* scratch;
|
||||
private EventSource.EventData* datas;
|
||||
private GCHandle* pins;
|
||||
private byte[] buffer;
|
||||
private int bufferPos;
|
||||
private int bufferNesting; // We may merge many fields int a single blob. If we are doing this we increment this.
|
||||
private bool writingScalars;
|
||||
|
||||
internal void Enable(
|
||||
byte* scratch,
|
||||
int scratchSize,
|
||||
EventSource.EventData* datas,
|
||||
int dataCount,
|
||||
GCHandle* pins,
|
||||
int pinCount)
|
||||
{
|
||||
this.datasStart = datas;
|
||||
this.scratchEnd = scratch + scratchSize;
|
||||
this.datasEnd = datas + dataCount;
|
||||
this.pinsEnd = pins + pinCount;
|
||||
this.scratch = scratch;
|
||||
this.datas = datas;
|
||||
this.pins = pins;
|
||||
this.writingScalars = false;
|
||||
}
|
||||
|
||||
internal void Disable()
|
||||
{
|
||||
this = new DataCollector();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Completes the list of scalars. Finish must be called before the data
|
||||
/// descriptor array is passed to EventWrite.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A pointer to the next unused data descriptor, or datasEnd if they were
|
||||
/// all used. (Descriptors may be unused if a string or array was null.)
|
||||
/// </returns>
|
||||
internal EventSource.EventData* Finish()
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
return this.datas;
|
||||
}
|
||||
|
||||
internal void AddScalar(void* value, int size)
|
||||
{
|
||||
var pb = (byte*)value;
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
var scratchOld = this.scratch;
|
||||
var scratchNew = scratchOld + size;
|
||||
if (this.scratchEnd < scratchNew)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_AddScalarOutOfRange"));
|
||||
}
|
||||
|
||||
this.ScalarsBegin();
|
||||
this.scratch = scratchNew;
|
||||
|
||||
for (int i = 0; i != size; i++)
|
||||
{
|
||||
scratchOld[i] = pb[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
for (int i = 0; i != size; i++, oldPos++)
|
||||
{
|
||||
this.buffer[oldPos] = pb[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddBinary(string value, int size)
|
||||
{
|
||||
if (size > ushort.MaxValue)
|
||||
{
|
||||
size = ushort.MaxValue - 1;
|
||||
}
|
||||
|
||||
if (this.bufferNesting != 0)
|
||||
{
|
||||
this.EnsureBuffer(size + 2);
|
||||
}
|
||||
|
||||
this.AddScalar(&size, 2);
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.PinArray(value, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
fixed (void* p = value)
|
||||
{
|
||||
Marshal.Copy((IntPtr)p, this.buffer, oldPos, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void AddBinary(Array value, int size)
|
||||
{
|
||||
this.AddArray(value, size, 1);
|
||||
}
|
||||
|
||||
internal void AddArray(Array value, int length, int itemSize)
|
||||
{
|
||||
if (length > ushort.MaxValue)
|
||||
{
|
||||
length = ushort.MaxValue;
|
||||
}
|
||||
|
||||
var size = length * itemSize;
|
||||
if (this.bufferNesting != 0)
|
||||
{
|
||||
this.EnsureBuffer(size + 2);
|
||||
}
|
||||
|
||||
this.AddScalar(&length, 2);
|
||||
|
||||
if (length != 0)
|
||||
{
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.PinArray(value, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldPos = this.bufferPos;
|
||||
this.bufferPos = checked(this.bufferPos + size);
|
||||
this.EnsureBuffer();
|
||||
Buffer.BlockCopy(value, 0, this.buffer, oldPos, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the start of a non-blittable array or enumerable.
|
||||
/// </summary>
|
||||
/// <returns>Bookmark to be passed to EndBufferedArray.</returns>
|
||||
internal int BeginBufferedArray()
|
||||
{
|
||||
this.BeginBuffered();
|
||||
this.bufferPos += 2; // Reserve space for the array length (filled in by EndEnumerable)
|
||||
return this.bufferPos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the end of a non-blittable array or enumerable.
|
||||
/// </summary>
|
||||
/// <param name="bookmark">The value returned by BeginBufferedArray.</param>
|
||||
/// <param name="count">The number of items in the array.</param>
|
||||
internal void EndBufferedArray(int bookmark, int count)
|
||||
{
|
||||
this.EnsureBuffer();
|
||||
this.buffer[bookmark - 2] = unchecked((byte)count);
|
||||
this.buffer[bookmark - 1] = unchecked((byte)(count >> 8));
|
||||
this.EndBuffered();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the start of dynamically-buffered data.
|
||||
/// </summary>
|
||||
internal void BeginBuffered()
|
||||
{
|
||||
this.ScalarsEnd();
|
||||
this.bufferNesting += 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks the end of dynamically-buffered data.
|
||||
/// </summary>
|
||||
internal void EndBuffered()
|
||||
{
|
||||
this.bufferNesting -= 1;
|
||||
|
||||
if (this.bufferNesting == 0)
|
||||
{
|
||||
/*
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
this.EnsureBuffer();
|
||||
this.PinArray(this.buffer, this.bufferPos);
|
||||
this.buffer = null;
|
||||
this.bufferPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBuffer()
|
||||
{
|
||||
var required = this.bufferPos;
|
||||
if (this.buffer == null || this.buffer.Length < required)
|
||||
{
|
||||
this.GrowBuffer(required);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureBuffer(int additionalSize)
|
||||
{
|
||||
var required = this.bufferPos + additionalSize;
|
||||
if (this.buffer == null || this.buffer.Length < required)
|
||||
{
|
||||
this.GrowBuffer(required);
|
||||
}
|
||||
}
|
||||
|
||||
private void GrowBuffer(int required)
|
||||
{
|
||||
var newSize = this.buffer == null ? 64 : this.buffer.Length;
|
||||
|
||||
do
|
||||
{
|
||||
newSize *= 2;
|
||||
}
|
||||
while (newSize < required);
|
||||
|
||||
Array.Resize(ref this.buffer, newSize);
|
||||
}
|
||||
|
||||
private void PinArray(object value, int size)
|
||||
{
|
||||
var pinsTemp = this.pins;
|
||||
if (this.pinsEnd <= pinsTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_PinArrayOutOfRange"));
|
||||
}
|
||||
|
||||
var datasTemp = this.datas;
|
||||
if (this.datasEnd <= datasTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
|
||||
}
|
||||
|
||||
this.pins = pinsTemp + 1;
|
||||
this.datas = datasTemp + 1;
|
||||
|
||||
*pinsTemp = GCHandle.Alloc(value, GCHandleType.Pinned);
|
||||
datasTemp->m_Ptr = (long)(ulong)(UIntPtr)(void*)pinsTemp->AddrOfPinnedObject();
|
||||
datasTemp->m_Size = size;
|
||||
}
|
||||
|
||||
private void ScalarsBegin()
|
||||
{
|
||||
if (!this.writingScalars)
|
||||
{
|
||||
var datasTemp = this.datas;
|
||||
if (this.datasEnd <= datasTemp)
|
||||
{
|
||||
throw new IndexOutOfRangeException(Environment.GetResourceString("EventSource_DataDescriptorsOutOfRange"));
|
||||
}
|
||||
|
||||
datasTemp->m_Ptr = (long)(ulong)(UIntPtr)this.scratch;
|
||||
this.writingScalars = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ScalarsEnd()
|
||||
{
|
||||
if (this.writingScalars)
|
||||
{
|
||||
var datasTemp = this.datas;
|
||||
datasTemp->m_Size = checked((int)(this.scratch - (byte*)datasTemp->m_Ptr));
|
||||
this.datas = datasTemp + 1;
|
||||
this.writingScalars = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EmptyStruct.cs
vendored
Normal file
13
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EmptyStruct.cs
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Empty struct indicating no payload data.
|
||||
/// </summary>
|
||||
internal struct EmptyStruct
|
||||
{
|
||||
}
|
||||
}
|
||||
42
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumHelper.cs
vendored
Normal file
42
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumHelper.cs
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides support for casting enums to their underlying type
|
||||
/// from within generic context.
|
||||
/// </summary>
|
||||
/// <typeparam name="UnderlyingType">
|
||||
/// The underlying type of the enum.
|
||||
/// </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);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumerableTypeInfo.cs
vendored
Normal file
62
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EnumerableTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
internal sealed class EnumerableTypeInfo<IterableType, ElementType>
|
||||
: TraceLoggingTypeInfo<IterableType>
|
||||
where IterableType : IEnumerable<ElementType>
|
||||
{
|
||||
private readonly TraceLoggingTypeInfo<ElementType> elementInfo;
|
||||
|
||||
public EnumerableTypeInfo(TraceLoggingTypeInfo<ElementType> elementInfo)
|
||||
{
|
||||
this.elementInfo = elementInfo;
|
||||
}
|
||||
|
||||
public override void WriteMetadata(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
collector.BeginBufferedArray();
|
||||
this.elementInfo.WriteMetadata(collector, name, format);
|
||||
collector.EndBufferedArray();
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref IterableType value)
|
||||
{
|
||||
var bookmark = collector.BeginBufferedArray();
|
||||
|
||||
var count = 0;
|
||||
if (value != null)
|
||||
{
|
||||
foreach (var element in value)
|
||||
{
|
||||
var el = element;
|
||||
this.elementInfo.WriteData(collector, ref el);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
collector.EndBufferedArray(bookmark, count);
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
var iterType = (IterableType)value;
|
||||
List<object> serializedEnumerable = new List<object>();
|
||||
foreach (var element in iterType)
|
||||
{
|
||||
serializedEnumerable.Add(elementInfo.GetData(element));
|
||||
}
|
||||
return serializedEnumerable.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
142
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventDataAttribute.cs
vendored
Normal file
142
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventDataAttribute.cs
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when authoring types that will be passed to EventSource.Write.
|
||||
/// EventSource.Write<T> only works when T is either an anonymous type
|
||||
/// or a type with an [EventData] attribute. In addition, the properties
|
||||
/// of T must be supported property types. Supported property types include
|
||||
/// simple built-in types (int, string, Guid, DateTime, DateTimeOffset,
|
||||
/// KeyValuePair, etc.), anonymous types that only contain supported types,
|
||||
/// types with an [EventData] attribute, arrays of the above, and IEnumerable
|
||||
/// of the above.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false)]
|
||||
public class EventDataAttribute
|
||||
: Attribute
|
||||
{
|
||||
private EventLevel level = (EventLevel)(-1);
|
||||
private EventOpcode opcode = (EventOpcode)(-1);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to use if this type is used for an
|
||||
/// implicitly-named event or an implicitly-named property.
|
||||
///
|
||||
/// Example 1:
|
||||
///
|
||||
/// EventSource.Write(null, new T()); // implicitly-named event
|
||||
///
|
||||
/// The name of the event will be determined as follows:
|
||||
///
|
||||
/// if (T has an EventData attribute and attribute.Name != null)
|
||||
/// eventName = attribute.Name;
|
||||
/// else
|
||||
/// eventName = typeof(T).Name;
|
||||
///
|
||||
/// Example 2:
|
||||
///
|
||||
/// EventSource.Write(name, new { _1 = new T() }); // implicitly-named field
|
||||
///
|
||||
/// The name of the field will be determined as follows:
|
||||
///
|
||||
/// if (T has an EventData attribute and attribute.Name != null)
|
||||
/// fieldName = attribute.Name;
|
||||
/// else
|
||||
/// fieldName = typeof(T).Name;
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to use for the event.
|
||||
/// Invalid levels (outside the range 0..255) are treated as unset.
|
||||
/// Note that the Level attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Level from the sub-object's attribute
|
||||
/// can affect the event's level.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the level of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// if (options.Level has been set)
|
||||
/// eventLevel = options.Level;
|
||||
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Level has been set)
|
||||
/// eventLevel = attribute.Level;
|
||||
/// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Level has been set)
|
||||
/// eventLevel = attribute.Level;
|
||||
/// else
|
||||
/// eventLevel = EventLevel.LogAlways;
|
||||
/// </summary>
|
||||
internal EventLevel Level
|
||||
{
|
||||
get { return this.level; }
|
||||
set { this.level = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the opcode to use for the event.
|
||||
/// Invalid opcodes (outside the range 0..255) are treated as unset.
|
||||
/// Note that the Opcode attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Opcode from the sub-object's attribute
|
||||
/// can affect the event's opcode.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the opcode of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// if (options.Opcode has been set)
|
||||
/// eventOpcode = options.Opcode;
|
||||
/// else if (data.GetType() has a TraceLoggingEvent attribute and attribute.Opcode has been set)
|
||||
/// eventOpcode = attribute.Opcode;
|
||||
/// else if (a field/property contained in data has a TraceLoggingEvent attribute and attribute.Opcode has been set)
|
||||
/// eventOpcode = attribute.Opcode;
|
||||
/// else
|
||||
/// eventOpcode = EventOpcode.Info;
|
||||
/// </summary>
|
||||
internal EventOpcode Opcode
|
||||
{
|
||||
get { return this.opcode; }
|
||||
set { this.opcode = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keywords to use for the event.
|
||||
/// Note that the Keywords attribute can bubble-up, i.e. if a type contains
|
||||
/// a sub-object (a field or property), and the sub-object's type has a
|
||||
/// TraceLoggingEvent attribute, the Keywords from the sub-object's attribute
|
||||
/// can affect the event's keywords.
|
||||
///
|
||||
/// Example: for EventSource.Write(name, options, data), the keywords of the
|
||||
/// event will be determined as follows:
|
||||
///
|
||||
/// eventKeywords = options.Keywords;
|
||||
/// if (data.GetType() has a TraceLoggingEvent attribute)
|
||||
/// eventKeywords |= attribute.Keywords;
|
||||
/// if (a field/property contained in data has a TraceLoggingEvent attribute)
|
||||
/// eventKeywords |= attribute.Keywords;
|
||||
/// </summary>
|
||||
internal EventKeywords Keywords
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flags for an event. These flags are ignored by ETW,
|
||||
/// but can have meaning to the event consumer.
|
||||
/// </summary>
|
||||
internal EventTags Tags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Tags are flags that are not interpreted by EventSource but are passed along
|
||||
/// to the EventListener. The EventListener determines the semantics of the flags.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum EventFieldTags
|
||||
{
|
||||
/// <summary>
|
||||
/// No special traits are added to the field.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/* Bits below 0x10000 are available for any use by the provider. */
|
||||
/* Bits at or above 0x10000 are reserved for definition by Microsoft. */
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TraceLogging: used when authoring types that will be passed to EventSource.Write.
|
||||
/// Controls how a field or property is handled when it is written as a
|
||||
/// field in a TraceLogging event. Apply this attribute to a field or
|
||||
/// property if the default handling is not correct. (Apply the
|
||||
/// TraceLoggingIgnore attribute if the property should not be
|
||||
/// included as a field in the event.)
|
||||
/// The default for Name is null, which means that the name of the
|
||||
/// underlying field or property will be used as the event field's name.
|
||||
/// The default for PiiTag is 0, which means that the event field does not
|
||||
/// contain personally-identifiable information.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EventFieldAttribute
|
||||
: Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// User defined options for the field. These are not interpreted by the EventSource
|
||||
/// but are available to the Listener. See EventFieldSettings for details
|
||||
/// </summary>
|
||||
public EventFieldTags Tags
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to use for the field. This defaults to null.
|
||||
/// If null, the name of the corresponding property will be used
|
||||
/// as the event field's name.
|
||||
///
|
||||
|
||||
internal string Name
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a field formatting hint.
|
||||
/// </summary>
|
||||
public EventFieldFormat Format
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldFormat.cs
vendored
Normal file
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventFieldFormat.cs
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a hint that may be used by an event listener when formatting
|
||||
/// an event field for display. Note that the event listener may ignore the
|
||||
/// hint if it does not recognize a particular combination of type and format.
|
||||
/// Similar to TDH_OUTTYPE.
|
||||
/// </summary>
|
||||
public enum EventFieldFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Field receives default formatting based on the field's underlying type.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should not be displayed.
|
||||
/// </summary>
|
||||
NoPrint = 1,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as character or string data.
|
||||
/// Typically applied to 8-bit or 16-bit integers.
|
||||
/// This is the default format for String and Char types.
|
||||
/// </summary>
|
||||
String = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as boolean data. Typically applied to 8-bit
|
||||
/// or 32-bit integers. This is the default format for the Boolean type.
|
||||
/// </summary>
|
||||
Boolean = 3,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as hexadecimal data. Typically applied to
|
||||
/// integer types.
|
||||
/// </summary>
|
||||
Hexadecimal = 4,
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a process identifier. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
ProcessId = 5,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as a thread identifier. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
ThreadId = 6,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet port. Typically applied to 16-bit integer
|
||||
/// types.
|
||||
/// </summary>
|
||||
Port = 7,
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet Protocol v4 address. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
Ipv4Address = 8,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an Internet Protocol v6 address. Typically applied to
|
||||
/// byte[] types.
|
||||
/// </summary>
|
||||
Ipv6Address = 9,
|
||||
/// <summary>
|
||||
/// Field should be formatted as a SOCKADDR. Typically applied to byte[] types.
|
||||
/// </summary>
|
||||
SocketAddress = 10,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as XML string data. Typically applied to
|
||||
/// strings or arrays of 8-bit or 16-bit integers.
|
||||
/// </summary>
|
||||
Xml = 11,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as JSON string data. Typically applied to
|
||||
/// strings or arrays of 8-bit or 16-bit integers.
|
||||
/// </summary>
|
||||
Json = 12,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a Win32 error code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
Win32Error = 13,
|
||||
|
||||
/// <summary>
|
||||
/// Field should be formatted as an NTSTATUS code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
NTStatus = 14,
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Field should be formatted as an HRESULT code. Typically applied to
|
||||
/// 32-bit integer types.
|
||||
/// </summary>
|
||||
HResult = 15,
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Field should be formatted as a FILETIME. Typically applied to 64-bit
|
||||
/// integer types. This is the default format for DateTime types.
|
||||
/// </summary>
|
||||
FileTime = 16,
|
||||
/// <summary>
|
||||
/// When applied to a numeric type, indicates that the type should be formatted
|
||||
/// as a signed integer. This is the default format for signed integer types.
|
||||
/// </summary>
|
||||
Signed = 17,
|
||||
|
||||
/// <summary>
|
||||
/// When applied to a numeric type, indicates that the type should be formatted
|
||||
/// as an unsigned integer. This is the default format for unsigned integer types.
|
||||
/// </summary>
|
||||
Unsigned = 18,
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when authoring types that will be passed to EventSource.Write.
|
||||
/// By default, EventSource.Write will write all of an object's public
|
||||
/// properties to the event payload. Apply [EventIgnore] to a public
|
||||
/// property to prevent EventSource.Write from including the property in
|
||||
/// the event.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class EventIgnoreAttribute
|
||||
: Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
147
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventPayload.cs
vendored
Normal file
147
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventPayload.cs
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
#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>
|
||||
/// EventPayload class holds the list of parameters and their corresponding values for user defined types passed to
|
||||
/// EventSource APIs.
|
||||
/// Preserving the order of the elements as they were found inside user defined types is the most important characteristic of this class.
|
||||
/// </summary>
|
||||
internal class EventPayload : IDictionary<string, object>
|
||||
{
|
||||
internal EventPayload(List<string> payloadNames, List<object> payloadValues)
|
||||
{
|
||||
Contract.Assert(payloadNames.Count == payloadValues.Count);
|
||||
|
||||
m_names = payloadNames;
|
||||
m_values = payloadValues;
|
||||
}
|
||||
|
||||
public ICollection<string> Keys { get { return m_names; } }
|
||||
public ICollection<object> Values { get { return m_values; } }
|
||||
|
||||
public object this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
int position = 0;
|
||||
foreach(var name in m_names)
|
||||
{
|
||||
if (name == key)
|
||||
{
|
||||
return m_values[position];
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
throw new System.Collections.Generic.KeyNotFoundException();
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(string key, object value)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, object> payloadEntry)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, object> entry)
|
||||
{
|
||||
return ContainsKey(entry.Key);
|
||||
}
|
||||
|
||||
public bool ContainsKey(string key)
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
foreach (var item in m_names)
|
||||
{
|
||||
if (item == key)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int Count { get { return m_names.Count; } }
|
||||
|
||||
public bool IsReadOnly { get { return true; } }
|
||||
|
||||
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
var instance = this as IEnumerable<KeyValuePair<string, object>>;
|
||||
return instance.GetEnumerator();
|
||||
}
|
||||
|
||||
public void CopyTo(KeyValuePair<string, object>[] payloadEntries, int count)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, object> entry)
|
||||
{
|
||||
throw new System.NotSupportedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out object value)
|
||||
{
|
||||
if (key == null)
|
||||
throw new System.ArgumentNullException("key");
|
||||
|
||||
int position = 0;
|
||||
foreach (var name in m_names)
|
||||
{
|
||||
if (name == key)
|
||||
{
|
||||
value = m_values[position];
|
||||
return true;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
|
||||
value = default(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
#region private
|
||||
private List<string> m_names;
|
||||
private List<object> m_values;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
317
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceActivity.cs
vendored
Normal file
317
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceActivity.cs
vendored
Normal file
@@ -0,0 +1,317 @@
|
||||
using System;
|
||||
|
||||
#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>
|
||||
/// Provides support for EventSource activities by marking the start and
|
||||
/// end of a particular operation.
|
||||
/// </summary>
|
||||
internal sealed class EventSourceActivity
|
||||
: IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the EventSourceActivity class that
|
||||
/// is attached to the specified event source. The new activity will
|
||||
/// not be attached to any related (parent) activity.
|
||||
/// The activity is created in the Initialized state.
|
||||
/// </summary>
|
||||
/// <param name="eventSource">
|
||||
/// The event source to which the activity information is written.
|
||||
/// </param>
|
||||
public EventSourceActivity(EventSource eventSource)
|
||||
{
|
||||
if (eventSource == null)
|
||||
throw new ArgumentNullException("eventSource");
|
||||
Contract.EndContractBlock();
|
||||
|
||||
this.eventSource = eventSource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// You can make an activity out of just an EventSource.
|
||||
/// </summary>
|
||||
public static implicit operator EventSourceActivity(EventSource eventSource) { return new EventSourceActivity(eventSource); }
|
||||
|
||||
/* Properties */
|
||||
/// <summary>
|
||||
/// Gets the event source to which this activity writes events.
|
||||
/// </summary>
|
||||
public EventSource EventSource
|
||||
{
|
||||
get { return this.eventSource; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets this activity's unique identifier, or the default Guid if the
|
||||
/// event source was disabled when the activity was initialized.
|
||||
/// </summary>
|
||||
public Guid Id
|
||||
{
|
||||
get { return this.activityId; }
|
||||
}
|
||||
|
||||
#if false // don't expose RelatedActivityId unless there is a need.
|
||||
/// <summary>
|
||||
/// Gets the unique identifier of this activity's related (parent)
|
||||
/// activity.
|
||||
/// </summary>
|
||||
public Guid RelatedId
|
||||
{
|
||||
get { return this.relatedActivityId; }
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Start event with the specified name and data. If the start event is not active (because the provider
|
||||
/// is not on or keyword-level indiates the event is off, then the returned activity is simply the 'this' poitner
|
||||
/// and it is effectively like the Start d
|
||||
///
|
||||
/// A new activityID GUID is generated and the returned
|
||||
/// EventSourceActivity remembers this activity and will mark every event (including the start stop and any writes)
|
||||
/// with this activityID. In addition the Start activity will log a 'relatedActivityID' that was the activity
|
||||
/// ID before the start event. This way event processors can form a linked list of all the activities that
|
||||
/// caused this one (directly or indirectly).
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. It is strongly suggested that this name end in 'Start' (e.g. DownloadStart).
|
||||
/// If you do this, then the Stop() method will automatically replace the 'Start' suffix with a 'Stop' suffix.
|
||||
/// </param>
|
||||
/// <param name="options">Allow options (keywords, level) to be set for the write associated with this start
|
||||
/// These will also be used for the stop event.</param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public EventSourceActivity Start<T>(string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
|
||||
/// and level==Info) Data payload is empty.
|
||||
/// </summary>
|
||||
public EventSourceActivity Start(string eventName)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
var data = new EmptyStruct();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data). Data payload is empty.
|
||||
/// </summary>
|
||||
public EventSourceActivity Start(string eventName, EventSourceOptions options)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Shortcut version see Start(string eventName, EventSourceOptions options, T data) Options is empty (no keywords
|
||||
/// and level==Info)
|
||||
/// </summary>
|
||||
public EventSourceActivity Start<T>(string eventName, T data)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
return this.Start(eventName, ref options, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a Stop event with the specified data, and sets the activity
|
||||
/// to the Stopped state. The name is determined by the eventName used in Start.
|
||||
/// If that Start event name is suffixed with 'Start' that is removed, and regardless
|
||||
/// 'Stop' is appended to the result to form the Stop event name.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Stop<T>(T data)
|
||||
{
|
||||
this.Stop(null, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
|
||||
/// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
|
||||
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
|
||||
/// </summary>
|
||||
public void Stop<T>(string eventName)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Stop(eventName, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Used if you wish to use the non-default stop name (which is the start name with Start replace with 'Stop')
|
||||
/// This can be useful to indicate unusual ways of stoping (but it is still STRONGLY recommeded that
|
||||
/// you start with the same prefix used for the start event and you end with the 'Stop' suffix.
|
||||
/// </summary>
|
||||
public void Stop<T>(string eventName, T data)
|
||||
{
|
||||
this.Stop(eventName, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes an event associated with this activity to the eventSource associted with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. If null, the name is determined from
|
||||
/// data's type.
|
||||
/// </param>
|
||||
/// <param name="options">
|
||||
/// The options to use for the event.
|
||||
/// </param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Write<T>(string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes an event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. If null, the name is determined from
|
||||
/// data's type.
|
||||
/// </param>
|
||||
/// <param name="data">The data to include in the event.</param>
|
||||
public void Write<T>(string eventName, T data)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes a trivial event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. Must not be null.
|
||||
/// </param>
|
||||
/// <param name="options">
|
||||
/// The options to use for the event.
|
||||
/// </param>
|
||||
public void Write(string eventName, EventSourceOptions options)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes a trivial event associated with this activity.
|
||||
/// May only be called when the activity is in the Started state.
|
||||
/// </summary>
|
||||
/// <param name="eventName">
|
||||
/// The name to use for the event. Must not be null.
|
||||
/// </param>
|
||||
public void Write(string eventName)
|
||||
{
|
||||
var options = new EventSourceOptions();
|
||||
var data = new EmptyStruct();
|
||||
this.Write(this.eventSource, eventName, ref options, ref data);
|
||||
}
|
||||
/// <summary>
|
||||
/// Writes an event to a arbitrary eventSource stamped with the activity ID of this activity.
|
||||
/// </summary>
|
||||
public void Write<T>(EventSource source, string eventName, EventSourceOptions options, T data)
|
||||
{
|
||||
this.Write(source, eventName, ref options, ref data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases any unmanaged resources associated with this object.
|
||||
/// If the activity is in the Started state, calls Stop().
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (this.state == State.Started)
|
||||
{
|
||||
var data = new EmptyStruct();
|
||||
this.Stop(null, ref data);
|
||||
}
|
||||
}
|
||||
|
||||
#region private
|
||||
private EventSourceActivity Start<T>(string eventName, ref EventSourceOptions options, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
// If the source is not on at all, then we don't need to do anything and we can simply return ourselves.
|
||||
if (!this.eventSource.IsEnabled())
|
||||
return this;
|
||||
|
||||
var newActivity = new EventSourceActivity(eventSource);
|
||||
if (!this.eventSource.IsEnabled(options.Level, options.Keywords))
|
||||
{
|
||||
// newActivity.relatedActivityId = this.Id;
|
||||
Guid relatedActivityId = this.Id;
|
||||
newActivity.activityId = Guid.NewGuid();
|
||||
newActivity.startStopOptions = options;
|
||||
newActivity.eventName = eventName;
|
||||
newActivity.startStopOptions.Opcode = EventOpcode.Start;
|
||||
this.eventSource.Write(eventName, ref newActivity.startStopOptions, ref newActivity.activityId, ref relatedActivityId, ref data);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return newActivity;
|
||||
}
|
||||
|
||||
private void Write<T>(EventSource eventSource, string eventName, ref EventSourceOptions options, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException(); // Write after stop.
|
||||
if (eventName == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
eventSource.Write(eventName, ref options, ref this.activityId, ref s_empty, ref data);
|
||||
}
|
||||
|
||||
private void Stop<T>(string eventName, ref T data)
|
||||
{
|
||||
if (this.state != State.Started)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
// If start was not fired, then stop isn't as well.
|
||||
if (!StartEventWasFired)
|
||||
return;
|
||||
|
||||
this.state = State.Stopped;
|
||||
if (eventName == null)
|
||||
{
|
||||
eventName = this.eventName;
|
||||
if (eventName.EndsWith("Start"))
|
||||
eventName = eventName.Substring(0, eventName.Length - 5);
|
||||
eventName = eventName + "Stop";
|
||||
}
|
||||
this.startStopOptions.Opcode = EventOpcode.Stop;
|
||||
this.eventSource.Write(eventName, ref this.startStopOptions, ref this.activityId, ref s_empty, ref data);
|
||||
}
|
||||
|
||||
private enum State
|
||||
{
|
||||
Started,
|
||||
Stopped
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If eventName is non-null then we logged a start event
|
||||
/// </summary>
|
||||
private bool StartEventWasFired { get { return eventName != null; }}
|
||||
|
||||
private readonly EventSource eventSource;
|
||||
private EventSourceOptions startStopOptions;
|
||||
internal Guid activityId;
|
||||
// internal Guid relatedActivityId;
|
||||
private State state;
|
||||
private string eventName;
|
||||
|
||||
static internal Guid s_empty;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs
vendored
Normal file
126
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/EventSourceOptions.cs
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
using System;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Used when calling EventSource.Write.
|
||||
/// Optional overrides for event settings such as Level, Keywords, or Opcode.
|
||||
/// If overrides are not provided for a setting, default values will be used.
|
||||
/// </summary>
|
||||
public struct EventSourceOptions
|
||||
{
|
||||
internal EventKeywords keywords;
|
||||
internal EventTags tags;
|
||||
internal EventActivityOptions activityOptions;
|
||||
internal byte level;
|
||||
internal byte opcode;
|
||||
internal byte valuesSet;
|
||||
|
||||
internal const byte keywordsSet = 0x1;
|
||||
internal const byte tagsSet = 0x2;
|
||||
internal const byte levelSet = 0x4;
|
||||
internal const byte opcodeSet = 0x8;
|
||||
internal const byte activityOptionsSet = 0x10;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level to use for the specified event. If this property
|
||||
/// is unset, the event's level will be 5 (Verbose).
|
||||
/// </summary>
|
||||
public EventLevel Level
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EventLevel)this.level;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.level = checked((byte)value);
|
||||
this.valuesSet |= levelSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the opcode to use for the specified event. If this property
|
||||
/// is unset, the event's opcode will 0 (Info).
|
||||
/// </summary>
|
||||
public EventOpcode Opcode
|
||||
{
|
||||
get
|
||||
{
|
||||
return (EventOpcode)this.opcode;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.opcode = checked((byte)value);
|
||||
this.valuesSet |= opcodeSet;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsOpcodeSet
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this.valuesSet & opcodeSet) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the keywords to use for the specified event. If this
|
||||
/// property is unset, the event's keywords will be 0.
|
||||
/// </summary>
|
||||
public EventKeywords Keywords
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.keywords;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.keywords = value;
|
||||
this.valuesSet |= keywordsSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tags to use for the specified event. If this property is
|
||||
/// unset, the event's tags will be 0.
|
||||
/// </summary>
|
||||
public EventTags Tags
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.tags;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.tags = value;
|
||||
this.valuesSet |= tagsSet;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the activity options for this specified events. If this property is
|
||||
/// unset, the event's activity options will be 0.
|
||||
/// </summary>
|
||||
public EventActivityOptions ActivityOptions
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.activityOptions;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.activityOptions = value;
|
||||
this.valuesSet |= activityOptionsSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
227
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/FieldMetadata.cs
vendored
Normal file
227
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/FieldMetadata.cs
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
using System;
|
||||
using Encoding = System.Text.Encoding;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
using Environment = Microsoft.Diagnostics.Tracing.Internal.Environment;
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: Contains the information needed to generate tracelogging
|
||||
/// metadata for an event field.
|
||||
/// </summary>
|
||||
internal class FieldMetadata
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the field
|
||||
/// </summary>
|
||||
private readonly string name;
|
||||
|
||||
/// <summary>
|
||||
/// The number of bytes in the UTF8 Encoding of 'name' INCLUDING a null terminator.
|
||||
/// </summary>
|
||||
private readonly int nameSize;
|
||||
private readonly EventFieldTags tags;
|
||||
private readonly byte[] custom;
|
||||
|
||||
/// <summary>
|
||||
/// ETW supports fixed sized arrays. If inType has the InTypeFixedCountFlag then this is the
|
||||
/// statically known count for the array. It is also used to encode the number of bytes of
|
||||
/// custom meta-data if InTypeCustomCountFlag set.
|
||||
/// </summary>
|
||||
private readonly ushort fixedCount;
|
||||
|
||||
private byte inType;
|
||||
private byte outType;
|
||||
|
||||
/// <summary>
|
||||
/// Scalar or variable-length array.
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
bool variableCount)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
variableCount ? Statics.InTypeVariableCountFlag : (byte)0,
|
||||
0,
|
||||
null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fixed-length array.
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
ushort fixedCount)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
Statics.InTypeFixedCountFlag,
|
||||
fixedCount,
|
||||
null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom serializer
|
||||
/// </summary>
|
||||
public FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType type,
|
||||
EventFieldTags tags,
|
||||
byte[] custom)
|
||||
: this(
|
||||
name,
|
||||
type,
|
||||
tags,
|
||||
Statics.InTypeCustomCountFlag,
|
||||
checked((ushort)(custom == null ? 0 : custom.Length)),
|
||||
custom)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
private FieldMetadata(
|
||||
string name,
|
||||
TraceLoggingDataType dataType,
|
||||
EventFieldTags tags,
|
||||
byte countFlags,
|
||||
ushort fixedCount = 0,
|
||||
byte[] custom = null)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(
|
||||
"name",
|
||||
"This usually means that the object passed to Write is of a type that"
|
||||
+ " does not support being used as the top-level object in an event,"
|
||||
+ " e.g. a primitive or built-in type.");
|
||||
}
|
||||
|
||||
Statics.CheckName(name);
|
||||
var coreType = (int)dataType & Statics.InTypeMask;
|
||||
this.name = name;
|
||||
this.nameSize = Encoding.UTF8.GetByteCount(this.name) + 1;
|
||||
this.inType = (byte)(coreType | countFlags);
|
||||
this.outType = (byte)(((int)dataType >> 8) & Statics.OutTypeMask);
|
||||
this.tags = tags;
|
||||
this.fixedCount = fixedCount;
|
||||
this.custom = custom;
|
||||
|
||||
if (countFlags != 0)
|
||||
{
|
||||
if (coreType == (int)TraceLoggingDataType.Nil)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNil"));
|
||||
}
|
||||
if (coreType == (int)TraceLoggingDataType.Binary)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfBinary"));
|
||||
}
|
||||
#if !BROKEN_UNTIL_M3
|
||||
if (coreType == (int)TraceLoggingDataType.Utf16String ||
|
||||
coreType == (int)TraceLoggingDataType.MbcsString)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_NotSupportedArrayOfNullTerminatedString"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (((int)this.tags & 0xfffffff) != 0)
|
||||
{
|
||||
this.outType |= Statics.OutTypeChainFlag;
|
||||
}
|
||||
|
||||
if (this.outType != 0)
|
||||
{
|
||||
this.inType |= Statics.InTypeChainFlag;
|
||||
}
|
||||
}
|
||||
|
||||
public void IncrementStructFieldCount()
|
||||
{
|
||||
this.inType |= Statics.InTypeChainFlag;
|
||||
this.outType++;
|
||||
if ((this.outType & Statics.OutTypeMask) == 0)
|
||||
{
|
||||
throw new NotSupportedException(Environment.GetResourceString("EventSource_TooManyFields"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is the main routine for FieldMetaData. Basically it will serialize the data in
|
||||
/// this structure as TraceLogging style meta-data into the array 'metaArray' starting at
|
||||
/// 'pos' (pos is updated to reflect the bytes written).
|
||||
///
|
||||
/// Note that 'metaData' can be null, in which case it only updates 'pos'. This is useful
|
||||
/// for a 'two pass' approach where you figure out how big to make the array, and then you
|
||||
/// fill it in.
|
||||
/// </summary>
|
||||
public void Encode(ref int pos, byte[] metadata)
|
||||
{
|
||||
// Write out the null terminated UTF8 encoded name
|
||||
if (metadata != null)
|
||||
{
|
||||
Encoding.UTF8.GetBytes(this.name, 0, this.name.Length, metadata, pos);
|
||||
}
|
||||
pos += this.nameSize;
|
||||
|
||||
// Write 1 byte for inType
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos] = this.inType;
|
||||
}
|
||||
pos += 1;
|
||||
|
||||
// If InTypeChainFlag set, then write out the outType
|
||||
if (0 != (this.inType & Statics.InTypeChainFlag))
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos] = this.outType;
|
||||
}
|
||||
pos += 1;
|
||||
|
||||
// If OutTypeChainFlag set, then write out tags
|
||||
if (0 != (this.outType & Statics.OutTypeChainFlag))
|
||||
{
|
||||
Statics.EncodeTags((int)this.tags, ref pos, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
// If InTypeFixedCountFlag set, write out the fixedCount (2 bytes little endian)
|
||||
if (0 != (this.inType & Statics.InTypeFixedCountFlag))
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
metadata[pos + 0] = unchecked((byte)this.fixedCount);
|
||||
metadata[pos + 1] = (byte)(this.fixedCount >> 8);
|
||||
}
|
||||
pos += 2;
|
||||
|
||||
// If InTypeCustomCountFlag set, write out the blob of custom meta-data.
|
||||
if (Statics.InTypeCustomCountFlag == (this.inType & Statics.InTypeCountMask) &&
|
||||
this.fixedCount != 0)
|
||||
{
|
||||
if (metadata != null)
|
||||
{
|
||||
Buffer.BlockCopy(this.custom, 0, metadata, pos, this.fixedCount);
|
||||
}
|
||||
pos += this.fixedCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/InvokeTypeInfo.cs
vendored
Normal file
114
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/InvokeTypeInfo.cs
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <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).
|
||||
/// </summary>
|
||||
/// <typeparam name="ContainerType">
|
||||
/// Type from which to read values.
|
||||
/// </typeparam>
|
||||
internal sealed class InvokeTypeInfo<ContainerType>
|
||||
: TraceLoggingTypeInfo<ContainerType>
|
||||
{
|
||||
private readonly PropertyAnalysis[] properties;
|
||||
private readonly PropertyAccessor<ContainerType>[] accessors;
|
||||
|
||||
public InvokeTypeInfo(
|
||||
TypeAnalysis typeAnalysis)
|
||||
: base(
|
||||
typeAnalysis.name,
|
||||
typeAnalysis.level,
|
||||
typeAnalysis.opcode,
|
||||
typeAnalysis.keywords,
|
||||
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(
|
||||
TraceLoggingMetadataCollector collector,
|
||||
string name,
|
||||
EventFieldFormat format)
|
||||
{
|
||||
var groupCollector = collector.AddGroup(name);
|
||||
if (this.properties != null)
|
||||
{
|
||||
foreach (var property in this.properties)
|
||||
{
|
||||
var propertyFormat = EventFieldFormat.Default;
|
||||
var propertyAttribute = property.fieldAttribute;
|
||||
if (propertyAttribute != null)
|
||||
{
|
||||
groupCollector.Tags = propertyAttribute.Tags;
|
||||
propertyFormat = propertyAttribute.Format;
|
||||
}
|
||||
|
||||
property.typeInfo.WriteMetadata(
|
||||
groupCollector,
|
||||
property.name,
|
||||
propertyFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteData(
|
||||
TraceLoggingDataCollector collector,
|
||||
ref ContainerType value)
|
||||
{
|
||||
if (this.accessors != null)
|
||||
{
|
||||
foreach (var accessor in this.accessors)
|
||||
{
|
||||
accessor.Write(collector, ref value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override object GetData(object value)
|
||||
{
|
||||
if (this.properties != null)
|
||||
{
|
||||
var membersNames = new List<string>();
|
||||
var memebersValues = new List<object>();
|
||||
for (int i = 0; i < this.properties.Length; i++)
|
||||
{
|
||||
var propertyValue = accessors[i].GetData((ContainerType)value);
|
||||
membersNames.Add(properties[i].name);
|
||||
memebersValues.Add(properties[i].typeInfo.GetData(propertyValue));
|
||||
}
|
||||
return new EventPayload(membersNames, memebersValues);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/NameInfo.cs
vendored
Normal file
75
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/NameInfo.cs
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
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: Stores the metadata and event identifier corresponding
|
||||
/// to a tracelogging event type+name+tags combination.
|
||||
/// </summary>
|
||||
internal sealed class NameInfo
|
||||
: ConcurrentSetItem<KeyValuePair<string, EventTags>, NameInfo>
|
||||
{
|
||||
/// <summary>
|
||||
/// Insure that eventIds strictly less than 'eventId' will not be
|
||||
/// used by the SelfDescribing events.
|
||||
/// </summary>
|
||||
internal static void ReserveEventIDsBelow(int eventId)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
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;
|
||||
internal readonly int identity;
|
||||
internal readonly byte[] nameMetadata;
|
||||
|
||||
public NameInfo(string name, EventTags tags, int typeMetadataSize)
|
||||
{
|
||||
this.name = name;
|
||||
this.tags = tags & Statics.EventTagsMask;
|
||||
this.identity = Interlocked.Increment(ref lastIdentity);
|
||||
|
||||
int tagsPos = 0;
|
||||
Statics.EncodeTags((int)this.tags, ref tagsPos, null);
|
||||
|
||||
this.nameMetadata = Statics.MetadataForString(name, tagsPos, 0, typeMetadataSize);
|
||||
|
||||
tagsPos = 2;
|
||||
Statics.EncodeTags((int)this.tags, ref tagsPos, this.nameMetadata);
|
||||
}
|
||||
|
||||
public override int Compare(NameInfo other)
|
||||
{
|
||||
return this.Compare(other.name, other.tags);
|
||||
}
|
||||
|
||||
public override int Compare(KeyValuePair<string, EventTags> key)
|
||||
{
|
||||
return this.Compare(key.Key, key.Value & Statics.EventTagsMask);
|
||||
}
|
||||
|
||||
private int Compare(string otherName, EventTags otherTags)
|
||||
{
|
||||
int result = StringComparer.Ordinal.Compare(this.name, otherName);
|
||||
if (result == 0 && this.tags != otherTags)
|
||||
{
|
||||
result = this.tags < otherTags ? -1 : 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
154
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAccessor.cs
vendored
Normal file
154
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAccessor.cs
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAnalysis.cs
vendored
Normal file
33
external/referencesource/mscorlib/system/diagnostics/eventing/TraceLogging/PropertyAnalysis.cs
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
#if ES_BUILD_STANDALONE
|
||||
namespace Microsoft.Diagnostics.Tracing
|
||||
#else
|
||||
namespace System.Diagnostics.Tracing
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// TraceLogging: stores the per-property information obtained by
|
||||
/// reflecting over a type.
|
||||
/// </summary>
|
||||
internal sealed class PropertyAnalysis
|
||||
{
|
||||
internal readonly string name;
|
||||
internal readonly MethodInfo getterInfo;
|
||||
internal readonly TraceLoggingTypeInfo typeInfo;
|
||||
internal readonly EventFieldAttribute fieldAttribute;
|
||||
|
||||
public PropertyAnalysis(
|
||||
string name,
|
||||
MethodInfo getterInfo,
|
||||
TraceLoggingTypeInfo typeInfo,
|
||||
EventFieldAttribute fieldAttribute)
|
||||
{
|
||||
this.name = name;
|
||||
this.getterInfo = getterInfo;
|
||||
this.typeInfo = typeInfo;
|
||||
this.fieldAttribute = fieldAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user