-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEventSourceLogStrategy.cs
137 lines (120 loc) · 5.52 KB
/
EventSourceLogStrategy.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics.Tracing;
using System.Runtime.InteropServices;
namespace ILCompiler.DependencyAnalysisFramework
{
[EventSource(Name = "Microsoft-ILCompiler-DependencyGraph")]
class GraphEventSource : EventSource
{
public class Keywords
{
public const EventKeywords Graph = (EventKeywords)1;
}
// Notice that the bodies of the events follow a pattern: WriteEvent(ID, <args>) where
// ID is a unique ID starting at 1 and incrementing for each new event method. and
// <args> is every argument for the method.
// WriteEvent then takes care of all the details of actually writing out the values complete
// with the name of the event (method name) as well as the names and types of all the parameters.
[Event(1, Keywords = Keywords.Graph, Level = EventLevel.Informational)]
public void Graph(int id, string name) { WriteEvent(1, id, name); }
[Event(2, Keywords = Keywords.Graph, Level = EventLevel.Informational)]
public void Node(int id, int index, string name) { WriteEvent(2, id, index, name); }
[Event(3, Keywords = Keywords.Graph, Level = EventLevel.Informational)]
public void Edge(int id, int dependentIndex, int dependencyIndex, string reason) { WriteEvent(3, id, dependentIndex, dependencyIndex, reason); }
[Event(4, Keywords = Keywords.Graph, Level = EventLevel.Informational)]
public void ConditionalEdge(int id, int dependentIndex1, int dependentIndex2, int dependencyIndex, string reason) { WriteEvent(4, id, dependentIndex1, dependentIndex2, dependencyIndex, reason); }
// Typically you only create one EventSource and use it throughout your program. Thus a static field makes sense.
public static GraphEventSource Log = new GraphEventSource();
}
public struct EventSourceLogStrategy<DependencyContextType> : IDependencyAnalysisMarkStrategy<DependencyContextType>
{
private static int s_GraphIds = 0;
private int GraphId;
private int RootIndex;
private int ObjectIndex;
private DependencyContextType _context;
public static bool IsEventSourceEnabled
{
get
{
return
#if !ALWAYS_SUPPORT_EVENTSOURCE_LOG
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && // Processing these event source events is only implemented on Windows
#endif
GraphEventSource.Log.IsEnabled();
}
}
bool IDependencyAnalysisMarkStrategy<DependencyContextType>.MarkNode(
DependencyNodeCore<DependencyContextType> node,
DependencyNodeCore<DependencyContextType> reasonNode,
DependencyNodeCore<DependencyContextType> reasonNode2,
string reason)
{
bool retVal = false;
int nodeIndex;
if (!node.Marked)
{
nodeIndex = Interlocked.Increment(ref ObjectIndex);
node.SetMark(nodeIndex);
if (GraphId == 0)
{
lock (GraphEventSource.Log)
{
if (GraphId == 0)
{
GraphId = Interlocked.Increment(ref s_GraphIds);
GraphEventSource.Log.Graph(GraphId, "");
RootIndex = Interlocked.Increment(ref ObjectIndex);
GraphEventSource.Log.Node(GraphId, RootIndex, "roots");
}
}
}
retVal = true;
GraphEventSource.Log.Node(GraphId, nodeIndex, node.GetNameInternal(_context));
}
else
{
nodeIndex = (int)node.GetMark();
}
if (reasonNode != null)
{
if (reasonNode2 != null)
{
GraphEventSource.Log.ConditionalEdge(GraphId, (int)reasonNode.GetMark(), (int)reasonNode2.GetMark(), nodeIndex, reason);
}
else
{
GraphEventSource.Log.Edge(GraphId, (int)reasonNode.GetMark(), nodeIndex, reason);
}
}
else
{
GraphEventSource.Log.Edge(GraphId, RootIndex, nodeIndex, reason);
}
return retVal;
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogEdges(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogEdgeVisitor<DependencyContextType> logEdgeVisitor)
{
// This marker does not permit logging.
return;
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.VisitLogNodes(IEnumerable<DependencyNodeCore<DependencyContextType>> nodeList, IDependencyAnalyzerLogNodeVisitor<DependencyContextType> logNodeVisitor)
{
// This marker does not permit logging.
return;
}
void IDependencyAnalysisMarkStrategy<DependencyContextType>.AttachContext(DependencyContextType context)
{
_context = context;
}
}
}