Categories

Checkio.ORG

Subscribe to Posts

Email:

  • 04Feb

    Мы продолжаем дарить добро.

    1. django.jQuery(function(){
    2.     $('body').append('<iframe name="fast_save" width="1" height="1"></iframe>');
    3.     $('.submit-row').append('<input class="fast_save" type="button" value="Fast save">');
    4.     $('.submit-row .fast_save').click(function(){
    5.         $('#task_form').attr('target','fast_save').submit().removeAttr('target');
    6.     })
    7. })

    А от какого гемороя избавляют эти красавцы – догодайтесь сами. Обязательно курить вместе со “4мя css строчками счастья”

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , , ,

  • 03Feb

    Меня за….ло скролить длинные админки туда-сюда ради сабмита и вот

    1. .submit-row{
    2.     position: fixed;
    3.     z-index: 100;
    4.     left: 220px;
    5.     top: 0;
    6. }

    И панель наконецто просто начинает за вами кататься

    А чем ты занимаешься в свой выходной? :)

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , ,

  • 14Aug

    Ура. Мы всетаки раскачались на полноценный Event и не без помощи наших друзей из Харькова и Киева.

    Формат city.py – доклады, прерываемые дебошем и кофебрейками.

    Наш официальный сайт dneprpy.org.ua

    Мы в соц. сетях – FaceBook, Twitter, Google+

    Хотелось бы встретися со старыми друзьями, которых давно не видел. А также познакомится с новыми. Незабываем регистрироваться.

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]
  • 29Jul


    Вся вы знаете, что PyCon Ukraine неудержимо приближается к нам. И для всего украинского python сообщества это чуть ли не самое ожидаемое событие. И это не только возможность услышать доклады питон-гуру, которых, благодаря организаторам, съезжается очень много и из разных точек мира ( В прошлом году uapycon шел в 2х залах одновременно и 2 дня под ряд ) . Но еще и это возможность встрериться с теми, с кем вы общались в чатах, форумах, твитерах. Встретится с теми, кто оценивал ваши вырвимозг идеи и давал ценные советы. И наконец-то поболтать в живую с ними за чашечкой чего-нибудь вкусного :)

    Перед самим PyCon по Украине проходит волна city.py. Donetsk.py организатор CNC, Odessa.py организатор Mikhail Kashkin, kharkiv.py организатор Ivan Kolodyazhny и kyiv.py организовывается Volodymyr Hotsyk. На все из них можете попасть и вы, и участие в них абсолютно бесплатно. Да и те из вас, кто захочет выступить на PyCon – может быть отличной практикой сделать это сначала на одно из city.py

    Меня давно не покидает мысль – что Днепр тоже не хуже. И вообще не понятно, почему днепровcкие питонщики до сих пор не собрались на пивко.

    Многие из нас делаю что-то необычное – самое время об этом рассказать! Или открыли для себя что-то новое – поделитесь, возможно вас отговорят это использовать :)

    Я знаю довольно много питонщиков-земляков, но с еще большими хотел бы познакомится.

    Что скажите народ? Есть кому что рассказать? Поделится опытом? Идеями? Может кто-то хочет попробовать себя в роли докладчика впервые?

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags:

  • 11Apr

    Мыль, коротка, убейте критикой.

    Ксательно орм и бд.

    Если У Вас есть один обхект данных – например пользователь, который имеет различные свойтства, например имя, баланс, статистика.

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

    Что скажите? Не понятно?

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: ,

  • 08Apr

    django-ucsvlog и django-ucsvlog-analytics также перехали на github. Код там не сильно грязный, но за усердную отчистку и покрытие тестами еще не садился.

    у python-ucsvlog небольшое обновлени в формате логов. Т.к. формат строки через “%” – это прошлый век, и format рулит – темлпейт для имен файлов поменялся, так что теперь файл лога с дневным рендерингом будет выглядить примерно так /var/log/django/{year}-{month}-{day}.ucsv

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , , , ,

  • 07Apr

    По многочисленным заявкам python-ucsvlog переехал на github https://github.com/oduvan/python-ucsvlog

    Но не просто переехали, а переехали c почищенным кодом, с коменами, с рефакторингом, оставили только нужное, прибрались в тестах.

    Рассчитываю на вашу критику.

    ПС: Вот так вот выглядит дифф в пеп8 :)

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 04Apr

    1ого апреля в Киеве в офисе Ciklum состаялась 6ая KyivPy конференция. На которую я “пролез” со своими UCSVLOG. После конфы и общения с людьми я ушел с полной уверенностью в том, что это нужно, и что люди устали от мусора и бесполезности своих логов. Поэтому уже дома я подготовил серию из трех статей о моем докладе на KyivPy

    Часть 1. Проблема и Идея – о всех своих негодованиях на тему классических схем ведения логов и идея, как это может быть исправлено

    Часть 2. Решение – чуть более детально про принципы ведения UCSVLOG

    Часть 3. Плюшки – Какая функциональная база для аналитики уже голова у нас, и как вы ее можете расширять и использовать.

    Видео Видео, за которое спасибо @Andrew Bananos – где-то минут 20 сам доклад, и 15 мин ответы на вопросы

    Спасибо Володе за организацию и за возможность встретиться с людьми, с которыми ты так долго общался в сети. Уже жду следующего пая.

    Из проектов в сети по схожей теме стоим обратить внимание не splunk.com – спасибо Максу за наводку. loggly.com и Solr от Apache – спасибо Василию за наводку.

    Кста. Харьков, Одесса и Донецк уже организивали свои Py и не по одному разу. Почему Днепр отстает. Если организовывать подобное действо у нас в Днепре – желающие прийти послушать / рассказать / поглядеть будут?

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

  • 04Apr

    Продолжаем о UCSVLOG. Начало читайте тут – Часть 1. Проблема и Идея, потом тут мы продолжили – Часть 2. Решение , ну а сейчас о плюхах

     Плюшки это типо сладости, которые тебе дают, если ты прилежно все делаешь. Так и с логами. Если ты правильно и аккуратно их пишешь – то в результате получаешь правильную и четкую аналитику любой сложности и не только.

    django-ucsvlog

    Проект лежит на bitbucket.org

     Первым для себя применением ucsvlog я нашел в как апой к Django. Он был создан за долго до того, как у Django появились свои логи. И пока миграцию на них я не планирую, а думаю, как объеденить и взять что-то хорошее с джанговских и сделать процесс миграции с джанговских на UCSVLOG более простым.

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

     Первая ‘djucsvlog.middleware.LogRequestInfo‘ идет как самой первой в Вашем списке мидлварь,а значит должна запускаться еще до того, как какая-либо из них начнет работать.

     Она открывает блок, в который кладется информация о запросе, а в settings задается список полей которые мы хотим записываться, например имя домена, путь, гет, пост параметры, файлы или BROWSER_UUID_COOKIE.

    BROWSER_UUID_COOKIE – это простой механизм, который по средствам кук следит за действиями пользователя. Когда приходит пользователь и у нег нет нашей куки – мы ему создаем ее и при каждом его запросе кладет ее в лог. Далее это позволит сводить свою аналитику.
    Как дополнительная возможность – это вести лог файлов, которые аплоадит пользователей. Т.е. мы в отдельное место сохраняем все аплоады пользователей, а в логах отмечаем – что и куда мы сохранено.

     Вторая ‘djucsvlog.middleware.LogViewInfo‘ записывается последней мидлварей, она опциональная, т.е. работать будет и без нее, сюда кладется инфа накопленная с других мидлварь, например информация о залогиненом пользователе или любая другая информация, которая может быть собранная уже с ваших мидлварь.

     Последнее – это указать у себя в сетингсах шаблон имени файла UCSVLOG_FILE, и можно начинать играться.

     Во время работы сам объект логера лежит в глобальной области видимости. Т.е. воспользоваться им можно в любой момент.

     За время работы с django-ucsvlog у нас накопилось много настроек для кастомизации этих логов. Все они лежат в djucsvlog.settings.py немного документированные, в лучших традициях опенсорса, с указанием дефолтных значений. Такие как – правило формирования отчет об ексепшене, буферизация, правило определение IP пользователя, возможность сохранять отдельно загружаемые файлы, а в лог класть инфу о том, куда мы сохранили текущий загруженый файл.
     + UCSVLOG_CHANGE_MODEL в этом дикте можно указать – за изменением каких моделей вы хотите следить ( предварительно указав ‘djucsvlog.components.change_model’ в списке компонентов UCSVLOG_COMPONENTS ), и какие поля этих моделей вы хотите класть в лог файл в момент их изменения. Т.е. теперь благодаря логам вы можете связывать изменения любой модели с определенным пользователем – ваще мечта.

    Пример settings.py вашего приложения:

    1. MIDDLEWARE_CLASSES = (
    2.     'djucsvlog.middleware.LogRequestInfo', ##первый
    3.     'django.middleware.common.CommonMiddleware',
    4.     'django.contrib.sessions.middleware.SessionMiddleware',
    5.     'django.middleware.csrf.CsrfViewMiddleware',
    6.     'django.middleware.locale.LocaleMiddleware',
    7.     'django.contrib.auth.middleware.AuthenticationMiddleware',
    8.     'django.contrib.messages.middleware.MessageMiddleware',
    9.     'django.middleware.transaction.TransactionMiddleware',
    10.     'djucsvlog.middleware.LogViewInfo', ## Второй
    11. )
    12. UCSVLOG_COMPONENTS = (
    13.         'djucsvlog.components.change_model',
    14.     ) # указываем список компонентов ( расширений )
    15.  
    16. UCSVLOG_FILE_VERSION = 'v3' # о смысле такого хука мы расскажем позже
    17. UCSVLOG_FILE = '/var/log/django/console-%(year)s-%(month)s-%(day)s-'+UCSVLOG_FILE_VERSION+'.ucsv'
    18.  
    19. #  По умолчанию False тоже, но если мы хотим, чтоб логи не велись, а выводились в консоль то делаем тру
    20. UCSVLOG_PRINT = False
    21.  
    22. # Эти поля будут класться в лог в момент закрытия блока запроса, т.е. в самом конце
    23. UCSVLOG_RESPONSE_FIELDS = ['status','ctype','content']
    24.  
    25. # кастомные пользовательские функции для логирования
    26. def server_ip(request,*args,**kwargs):
    27.     return request.META.get('REMOTE_ADDR', '0.0.0.0')
    28.  
    29. def ucsvlog_last_login(request,*args,**kwargs):
    30.     return request.session.get('last_login','')
    31.  
    32. # поля, которые мы созраняем при открытии реквеста ( в первой мидлвари )
    33. UCSVLOG_REQUEST_FIELDS = ['http_host','browser_uuid','remote_addr',server_ip,\
    34.               'path','get','post','save_files','http_user_agent',\
    35.               'http_referer','http_accept_language']
    36.  
    37. UCSVLOG_VIEW_OPEN_FIELDS = ['userid',ucsvlog_last_login] # во второй мидлвари
    38. UCSVLOG_RESPONSE_FIELDS = ['ctype','content','status','headers'] #при закрытии
    39. UCSVLOG_REQUEST_REQ_REMOTE_ADDR_REAL_IP = 'HTTP_X_REAL_IP'
    40. # каталог с исходниками, относительно него будет писаться инфа о вызове функций
    41. UCSVLOG_RELATED_FOLDER = PRJ_ROOT

    Большая часть этих настроек имеют значения по умолчанию, поэтому заведется и с такими вот:

    1. MIDDLEWARE_CLASSES = (
    2.     'djucsvlog.middleware.LogRequestInfo', ##первый
    3.     'django.middleware.common.CommonMiddleware',
    4.     'django.contrib.sessions.middleware.SessionMiddleware',
    5.     'django.middleware.csrf.CsrfViewMiddleware',
    6.     'django.middleware.locale.LocaleMiddleware',
    7.     'django.contrib.auth.middleware.AuthenticationMiddleware',
    8.     'django.contrib.messages.middleware.MessageMiddleware',
    9.     'django.middleware.transaction.TransactionMiddleware',
    10.     'djucsvlog.middleware.LogViewInfo', ## Второй
    11. )
    12. UCSVLOG_FILE = '/var/log/django/console-%(year)s-%(month)s-%(day)s.ucsv'

    django-ucsvlog-analytics

    Проект лежит на bitbucket.org

     Но все самое вкусное для этих логов, благодаря их хорошей структуризации – должно лежать в аналитике.
     Аналитике представленна набором базовых коммнад, которые расширяются исходя из нужд конкретной задачи.
     Приятной особенностью в написании логов является то, что на вход функций анализа приходят не массивы, а объекты класса Row , у которого есть множество свойтсв, заполеныне исходя из настроек django-ucsvlog. Т.к. к примеру, когда приходит row из первого индекса реквеста то у него уже есть к примеру аттрибуты row.data_path или row.data_ip
     Но этот бонус также накладывает и свои ограничения, о которых я расскажу позже.

    BaseSimpleAnalyticCommand – простой анализатор

     Это самый простой метод анализа. Подходит в случае если вы своим логам хотите задать все один и довольно конктерный вопрос. “Дай мне количество хитов за период?” или “Дай мне топ стран”. В этом случае команде кормится набор логфайлов, а в вашу функцию collect_row передаются объекты строк, где вы можете проводить анализ и выдавать пользователю. Тут в принципе ничего сверхествественного не происходит.

     Вот пример команды, которая собирает из Ваших логов топ accepted languages

    1. from djucsvlog_analytics.analytic_commands import BaseSimpleAnalyticCommand
    2.  
    3. class Command(BaseSimpleAnalyticCommand):
    4.     data = {}
    5.     # переопределяя эту функцию – вы указываете,
    6.     # какие записи вы ходите видеть в анализе
    7.     # в нашем случае мы хотим видеть только
    8.     # первые записи блока реквеста,
    9.     # потому что только в них есть инфа о
    10.     # браузере пользователя
    11.     def filter_row(self,row):
    12.         return row.is_a_req
    13.    
    14.     # собственно функция анализа тех записей, которые
    15.     # прошли через фильтер
    16.     def collect_row(self,row):
    17.         al = row.data_http_accept_language.\
    18.            split(';')[0].split(',')[0].split('-')[0]
    19.         if al in self.data:
    20.             self.data[al]+=1
    21.         else:
    22.             self.data[al] = 1
    23.  
    24.     # и вывод результатов
    25.     def output_results(self):
    26.         for item in  sorted(self.data.items(),\
    27.                      key=lambda a:a[1]):
    28.             print item[0], item[1]

     Если это сохранить как команду djucsvlog_test_simple_analytics то запуск будет выглядить следующим образом:

    1. $ python manage.py djucsvlog_test_simple_analytics /var/log/django/stats-2012-3-21-v3.ucsv  –settings=settings.analytics

    djucsvlog_user_path_convertor

     Это уже команда на основе базового класса BaseAnalyticCommand ( наследник от BaseSimpleAnalyticCommand ).

     Очень полезна, когда для одних логов вы хотите провести более детальный анализ. Когда Вам нужен не просто маленький отчет, а когда Вам надо разобраться дельано со сложившейся проблемой с трафиком. Это очень похоже на то, когда трафик есть а продаже нет. Почему?

     Идея проста convertor собирает из логов sqlite3 БД и кладет в один файл, при этом может дополнить его информацией о браузере, оси и стране пользователя. Таблици внутри него не просто набор строк, а связные таблицы. Хосты имеют много пользователей, пользователи имеют много реквестов, а реквес имеет много лог записей. Сам этот файл уже по сути часть анализа можно просто зайти в нее и на уровне SQL получать необходимые выборки и сводить статистику.

     djucsvlog_user_path_convertor – это именно наша идея конвертации в такую вот струкруту БД. Если вы заходите сделать свой конвертато в БД, то просто пишите команду, наследник от BaseAnalyticCommand.

    Ниже несколько примеров запуска такой команды в наших проектах

    1. $ python manage.py djucsvlog_user_path_convertor /var/log/django/* \
    2.         –out=/tmp/django.userpath.db

    Это мы просто конвертим все файлы из папки /var/log/django/ в базу

    1. $ python manage.py djucsvlog_user_path_convertor /var/log/django/* \
    2.         –out=/tmp/django.userpath.db –force-new

    Указываем, что если БД уже есть, то в нее не дописывать а создавать заново

    1. $ python manage.py djucsvlog_user_path_convertor /var/log/django/* \
    2.         –out=/tmp/django.userpath.db –force-new\
    3.        –geoip-db=/var/geodb/2012-04-01.db

    Передаем ссылку на базу GEO IP для добавления дополнительного поля со страной

    djucsvlog_user_path_analytics

     Но мы очень быстро поняли, что очень много задач не решаются просто SQL командой, поэтому мы к sqlite3 базе начали дописывать скриптики для ее анализа, и все это свернули в отдельную команды, на вход которой передается один или несколько sqlite файлов и параметры для анализа. Причем параметры разделаются на задачи и на условия. Т.е. мы при вызове команды можем передать ей на вход несколько задач например топ браузеров или топ стран, и условия например пользователи, которые зашли на определенную страницу, пользователи, которые сделали больше определенного количества шагов. Или как связка – дай мне следующий шаг после переданного.

     Сама команда является наследником от BaseAnalyticReadCommand, а задачи являются наследниками от BaseAnalyticElement, список условий передаются при создании элемента задачи

     Ниже несколько примеров использования этой команды:

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db –get-entry-points

    Получаем ТОП точек входа на сайт

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db /tmp/django_2.userpath.db \
    3.        –get-entry-points

    Для анализа можно указывать не один файл

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db /tmp/django_2.userpath.db \
    3.        –get-entry-points –after-path=/

    Какой был следующий шаг после /

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db
    3.        –top-404

    Невероятно полезная команда после переверстки

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db
    3.        –get-country-ip

    Дай топ стран

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db
    3.        –get-country-ip –get-os

    топ стран и топ осей

    1. $ python manage.py djucsvlog_user_path_analytics \
    2.          /tmp/django.userpath.db
    3.        –get-country-ip –get-os –after-steps=3

    топ стран и топ осей пользователей которые сделали на сайте больше 3х шагов

     Тут мне даже сложно будет перечеслить все возможности которые есть у этой команды, а сколько всего Вы еще можете дописать!!! :)

    Следующие 2 возможности особо мне теплы, т.к. кроме того что они добавляют аналитику они еще и существенно облегчают жизнь программисту.

    BaseStreamCommand – отложеная статистика

     Раньше, для сбора онлайн статистики о ваших пользователях – Вам надо было в момент захода этого пользователя раскидывать записи по таблицам и возможно совершать какие-то дополнительные расчеты. Причем это надо было делать максимально быстро, чтоб пользователь не видел никаких задержек. С четко структурированными логами, такими как ucsvlog, нет необходимости делать это в момент захода пользователя. Достаточно просто дочитывать периодически логи, которые пишутся, и уже в момент чтений, уже раскидывать статистику. При этом ваши расчеты уже никого не задерживают. Я назвал это “отложенная статистика”, т.к. мы откладывает всю работу по ее расчет в отдельную команду.

     Вы пишите команду на вход которой подаются новые записи из каталога с логами. Причем подаются эти записи именно в хронологии возникновения их в логах. Т.е. если ваш сервис пишет 10 различных лог файлов одновременно и команда в момент запуска определила, что все они выросли с момента последнего запуска, то она будет выдавать к вам на вход записи с разных файлов в разброс в зависимости от того, где записи появляются раньше. Чтоб аналитика в этом случае была максимально четкой.

     Особенности работы такой команды является индексный файл ( sqlite3 ), в котором она держит данные которые используются между ее вызовами, например такие как – последние размеры лог файлов

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

     Наследника BaseStreamBlockCommand, передает анализу не одну строку,а уже собранный блок.

    BaseConvertBlockCommand – конвертация логов.

     Последней плюшкой анализатора, которая нами в данным момент обкатывается еще – это конвертатор.

     Меня всегда расстраивал тот факт, что логи надо удалять :( А при использования django-ucsvlog апетиты засунуть в них чего по больше только растут, в результате они и стают очень толстыми. Самое грустное, что единственным правилом для удаления логов всегда служил их срок, который прямо пропорционален размеру вашего винта и размеру плодящихся логов. Говоря короче большие логи живут меньше, т.к. надо удалять их быстрее, чтоб освобождать место другим логам.

     Но я не хочу удалять все логи, я хочу удалять из логов только ненужное. Мне через месяц будет неважен call_info т.е. место, где были вызваны эти логи. Мне будет все также все равно на заходы пользователя на всякие информационные страници, или к примеру стуки всяких мониторингов меня тоже будут не волновать. Но я хочу держать как можно дольше процесс совершения покупки и процессинга карты. Для этого и делается конвертатор, который перегоняет логи из толстых, в которых часть инфы актуальна только несколько дней, в тонкие, в которых остается инфа, актуальность которой максимально долгая.

     Ваша команда наследник от BaseConvertBlockCommand легко может с этим справляться.

     Вот пример команды, которая делает это у меня:

    1. class Command(BaseConvertBlockCommand):
    2.     def filter_convert_row(self,row):
    3.         if not row.is_a_req:
    4.             return True
    5.         return not(row.data_path.startswith('/info') \
    6.             or row.data_path.startswith('/test-exception') \
    7.             or row.data_path.startswith('/check-back') \
    8.             or row.data_path.startswith('/calculate-statistics') \
    9.             or row.data_path.startswith('/captcha') \
    10.             or row.data_path.startswith('/media') \
    11.             or row.data_path.startswith('/favicon'))

     Тут указывается фильтр – какие строки надо оставить. Какие столбци надо оставить указывается в сетингсах. Детали смотрите в сетингсах, там под это выделен подраздел.

     Самое приятное в стриминге и конверторе – это то, что абсолютно не важно – сколько сервисов ведут свой лог. У Вас может быть ucsvlog на твистеде, отдельный на Django, еще отдельные логи ведут кроновские команды. А вот стриминг с конвертором берут и объединяют их в один поток, в один файл, где вы в хронологии сможете посмотреть события каждого из них. ( Да и не только питон, сам формат логов очень простой )

    Версионность логов.

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

     Например, когда я только подключил ucsvlog к системе имена всех файлов логов оканчиваются на v1.ucsv. Потом я добавил дополнительные поля в строку открытия реквеста, и изменил формат файлов на v2.ucsv, но также создал файл analytics/v1.py в которую положил настройки для первой версии логов. Теперь когда я буду парсить логи из первой версии я буду использовать этот сетингс.

    1. $ python manage.py djucsvlog_user_path_convertor \
    2.      /var/logs/django/*-v1.ucsv \
    3.      –settings=analytics.v1

    Тоже самое с каждой следующей версией

    Заключение

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

     Вобщем подключайтесь, Вам понравится, я уверен :)

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , , ,

  • 02Apr

    Продолжаем о UCSVLOG. Начало читайте тут – Часть 1. Проблема и Идея

     Давайте, для начала, сформируем еще раз требования к логам.

    * Легко писать / читать. – никто не хочет тратить ресурсы на такую пустяковую операцию, как логи. Они должны быть читабельны глазами без тулсов. И они должны быть простыми – чем проще механизм, тем он надежнее. Соответственно парсинг таких логов не должен быть сильно тяжелым.

    * Shit Happens – отказоустойчивость. Я не хочу сломать структуру логов в момент сбоя. Если в момент записи случится какой-нибудь сбой, то может не дописаться часть записи, и я хочу, чтоб структура такого лога осталась неизменной.

    * Индексы – о них и о их преимуществах мы уже успели рассказать ( Мне не надо про Свету каждый раз рассказывать, достаточно познакомиться один раз )

    python-ucsvlog

    Формат

     Общий формат логов выглядит так:

     Каждая запись должна начинаться с новой строки ( \n ) …

    … а каждая ячейчка должна начинаться с кавычки ( “ ).

     Ячейки должны быть разделены запятыми ( , ) …

    … а кавычка внутри ячейки экранируется двумя кавычками ( “” )

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

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

    Формат данных

      Теперь я расскажу – какие поля и в каком порядке кладутся запись лога

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

    call_info – Опциональна. Информация о месте вызова функции логирования, например имя файла, срока, имя функции, класс, модуль. Список этих данных кастомизируется в момент создания объекта логера.

    log_info – сюда мы кладем классический элемент важности логов dev, err, imp, log. Например при создании логера на продакшене мы можем указать, что не хотим записывать dev-логи.

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

     Как видите логи в этом формате очень гибкие, можно записать сколько угодно много данных, они будут структурированы, А читать их можно не только сначала но и с середины, при этом вы легко найдете начало первой валидной записи.

    CODE

     Теперь давайте посмотрим, как это выглядит в коде.

    1. glog.a_log(‘REQ’,’log_data1’)
    2. glog(‘Hi all’)
    3. glog.log([‘Payment’,’CardNumber’,'4111 *** **** ****’])
    4. glog.a_log(‘IN’,[‘UserID’,98])
    5. glog.imp([‘UserBalance’,1500])
    6. glog.c_log(‘REQ’)

     1 a_log – мы открываем индекс. При открытии можно указывать имя, что-то типа метки, которую можно будет использовать как ссылку в коде. Вообще это не обязательно. Можно им пользоваться как структурированным линейным логом, без открытия индекса. Но я считаю древовидность – большим бонусом, которым надо пользоваться.

    "I1,","a_log,"REQ,"log_data1
    

     2 log – записываем строковые данные. Т.е. запись одной ячейки. Т.к. у нас есть открытый индекс, то все остальные записи идут как его чаилды. А если мы логер используем как функцию, то он автоматом пишет логи с приоритетом log

    "I1,","a_log,"REQ,"log_data1
    "I2,"I1,"log,"Hi all
    

     3 log – запись еще 3х ячеек. Теперь мы явно указали, что приоритетность у нас log, и аргументом передали массив ячеек, которые надо записать

    "I1,","a_log,"REQ,"log_data1
    "I2,"I1,"log,"Hi all
    "I3,"I1,"log,"Payment,"CardNumber,"4111 *** **** ****
    

      4 a_log – открытие еще одного индекса. Все верно, уровень вложенности может быть бесконечный. И при открытии мы также можем указать не только строку, но и массив ячеек

    "I1,","a_log,"REQ,"log_data1
    "I2,"I1,"log,"Hi all
    "I3,"I1,"log,"Payment,"CardNumber,"4111 *** **** ****
    "I4,"I1,"a_log,"IN,"UserID,"98
    

    &emps; 5 imp – запись еще 2х ячеек теперь уже в четвертый индекс, тот, который мы открыли последним. И приоритетность у него img

    "I1,","a_log,"REQ,"log_data1
    "I2,"I1,"log,"Hi all
    "I3,"I1,"log,"Payment,"CardNumber,"4111 *** **** ****
    "I4,"I1,"a_log,"IN,"UserID,"98
    "I5,"I4,"imp,"UserBalance,"1500
    

    &emps; 6 c_log – закрытия индекса. Тут закроются сразу 2 открытых индекса и REQ и IN, потому что мы при закрытии сказали метку открытия индекса. Индекс можно закрывать с записью в лог а можно и без. В закрытие лога как правило кладут результат выполнения этого блока. После закрытия всех индексов ведение записей будет идти без указания родителя, точно так-же как это происходило с первой строкой. А в записи закрытия родителем будет указана тот, кого закрывают, в нашем случае – первый

    "I1,","a_log,"REQ,"log_data1
    "I2,"I1,"log,"Hi all
    "I3,"I1,"log,"Payment,"CardNumber,"4111 *** **** ****
    "I4,"I1,"a_log,"IN,"UserID,"98
    "I5,"I4,"imp,"UserBalance,"1500
    "I6,"I1,"c_log,"REQ
    

      Рендерингом логов занимается сам логер, т.е. при создании логера ему на вход передается не имя файла, а темплейн для его формирования. Например на основе текущей даты. Это очень удобно для того, чтоб блоки не разбрасывались по файлам.

    1. glog = Logger(‘/var/log/%(year)s-%(month)s-%(day)s.ucsv)

     На этом все про ucsvlog как формат, дальше я просто пройдусь по плюшкам, которые мы используем постоянно при работе с ними. Единственное хочу отметить,последнюю идею по этим логам. Как вы помните вначале я рассказал про то, что и строки и записи только открываются, но не закрываются, но это накладывает определенную ответственность на ячейку которая идет вконце записи. Например обратите внимание на 5ую строку.

     Если случится проблема с записью на последней ячейке, которая не допишет пару последних нулей – то это будет большая проблема, т.к. тогда мы будем полностью уверены в том, что у пользователя баланс в 100 раз меньше, поэтому мы ввели дополнительный параметр close_row в котором можно передать значение последней ячейки в каждой записи. И теперь вы можете принимать запись как валидную только в том случае, если ее последним значением является закрывающий символ. Т.е. в нашем случае мы просто скажем что 5ая запись невалидна.

    Репозитарий python-ucsvlog на bitbucket

    и на pypi.python.org Т.е. себе можно поставить pip install python-ucsvlog

    А теперь… плюшки… плюшки….. плюшки…

    Share and Enjoy:
    • Facebook
    • LinkedIn
    • Twitter
    • del.icio.us
    • StumbleUpon
    • MySpace
    • Reddit
    • Digg
    • Google Bookmarks
    • Technorati
    • email
    • Print
    • Sphinn
    • Mixx
    • Blogplay
    • Add to favorites
    • Linkter
    • Live
    • MSN Reporter
    • NewsVine
    • RSS
    • Yahoo! Bookmarks
    • Yahoo! Buzz
    • Yigg
    Rating 3.00 out of 5
    [?]

    Tags: , , ,

« Previous Entries   

Recent Posts

Recent Comments

  • Благодарю, начал изучать fabric с вашей статьи....
  • Идея действительно отличная и очень радует то, что подобн...
  • Спасибо...
  • Там четыре круглых кнопочки. Подразумевается, что каждая ...
  • А в чем заключатеся неправильна работа?...