Как настроить Network Tracing в .net
Если вы, как и я, изучали .net в “боевых условиях” под лозунги “вперед на мины, за вами Родная Компания”, а первым встретившимся вам инструментом логирования был log4net, вы, позже, узнали про стандартные средства логирования в .net (System.Diagnostics.Trace
, например), но не видели смысла разбираться с еще одним логером, когда вас старый полностью устраивает.
То, вполне вероятно, что вы тоже не знали, что у стандартного логера есть особенность, о которой желательно знать всем.
Особенность эта в том, что код .net фреймворка уже прошит его вызовами. И что для получения всей этой (иногда жизненно важной) информации вам всего лишь нужно добавить несколько строчек в конфиг. И пусть вы и дальше будете продолжать пользоваться log4net, знание, что вы всегда можете включить дополнительное логирование, не раз может вам пригодиться. Мне это уже пригодилось. Но обо всем по порядку.
История (почти) детективная о неработающем приложении)))
Разрабатывали мы клиента, который скачивал данные из одного облачного хранилища. Разработали, оттестировали на рабочей машине, на тестовом сервере, выкатили на продакшен и… ничего. Программа данные не качает, молчит, а через некоторое время валится с ошибкой.
На сервере ничего установить нельзя, ни дебагер, ни трассировщик, ничего стороннего. Ну с таким мы уже сталкивались. Прошили клиента лог-сообщениями; запустили, собрали лог; уточнили место, в котором валится, прошили плотнее; обнаружили место ошибки. Ура! Нет, не ура. Этой строчкой оказался вызов библиотеки провайдера данных. Этот вызов, в свою очередь, отправлял HTTP REST запрос и получал ответ от сервера. Логика вроде не сложная, но в ответ от сервера нам приходила пустота (т.е. null
). На рабочих машинах все в порядке. На таком же тестовом сервере, с тем же [теоретически] набором ПО и настройками работает. А на продакшен сервере не работает.
Нам бы поставить fiddler и посмотреть, что же происходит “под капотом”, но нельзя. Сервак-с. Появились безумные мысли дизассемблировать библиотеку провайдера и напихать туда логирования (благо .net). Но, к счастью, мы наткнулись на сообщение о том, что можно включить логирование в самом .net Framework-е через конфиг файл.
Мы его включили, запустили приложение, забрали логи, проанализировали, стукнули себя по лбу, исправили. Все заработало. (В чем была ошибка, я говорить не буду. Стыдно.)
Как все же настроить Network Tracing
Само сообщение: How to: Configure Network Tracing. В нем содержится конфиг файл, который включает логирование в нэймспэйсе System.Net. Добавили эти строчки в конфиг и обнаружили, что в лог пишется слишком много ненужной нам информации. Поменяли параметр tracemode="includehex"
на tracemode="protocolonly"
(16-ричные коды нам точно не нужны), убрали логирование в System.Net.Sockets
и System.Net.WebSockets
.
Вот итоговый конфиг файл:
<system.diagnostics>
<sources>
<source name="System.Net" tracemode="protocolonly" maxdatasize="1024">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Cache">
<listeners>
<add name="System.Net"/>
</listeners>
</source>
<source name="System.Net.Http">
<listeners>
<add name="System.Net "/>
</listeners>
</source>
</sources>
<switches>
<add name="System.Net" value="Verbose"/>
<add name="System.Net.Cache" value="Verbose"/>
<add name="System.Net.Http" value="Verbose"/>
</switches>
<sharedListeners>
<add name="System.Net"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="network.log"
/>
</sharedListeners>
<trace autoflush="true"/>
</system.diagnostics>
Пример лог вывода:
System.Net Verbose: 0 : [4456] WebRequest::Create(#####################URL########################)
System.Net Verbose: 0 : [4456] HttpWebRequest#58870012::HttpWebRequest(#####################URL########################)
System.Net Warning: 0 : [4456] The Registry value 'Software\Microsoft\Windows NT\CurrentVersion\InstallationType' was either empty or not a string type.
System.Net Information: 0 : [4456] Current OS installation type is 'Unknown'.
System.Net Information: 0 : [4456] RAS supported: True
System.Net Verbose: 0 : [4456] Exiting HttpWebRequest#58870012::HttpWebRequest()
System.Net Verbose: 0 : [4456] Exiting WebRequest::Create() -> HttpWebRequest#58870012
System.Net Verbose: 0 : [4456] HttpWebRequest#58870012::GetRequestStream()
System.Net Information: 0 : [4456] Associating HttpWebRequest#58870012 with ServicePoint#3741682
System.Net Information: 0 : [4456] Associating Connection#33675143 with HttpWebRequest#58870012
System.Net Information: 0 : [4456] ConnectStream#20234383 - Sending headers
{
Authorization: Basic *************************************************==
Accept: application/json, application/xml, text/json, text/x-json, text/javascript, text/xml
User-Agent: RestSharp 102.7.0.0
Content-Type: application/json
Host: ************
Content-Length: 2430
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
}.
System.Net Verbose: 0 : [4456] Exiting HttpWebRequest#58870012::GetRequestStream() -> ConnectStream#20234383
System.Net Verbose: 0 : [4456] ConnectStream#20234383::Write()
System.Net Verbose: 0 : [4456] Data from ConnectStream#20234383::Write
System.Net Verbose: 0 : [4456] (printing 1024 out of 2430)
System.Net Verbose: 0 : [4456] <<{"createdBy":null,"createdAt":null,"fields":{"ContactIDExt":"\{\{Contact.Field(C XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX>>
System.Net Verbose: 0 : [4456] Exiting ConnectStream#20234383::Write()
System.Net Verbose: 0 : [4456] ConnectStream#20234383::Close()
System.Net Verbose: 0 : [4456] Exiting ConnectStream#20234383::Close()
System.Net Verbose: 0 : [4456] HttpWebRequest#58870012::GetResponse()
Нужно поднимать основы
Несмотря на то, что я уже больше 8 лет работаю с платформой .net, о многих вещах я до сих пор не знаю. О базовых, можно сказать, вещах. Патерны, архитектура, Эджайлы, Канбаны, REST, HighLoad, DI, IoC, SOLID, … На это время у меня находится. А вот взять и разобраться с тем, что уже предоставляют мне мои инструменты…, на это у меня времени нет :(
Нужно будет обязательно разобраться со стандартным логированием, посмотреть, какие еще стандартные библиотеки предоставляют такой сервис (предположительно все библиотеки прикладного уровня). А так же раздобыть книжку с обзором средств диагностики в .net фреймворке. Может, вы такую посоветуете? И, наконец, дочитать Рихтера CLR via C#.