forked from aspnet/AspNetWebStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTraceManager.cs
More file actions
222 lines (198 loc) · 10.4 KB
/
TraceManager.cs
File metadata and controls
222 lines (198 loc) · 10.4 KB
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.ObjectModel;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
using System.Web.Http.Services;
using System.Web.Http.Tracing.Tracers;
namespace System.Web.Http.Tracing
{
internal class TraceManager : ITraceManager
{
public void Initialize(HttpConfiguration configuration)
{
ITraceWriter traceWriter = configuration.Services.GetTraceWriter();
if (traceWriter != null)
{
// Install tracers only when a custom trace writer has been registered
CreateAllTracers(configuration, traceWriter);
}
}
private static void CreateAllTracers(HttpConfiguration configuration, ITraceWriter traceWriter)
{
CreateActionInvokerTracer(configuration, traceWriter);
CreateActionSelectorTracer(configuration, traceWriter);
CreateActionValueBinderTracer(configuration, traceWriter);
CreateContentNegotiatorTracer(configuration, traceWriter);
CreateControllerActivatorTracer(configuration, traceWriter);
CreateControllerSelectorTracer(configuration, traceWriter);
CreateHttpControllerTypeResolverTracer(configuration, traceWriter);
CreateMessageHandlerTracers(configuration, traceWriter);
CreateMediaTypeFormatterTracers(configuration, traceWriter);
}
// Get services from the global config. These are normally per-controller services, but we're getting the global fallbacks.
private static TService GetService<TService>(ServicesContainer services)
{
return (TService)services.GetService(typeof(TService));
}
private static void CreateActionInvokerTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IHttpActionInvoker invoker = GetService<IHttpActionInvoker>(configuration.Services);
if (invoker != null && !(invoker is HttpActionInvokerTracer))
{
HttpActionInvokerTracer tracer = new HttpActionInvokerTracer(invoker, traceWriter);
configuration.Services.Replace(typeof(IHttpActionInvoker), tracer);
}
}
private static void CreateActionSelectorTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IHttpActionSelector selector = GetService<IHttpActionSelector>(configuration.Services);
if (selector != null && !(selector is HttpActionSelectorTracer))
{
HttpActionSelectorTracer tracer = new HttpActionSelectorTracer(selector, traceWriter);
configuration.Services.Replace(typeof(IHttpActionSelector), tracer);
}
}
private static void CreateActionValueBinderTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IActionValueBinder binder = GetService<IActionValueBinder>(configuration.Services);
if (binder != null && !(binder is ActionValueBinderTracer))
{
ActionValueBinderTracer tracer = new ActionValueBinderTracer(binder, traceWriter);
configuration.Services.Replace(typeof(IActionValueBinder), tracer);
}
}
private static void CreateContentNegotiatorTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IContentNegotiator negotiator = configuration.Services.GetContentNegotiator();
if (negotiator != null && !(negotiator is ContentNegotiatorTracer))
{
ContentNegotiatorTracer tracer = new ContentNegotiatorTracer(negotiator, traceWriter);
configuration.Services.Replace(typeof(IContentNegotiator), tracer);
}
}
private static void CreateControllerActivatorTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IHttpControllerActivator activator = GetService<IHttpControllerActivator>(configuration.Services);
if (activator != null && !(activator is HttpControllerActivatorTracer))
{
HttpControllerActivatorTracer tracer = new HttpControllerActivatorTracer(activator, traceWriter);
configuration.Services.Replace(typeof(IHttpControllerActivator), tracer);
}
}
private static void CreateControllerSelectorTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
IHttpControllerSelector controllerSelector = configuration.Services.GetHttpControllerSelector();
if (controllerSelector != null && !(controllerSelector is HttpControllerSelectorTracer))
{
HttpControllerSelectorTracer tracer = new HttpControllerSelectorTracer(controllerSelector, traceWriter);
configuration.Services.Replace(typeof(IHttpControllerSelector), tracer);
}
}
private static void CreateHttpControllerTypeResolverTracer(HttpConfiguration configuration, ITraceWriter traceWriter)
{
DefaultHttpControllerTypeResolver resolver =
configuration.Services.GetHttpControllerTypeResolver() as DefaultHttpControllerTypeResolver;
if (resolver != null)
{
IHttpControllerTypeResolver tracer = new DefaultHttpControllerTypeResolverTracer(resolver, traceWriter);
configuration.Services.Replace(typeof(IHttpControllerTypeResolver), tracer);
}
}
private static void CreateMediaTypeFormatterTracers(HttpConfiguration configuration, ITraceWriter traceWriter)
{
for (int i = 0; i < configuration.Formatters.Count; i++)
{
MediaTypeFormatter formatter = configuration.Formatters[i];
if (!(formatter is IFormatterTracer))
{
configuration.Formatters[i] = MediaTypeFormatterTracer.CreateTracer(
configuration.Formatters[i],
traceWriter,
request: null);
}
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Will be disposed when pipeline is disposed.")]
private static void CreateMessageHandlerTracers(HttpConfiguration configuration, ITraceWriter traceWriter)
{
int handlerCount = configuration.MessageHandlers.Count;
// If message handlers have already been wired into the pipeline,
// we do not install tracing message handlers. This scenario occurs
// when initialization is attempted twice, such as per-controller configuration.
if (handlerCount > 0 && configuration.MessageHandlers[0].InnerHandler != null)
{
return;
}
// RequestMessageHandlerTracer will be the first tracer to get executed and each messageHandlerTracer
// will execute before its respective handler. For the MessageHandlerTracers to be registered,
// the message handler list must be of the form:
// requestMessageHandlerTracer
// messageHandler1Tracer
// messageHandler1
// ...
// ...
// messageHandlerNTracer
// messageHandlerN
// Where "N" is a non-negative integer. That is, there could be zero or more pairs of handlers/tracers, plus a
// request tracer at the beginning. If the state does not match this pattern, the tracer list is recreated.
if (!AreMessageHandlerTracersRegistered(configuration.MessageHandlers))
{
// Removing the MessageHandlerTracer and RequestMessageHandlerTracer in the reverse order.
for (int i = handlerCount - 1; i >= 0; i--)
{
if (configuration.MessageHandlers[i] is RequestMessageHandlerTracer || configuration.MessageHandlers[i] is MessageHandlerTracer)
{
configuration.MessageHandlers.RemoveAt(i);
}
}
handlerCount = configuration.MessageHandlers.Count;
// Insert a tracing handler before each existing message handler (in execution order)
for (int i = 0; i < handlerCount * 2; i += 2)
{
DelegatingHandler innerHandler = configuration.MessageHandlers[i];
DelegatingHandler handlerTracer = new MessageHandlerTracer(innerHandler, traceWriter);
configuration.MessageHandlers.Insert(i, handlerTracer);
}
configuration.MessageHandlers.Insert(0, new RequestMessageHandlerTracer(traceWriter));
}
}
private static bool AreMessageHandlerTracersRegistered(Collection<DelegatingHandler> messageHandlers)
{
int handlerCount = messageHandlers.Count;
// if the handler count is zero, exit early.
if (handlerCount == 0)
{
return false;
}
// if RequestMessageHandlerTracer is absent, exit early.
if (!(messageHandlers[0] is RequestMessageHandlerTracer))
{
return false;
}
// Message handler list must be an odd number (2*N+1) for N message handlers.
if (handlerCount % 2 != 1)
{
return false;
}
// Check if all odd positions have tracers and even positions have their corresponding handlers.
for (int i = 2; i < handlerCount; i += 2)
{
DelegatingHandler tracer = messageHandlers[i - 1];
DelegatingHandler messageHandler = messageHandlers[i];
if (!(tracer is MessageHandlerTracer))
{
return false;
}
DelegatingHandler innerHandler = Decorator.GetInner(tracer);
if (innerHandler != messageHandler)
{
return false;
}
}
return true;
}
}
}