EventTrace for Windows. Высокоскоростная передача отладочных сообщений драйвера по сети

Существует разные техники отладки: кто-то зарывается в отладчик, кто-то медитирует, ожидая просветления, кто-то судорожно меняет код в надежде на удачу, но почти ни кто не откажется от файла в котором будет сохранены последние мгновения жизни процесса, что происходило, в каких нитях, на каких ядрах, в какое время. Заботливо и педантично сохраненная отладочная информация может сохранить многие рабочие часы, особенно если речь идет о отладке драйвера и аппаратного обеспечения с которым он работает. Ну, а в случае когда ошибка случайная и воспроизводиться на 1 системе из 20 в течении недели, то без отладочной информации медитация может затянуться.
В данной статье пойдет речь об утилитах, помогающих в перехвате отладочных сообщений драйверов, работающих на нескольких машинах одновременно и передаче сообщений на сервер для сохранения и анализа.

Предыстория

Технология EventTrace for Windows впервые была включена в Windows 2k и с тех пор она была верным спутником всех последующих ОС, постепенно проникая во все большее количество ПО: от драйверов до пользовательских приложений.
Трудно сказать, что это был прорыв, но изюминка у ETW имеется – скорость. Десятки тысяч отладочных сообщений в секунду из глубин драйвера с мизерным влиянием на производительность дает простор для фантазии инженера. А если к этому добавить детальность и точность получаемой информации, то жизнь начинает казаться безоблачной.
Окрыленные этим чувством, мы приступили к внедрению. Трудности начались почти сразу, и имя этим трудностям было — TraceView. Данная утилита, предназначенная для получения и просмотра отладочных сообщений, упорно не желала делать то, ради чего создавалась.
Если технология доставки сообщений была проработана достаточно хорошо — ETW с лёгкостью проглатывал десятки тысяч, то вот с получением не заладилось, создавалось впечатление, что TraceView был создан для собственных нужд одиноким инженером в недрах корпорации и по случайности попал в DDK.

Проблема

После очередной потери результатов длительных тестов было принято решение классифицировать все трудности, с которыми мы столкнулись, и искать альтернативу, которая нас бы устроила. Желающие ознакомиться со списком причин могут найти их под

спойлером.

  • Работа с большими файлами (файл считается большим, если размер превысил 25 мегабайт). Открытие такого файла занимает существенное время;
  • Потеря служебны данных. Регулярно ETW, сохраняя файл, забывает записать служебный заголовок. Впоследствии, обнаружив такой файл, приходится долго медитировать над шестнадцатиричным редактором, восстанавливая данные. Особенно это обидно когда файл содежрит информацию об ошибке, которую не могли воспроизвести несколько дней. В Windows 8 этот дефект обещали устранить;
  • В режиме реального времени окно просмотра сообщений вмещает только 65 тысяч. На первый взгляд это много, но если представить, что драйвер шлет хотя бы 1 тысячу сообщений в секунду, то все что Вы сможете рассмотреть это только 1 минута;
  • Копирование текста сообщения. Вы можете скопировать сообщение только целиком, нет возможности работать с частями текста;
  • Поиск. Его нет;
  • Подсветка выполнена через окно фильтрации, выбор цвета осуществляется по его названию: например «Gray — 50»;
  • Фильтрация. Применить фильтр на заранее сохраненных данных не тривиальная задача;
  • Профили. Создание нового профиля утомительное и долгое занятие, перегруженное настройками. Копировать профили посредством утилиты нельзя;

Поиск не дал результатов, ближе всех к требованиям была утилита ETViewer, но и она не покрывала всех необходимых потребностей, к тому же работа над ней была заброшена и в данный момент список разработчиков пуст.
Надежды на быстрое решение наших проблем пошли прахом. Чтоб свыкнуться с этим фактом потребовалось время, в течение которого мы все так же использовали TraceView, копили силы и идеи.

Решение

Идея самостоятельной разработки была встречена руководством нашего R&D отдела с пониманием и энтузиазмом, однако после составления списка задач и оценки в попугаях — стало очевидно, что такими свободными ресурсами мы не располагаем. Речь шла приблизительно о 6 человеко-месяцах только для самого базового функционала. А, как известно – аппетит приходит во время еды.
Несмотря на серию «неудач» выбросить и забыть идею я не смог. Так началась череда вечеров длинной почти в год когда, придя с одной работы, я приступал к другой. Как результат этой работы на свет появились следующие приложения и библиотеки (исходные коды распространяются под лицензией Apache 2.0):

  • Байкал – серверное приложение-каркас, к которому подключаются модули расширения (провайдеры, хранилища, просмотрщики);
  • Ангара – клиентское приложение управляющее сессией ETW, получающее сообщения и переправляющее их Байкалу;
  • P7.Trace – C++ библиотека, ответственная за обработку отладочных сообщений разрабатываемого приложения, и передачу их Байкалу. По сути это замена ETW, способная работать и под Windows и под Linux;

В чем изюминка всего этого добра? Как и в случае с ETW — это скорость. Речь идет о миллионах отладочных сообщений в секунду для современных домашних ПК. К примеру: дуэт I7-870 и гигабитной сети способен проглотить более 2 миллионов сообщений формата:

 Trace(“Here is my trace and here are my values: %d %d”, iVal1, iVal2);

Помимо очевидной формат строки и параметров передаются так же следующие данные:

  • Уровень «тревожности» (trace, info, warning, error, etc) ;
  • Время с точностью до 100 нано секунд;
  • Номер процессора, на котором выполнился код;
  • ID текущей нити;
  • ID модуля;
  • Имя функции, файла, номер линии в файле;
  • Порядковый номер;
  • Информация о процессе (имя, ID, время создания);

На стороне Байкала все это выглядит вот так

image
image

Второй по важности и удобству момент – централизованный сбор отладочных сообщений. Приведу пример – компания, в которой я работаю, разрабатывает как свое аппаратное обеспечение, так и почти все слои ПО для него. При разработке и тестировании тратиться огромное кол-во времени для наблюдения за зоопарком из нескольких железок, драйверов и ПО. Поэтому возможность централизованно наблюдать за жизненными показателями и, в случае сбоя, восстановить детальную картину произошедшего цениться высоко.
К сожалению, а возможно к счастью, я не смогу уместить в одну статью все возможную информацию по всем компонентам в силу моих временных ограничений. Так же за бортом останется обзор того что находится под капотом ETW, но при наличии интереса этот недостаток можно будет восполнить другой статьей.

Ангара

Вот я и добрался в своем повествовании до той его части, ради которой оно и затевалось. В этой главе я расскажу о том, как сконфигурировать и запустить Ангару. Предполагается, что Вы уже знакомы с ETW и Ваш драйвер уже инструментирован подобными сообщениями.

Параметры ETW сессии

Отправной точкой каждой ETW сессии является Control GUID, в одном из Ваших исходных файлов есть похожие строки:

  //{63423ADB-D156-4281-BA74-8ACAEDDBD810} #define WPP_CONTROL_GUIDS \     WPP_DEFINE_CONTROL_GUID(ProviderGuid, (63423ADB, D156, 48d5, B0BC, 8ACAEDDBD810),\     WPP_DEFINE_BIT(DBG_PROVIDER)           /* bit  0 = 0x00000001 */ \     /* You can have up to 32 defines. If you want more than that,\     you have to provide another trace control GUID */\     ) 

Нас интересует значение WPP_DEFINE_CONTROL_GUID, которое может быть записано в форме {63423ADB-D156-4281-BA74-8ACAEDDBD810}, запомните его — оно еще понадобиться.

Вторым по важности элементом, который потребуется от Вашего драйвера будет Trace Message Format File (TMF). Файл описывает формат отладочных сообщений, а так же содержит дополнительную информацию о сообщении. Наиболее простой способ получить этот файл – это выполнить следующую команду после успешной сборки вашего драйвера:

Tracepdb.exe -f MyDriver.pdb -o MyTraceMessageFormatFile.tmf 

Утилита «Tracepdb.exe» поставляется вместе с DDK, путь по умолчанию следующий: C:\WinDDK\{Version}\tools\tracing\

Настройки. Провайдер

Итак, мы вооружились Control GUID и TMF файлом – настало время редактировать конфигурационный файл Ангары, называется он незатейливо — «Angara.xml» и находится в той же папке что и исполняемые файлы. Откройте его любым редактором, понимающим UTF-16, и можем приступать к редактированию.

Первая интересующая нас секция посвящена ETW провайдеру:

<Provider TMF="."           GUID="{63423ADB-D156-48d5-B0BC-8ACAEDDBD810}"           Level="5"           Flags="0xFFFFFFFFFFFFFFFF"           Filter=""           Platform="X32" /> 

Обязательных параметра всего два:

  • TMF – путь к папке с TMF файлами, которые Вы же и сгенерировали;
  • GUID – тот самый Control GUID;

Важными, но не обязательными параметрами являются параметры «Flags» и «Level» они позволяют фильтровать нежелательные в данный момент сообщения на стороне драйвера, тем самым снижая нагрузку на ETW и систему в целом.
Остальные опциональные параметры достаточно подробно описаны в документации, а так же в самом XML файле и приводить их описание здесь излишне.

Настройки. Сеть

Следующая секция посвящена сетевому соединению:

<P7Trace Address="localhost"          Port="9009"          Packet="1472"          Name="MyChannel"          Verbosity="1" />

Обязательный параметр лишь один – Address, в него необходимо вписать IP адрес (IPv4/ IPv6) или символьное имя ПК на котором запущен Байкал. Опциональные параметры подробно описаны в документации.

Настройки. Уровни

Последняя секция представляет собой карту, по которой происходит преобразование уровня сообщений ETW в уровень сообщений понятный Байкалу:

<Levels>     <Trace>         <WPP Text="TRACE_LEVEL_VERBOSE"/>     </Trace>     <Debug>         <WPP Text="TRACE_LEVEL_NONE"/>     </Debug>     <Info>         <WPP Text="TRACE_LEVEL_INFORMATION"/>     </Info>     <Warning>         <WPP Text="TRACE_LEVEL_WARNING"/>     </Warning>     <Error>         <WPP Text="TRACE_LEVEL_ERROR"/>     </Error>     <Critical>         <WPP Text="TRACE_LEVEL_FATAL"/>         <WPP Text="TRACE_LEVEL_CRITICAL"/>     </Critical> </Levels> 

Редактировать эту секцию необходимо, только если вы переопределили макросы в исходном коде Вашего драйвера, например вот так:

  // Define debug levels #define     NONE      0 //  Tracing is not on #define     FATAL      1 // Abnormal exit or termination #define     ERROR      2 // Severe errors that need logging #define     WARNING    3  // Warnings such as allocation failure #define     INFO       4  // Includes non-error cases such as Entry-Exit #define     TRACE      5 // Detailed traces from intermediate steps #define     LOUD       6  // Detailed trace from every step 

В таком случае XML секция примет следующий вид:

<Levels>                                          <Trace>                                           <WPP Text="LOUD"/>         </Trace>                                      <Debug>                                           <WPP Text="TRACE"/>         </Debug>                                      <Info>                                            <WPP Text="INFO"/>     </Info>                                       <Warning>                                         <WPP Text="WARNING"/>         </Warning>                                    <Error>                                           <WPP Text="ERROR"/>           </Error>                                      <Critical>                                        <WPP Text="FATAL"/>           </Critical>                               </Levels>        
Старт

Вот и все, редактирование конфигурационного файла закончено, можно приступать к запуску. В каком порядке Вы будете запускать Байкал и Ангару — не имеет значения, но разумно запустить Байкал первым, чтоб иметь возможность принять все отправленные сообщения, только не забудьте вежливо попросить Ваш межсетевой экран (Firewall) не блокировать трафик между Ангарой и Байкалом.
Запуск Ангары очень прост:

Angara_32.exe Angara.xml #либо Angara_64.exe Angara.xml 

Пример работы Ангары:

N.B. : На старых ОС (Windows 2k, XP) сессия ETW не может стабильно работать без промежуточного файла, поэтому при запуске Ангары на этих версиях ОС следует помнить, что Ангара попытается создать несколько временных файлов суммарным объемом от 250 Мб до 1 Гб, в случае неудачи – процесс завершится.

Внешний вид

Весь графический интерфейс, а вернее — его отсутствие, можно описать следующей картинкой:
image
Помимо статической информации о сессии, предоставляются 12 различных счетчиков, достаточно большое и, на данный момент, избыточное кол-во информации. Они были нужны на этапе активной отладки программы и позволяли достаточно точно детектировать проблемное место, сейчас это лишь исторический пережиток, который оставлен с целью технической возможности мониторинга. Счетчики делятся на 3 группы:

  • Главная статистика (Angara):
    • Send – количество отправленных сообщений
    • Rejected – суммарное (по всем причинам) количество отклоненных к отправке сообщений
    • Unknown – количество неопознанных сообщений, этот счетчик увеличивается каждый раз когда приходит сообщение описание которого не может быть найдено в TMF файлах. Возможная причина – отсутствие необходимого TMF файла либо TMF файл устарел (не был сгенерирован после компиляции драйвера)
    • TPS – приблизительное количество отсылаемых сообщений в секунду

  • Сетевая статистика (P7):
    • Free mem. – процент свободной внутренней памяти.
    • Rej. No connect. — количество отклоненных к отправке сообщений по причине отсутствия соединения с сервером (Байкал)
    • Rej. No Memory — количество отклоненных к отправке сообщений по причине нехватки памяти
    • Rej. Internal — количество отклоненных к отправке сообщений по причине внутренних сбоев

  • Статистика ETW:
    • Traces lost – количество потерянных сообщений внутри ETW
    • Buffers lost — количество потерянных буферов внутри ETW
    • RealT. Buf. lost — количество потерянных буферов реального времени внутри ETW
    • Broken Seq. – количество неучтенных потерь ETW, мониторинг происходит исходя из предположения, что номера приходящих сообщений увеличиваются линейно на единицу

Заключение

На этом мое повествование заканчивается, я надеюсь, что представленные здесь утилиты облегчат нелегкую, но творческую жизнь разработчиков драйверов и прикладного ПО.

PS: Сайт проекта с исходными кодами и бинарными файлами, а так же англоязычная справка.
PPS: Baical — это не случайная опечатка.

ссылка на оригинал статьи http://habrahabr.ru/post/156817/

Интернационализация локального проекта django

Хорошо, когда при разработке проекта под django, разработчики проекта изначально озаботились его интернационализацией.

Минимальными усилиями, проект адаптируется под различные языки. Django имеет богатый набор инструментов, достаточный для почти автоматического добавления новых языков, исправления и добавления переводов отдельных участков текста и так далее.

Ситуация выглядит совсем иначе, если проект изначально не предназначался для интернационализации. Огромный массив файлов, в которых разбросаны локальные строки в совершеннейшем беспорядке, при этом многие из них дублируются в разных файлах. Собирать все эти строчки в один файл, сортировать, заменять их содержимое в исходных файлах на идентификаторы сообщений — огромная и неблагодарная работа.

Встретившись с этой задачей, я понял, что выполняя ее вручную, я умру от скуки, если прежде того меня не стошнит. При этом я с удивлением обнаружил, что инструментов, которые бы облегчали мне жизнь хотя бы наполовину, до сих пор нет. Четыре дня работы — и на свет появился проект django-make-i18n, который я вам и представляю.

Всю работу выполняет один достаточно объемный скрипт на python. Дополнительно к питону (у меня 2.7), сам скрипт зависит только от polib и не требует наличия окружения django.

Запуская скрипт в первый раз и напуская его на каталог проекта, вы получаете заготовку файла django.po, в которой собраны все обнаруженные строки на локальном (по умолчанию — русском) языке. Пойманные строки размещены в разделах msgstr, а msgid заполнены начальным значением «NEEDS TO BE EDITED [nnn]».

Исходные файлы не изменяются, вместо этого рядом с исходным проектом создается параллельный, с добавлением к имени каталога расширения .i18n.

Далее вам предстоит пройтись по файлу django.po и произвести «обратный перевод», то есть заменить начальные значения msgid каким-нибудь внятным эквивалентом на английском языке. Надо только следить, чтобы у всех строк msgid значения при этом оставались уникальными.

Второй запуск скрипта анализирует файл django.po и производит подстановку обращений к подсистеме перевода вместо исходных локальных строк. Например, допустим Вы имеете файл views.py, в котором размещен следующий код:

    if request.method == 'POST': # If the form has been submitted...         post = True         logging.info('POST запрос обнаружен')         request_form = RequestVideoForm(request.POST)         if request_form.is_valid(): # All validation rules pass             logging.info('Форма верна')             ok = True             send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')             message = u'Ваша заявка была отправлена'             request_form = None             # clean form         else:             message = u'Исправьте данные в форме' 

После первого запуска скрипта, в django.po обнаружатся строки примерно следующего содержания:

msgid "NEEDS TO BE EDITED [333]" msgstr "POST запрос обнаружен"  msgid "NEEDS TO BE EDITED [334]" msgstr "Форма верна"     msgid "NEEDS TO BE EDITED [335]" msgstr "Ваша заявка была отправлена"  msgid "NEEDS TO BE EDITED [336]" msgstr "Исправьте данные в форме"  

Если вы ничего не измените в файле django.po, то после второго запуска скрипта, будет создана копия файла views.py, содержащая примерно следующие строки:

    if request.method == 'POST': # If the form has been submitted...         post = True         logging.info(_('NEEDS TO BE EDITED [333]'))         request_form = RequestVideoForm(request.POST)         if request_form.is_valid(): # All validation rules pass             logging.info(_('NEEDS TO BE EDITED [334]'))             ok = True             send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')             message = _('NEEDS TO BE EDITED [335]')             request_form = None             # clean form         else:             message = _('NEEDS TO BE EDITED [336]')              else:         logging.info(_('NEEDS TO BE EDITED [337]'))         request_form = RequestVideoForm(auto_id=True)  

Попробуем заполнить строки в django.po следующим образом:

msgid "POST request has been found" msgstr "POST запрос обнаружен"  msgid "Form is valid"    msgstr "Форма верна"  msgid "Your request has just been sent" msgstr "Ваша заявка была отправлена"  msgid "Fix form data"    msgstr "Исправьте данные в форме" 

Запускаем скрипт еще раз — и получаем вполне сносный код следующего вида:

    if request.method == 'POST': # If the form has been submitted...         post = True         logging.info(_('POST request has been found'))         request_form = RequestVideoForm(request.POST)         if request_form.is_valid(): # All validation rules pass             logging.info(_('Form is valid'))             ok = True             send_request(request,request_form,request.region.urlname,'feedback@doroga.tv')             message = _('Your request has just been sent')             request_form = None             # clean form         else:             message = _('Fix form data')  

Дополнительно, скрипт добавляет в начало файла код импорта пакета интернационализации:

from django.utils.translation import ugettext as _ 

на случай, если вы случайно забыли сделать это.

Те же операции, с учетом специфики языка и использования django, выполняются на файлах html и js. При этом для JavaScript создается файл djangojs.po.

Осталось скомпилировать сообщения:

python manage.py compilemessages --all 

Вуаля — ваш проект подготовлен к интернализации. Конечно, еще остается много всяких деталей самой интернационализации под django, но они выходят за рамки данной статьи.

ссылка на оригинал статьи http://habrahabr.ru/post/156879/

Яндекс.Деньги продается

На «Яндексе» появился пресс-релиз: Яндекс объявляет финансовые результаты за III квартал 2012 года.

В конце пресс-релиза есть интересная ссылка: "Полная версия пресс-релиза (на английском языке)". Там можно найти интересную информацию:

Balance Sheet

As of September 30, 2012, Yandex had cash, cash equivalents, term deposits (including long-term deposits) and long-term debt securities of RUR 24.3 billion ($785.9 million).

Assets and liabilities related to the operations of Yandex.Money, our proprietary electronic payments system, have been reclassified on the balance sheet as assets of RUR 1.7 billion, ($56.0 million) and liabilities of RUR 1.3 billion ($42.7 million), respectively, held for sale, as we are actively seeking to transfer majority control of Yandex.Money to a strategic buyer.

Яндекс.Деньги планируют продать контрольную долю стратегическому покупателю, а решение об этом, судя по всему, было принято давно. И вполне возможно, что многие последние нововведения в системе (в том числе и прием платежей на счет банковским переводом из любой страны) — это подготовка к продаже.

Выходит, что балансовая стоимость «Яндекс.Денег» — 1,7 млрд рублей, обязательства — 1,3 млрд рублей (так перевели в "Интерфакс-Украина"). В итоге можно сделать вывод о том, что чистая стоимость капитала «Яндекс.Денег» — 400 млн. рублей при обязательствах в 1,3 млрд. рублей.

ссылка на оригинал статьи http://habrahabr.ru/post/156885/

Яндекс.Деньги продается

На «Яндексе» появился пресс-релиз: Яндекс объявляет финансовые результаты за III квартал 2012 года.

В конце пресс-релиза есть интересная ссылка: "Полная версия пресс-релиза (на английском языке)". Там можно найти интересную информацию:

Balance Sheet

As of September 30, 2012, Yandex had cash, cash equivalents, term deposits (including long-term deposits) and long-term debt securities of RUR 24.3 billion ($785.9 million).

Assets and liabilities related to the operations of Yandex.Money, our proprietary electronic payments system, have been reclassified on the balance sheet as assets of RUR 1.7 billion, ($56.0 million) and liabilities of RUR 1.3 billion ($42.7 million), respectively, held for sale, as we are actively seeking to transfer majority control of Yandex.Money to a strategic buyer.

Яндекс.Деньги планируют продать контрольную долю стратегическому покупателю, а решение об этом, судя по всему, было принято давно. И вполне возможно, что многие последние нововведения в системе (в том числе и прием платежей на счет банковским переводом из любой страны) — это подготовка к продаже.

Выходит, что балансовая стоимость «Яндекс.Денег» — 1,7 млрд рублей, обязательства — 1,3 млрд рублей (так перевели в "Интерфакс-Украина"). В итоге можно сделать вывод о том, что чистая стоимость капитала «Яндекс.Денег» — 400 млн. рублей при обязательствах в 1,3 млрд. рублей.

ссылка на оригинал статьи http://habrahabr.ru/post/156883/

анимированное облако тегов на css3

Захотелось моей половинке анимированное облако тегов в ЖЖ. Казалось бы, в сети полным-полно вариаций на эту тему: крутящихся, интерактивных, выбирай любое. Но всё это богатство либо на javascript, либо на flash. И прикрутить это к журналу нельзя (стандартный аккаунт, про платные не в курсе).

Нужно было вращающееся облако тегов, написанное на чистом css3. Сразу оговорюсь, решить задачу удалось лишь частично. Попытки что-то лучшее найти не увенчались успехом, в свое время даже публиковал вопрос на Хабре.

Собственно, вот что у меня получилось:
github.com/paratrooper5730/css3AnimatedTagcloud (код)
3611.livejournal.com/ (журнал с примером).

Для создания анимации, создается правило @keyframes, в котором указаны начальное, конечное, и, опционально, промежуточные свойства объекта. А для самого объекта указываются свойства animation-name, animation-duration, animation-timing-function, animation-delay, animation-iteration-count, animation-direction. Таким образом оперделяется, какие преобразования происходят с объектом, с какой скоростью и в каком направлении. Есть много учебных ресурсов на эту тему, я пользовался w3schools.com.

Сразу перейду к ограничениям, на которые я наткнулся.
В свойстве animation-name для одного объекта можно указать несколько @keyframes, но они будут выполняться одновременно — нельзя зациклить одно преобразование с периодами в 10 секунд и параллельно другое с периодами в 5.
Возможности animation-timing-function очень ограничены. Теоретически, можно прописать какое угодно поведение объектов, с помощию большого количества промежуточных состояний в @keyframes. Но на практике, анимация шла неказисто, с рывками.

Пришлось упростить самому себе задачу: «дальняя» часть облака не видна, элементы появляются из небытия, и туда же уходят.

Для этого я использую 2 преобразования.
Вот это отвечает за движение сверху вниз:
@keyframes tagmove { from { top:-80px; } to { top:80px; } }
А вот это — за «выплывание» тегов с заднего плана на передний и обратно
@keyframes coloring { from { opacity: 0; } 50% { opacity: 1; } to { opacity: 0; } }

Чтобы облако было равномерным и красивым, может потребоваться подогнать параметры animation-duration и animation-delay для разных эелементов. Значения, которые там прописаны — это рукотворный рандом. Также можно заморочиться и использовать абсолютное позиционирование, чего я делать не стал. Исходное расположение Тегов в облаке дает нужный псевдослучайный разброс по горизонтали и вертикали. Последний можно уменьшить с помощью line-height.

Вот, пожалуй, и всё. Буду рад советам, как сделать лучше

ссылка на оригинал статьи http://habrahabr.ru/post/156873/