Поделиться через


Анализ журналов веб-сайтов с помощью пользовательской библиотеки Python с кластером Apache Spark в HDInsight

В этой записной книжке показано, как анализировать данные журнала с помощью пользовательской библиотеки с Apache Spark в HDInsight. Используемая пользовательская библиотека — это библиотека Python с именем iislogparser.py.

Предпосылки

Кластер Apache Spark в HDInsight. Для получения инструкций см. Создание кластеров Apache Spark в Azure HDInsight.

Сохранение необработанных данных в виде RDD

В этом разделе мы используем Jupyter Notebook, связанный с кластером Apache Spark в HDInsight, для выполнения заданий, обрабатывающих необработанные образцы данных и сохраняем их в виде таблицы Hive. Пример данных — это файл .csv (hvac.csv), доступный во всех кластерах по умолчанию.

После сохранения данных в качестве таблицы Apache Hive в следующем разделе мы подключимся к таблице Hive с помощью таких средств бизнес-аналитики, как Power BI и Tableau.

  1. В веб-браузере перейдите на страницу https://CLUSTERNAME.azurehdinsight.net/jupyter, где CLUSTERNAME — это имя вашего кластера.

  2. Создайте новую записную книжку. Выберите "Создать", а затем PySpark.

    Создайте новую записную книжку Apache Jupyter Notebook. Notebook" border="true":::

  3. Будет создана и открыта записная книжка с именем Untitled.pynb. Выберите название блокнота в верхней части и введите понятное имя.

    Укажите имя записной книжки.

  4. Так как вы создали записную книжку с помощью ядра PySpark, вам не нужно явно создавать контексты. Контексты Spark и Hive автоматически создаются при запуске первой ячейки кода. Сначала можно импортировать типы, необходимые для этого сценария. Вставьте следующий фрагмент кода в пустую ячейку и нажмите клавиши SHIFT+ВВОД.

    from pyspark.sql import Row
    from pyspark.sql.types import *
    
  5. Создайте RDD с помощью примеров данных журнала, уже доступных в кластере. Вы можете получить доступ к данным в учетной записи хранения по умолчанию, связанной с кластером \HdiSamples\HdiSamples\WebsiteLogSampleData\SampleLog\909f2b.log. Выполните следующий код:

    logs = sc.textFile('wasbs:///HdiSamples/HdiSamples/WebsiteLogSampleData/SampleLog/909f2b.log')
    
  6. Извлеките образец журнала, чтобы убедиться, что предыдущий шаг выполнен успешно.

    logs.take(5)
    

    Должен отобразиться результат, аналогичный приведенному ниже:

    [u'#Software: Microsoft Internet Information Services 8.0',
    u'#Fields: date time s-sitename cs-method cs-uri-stem cs-uri-query s-port cs-username c-ip cs(User-Agent) cs(Cookie) cs(Referer) cs-host sc-status sc-substatus sc-win32-status sc-bytes cs-bytes time-taken',
    u'2014-01-01 02:01:09 SAMPLEWEBSITE GET /blogposts/mvc4/step2.png X-ARR-LOG-ID=2ec4b8ad-3cf0-4442-93ab-837317ece6a1 80 - 1.54.23.196 Mozilla/5.0+(Windows+NT+6.3;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36 - http://weblogs.asp.net/sample/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx www.sample.com 200 0 0 53175 871 46',
    u'2014-01-01 02:01:09 SAMPLEWEBSITE GET /blogposts/mvc4/step3.png X-ARR-LOG-ID=9eace870-2f49-4efd-b204-0d170da46b4a 80 - 1.54.23.196 Mozilla/5.0+(Windows+NT+6.3;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36 - http://weblogs.asp.net/sample/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx www.sample.com 200 0 0 51237 871 32',
    u'2014-01-01 02:01:09 SAMPLEWEBSITE GET /blogposts/mvc4/step4.png X-ARR-LOG-ID=4bea5b3d-8ac9-46c9-9b8c-ec3e9500cbea 80 - 1.54.23.196 Mozilla/5.0+(Windows+NT+6.3;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36 - http://weblogs.asp.net/sample/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx www.sample.com 200 0 0 72177 871 47']
    

Анализ данных журнала с помощью пользовательской библиотеки Python

  1. В выводе выше первые строки включают сведения о заголовке, а каждая из оставшихся строк соответствует схеме, описанной в этом заголовке. Анализ таких журналов может быть сложным. Поэтому мы используем пользовательскую библиотеку Python (iislogparser.py), что упрощает анализ таких журналов. По умолчанию эта библиотека включена в кластер Spark в HDInsight /HdiSamples/HdiSamples/WebsiteLogSampleData/iislogparser.py.

    Однако этой библиотеки нет в PYTHONPATH, поэтому мы не можем использовать ее с помощью инструкции импорта, например import iislogparser. Чтобы использовать эту библиотеку, необходимо распространить ее на все рабочие узлы. Выполните следующий фрагмент кода.

    sc.addPyFile('wasbs:///HdiSamples/HdiSamples/WebsiteLogSampleData/iislogparser.py')
    
  2. iislogparser предоставляет функцию parse_log_line , возвращающую None , если строка журнала является строкой заголовка LogLine , и возвращает экземпляр класса, если он встречает строку журнала. LogLine Используйте класс для извлечения только строк журнала из RDD:

    def parse_line(l):
        import iislogparser
        return iislogparser.parse_log_line(l)
    logLines = logs.map(parse_line).filter(lambda p: p is not None).cache()
    
  3. Получите пару извлеченных строк журнала, чтобы убедиться, что шаг выполнен успешно.

    logLines.take(2)
    

    Выходные данные должны быть похожи на следующий текст:

    [2014-01-01 02:01:09 SAMPLEWEBSITE GET /blogposts/mvc4/step2.png X-ARR-LOG-ID=2ec4b8ad-3cf0-4442-93ab-837317ece6a1 80 - 1.54.23.196 Mozilla/5.0+(Windows+NT+6.3;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36 - http://weblogs.asp.net/sample/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx www.sample.com 200 0 0 53175 871 46,
    2014-01-01 02:01:09 SAMPLEWEBSITE GET /blogposts/mvc4/step3.png X-ARR-LOG-ID=9eace870-2f49-4efd-b204-0d170da46b4a 80 - 1.54.23.196 Mozilla/5.0+(Windows+NT+6.3;+WOW64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/31.0.1650.63+Safari/537.36 - http://weblogs.asp.net/sample/archive/2007/12/09/asp-net-mvc-framework-part-4-handling-form-edit-and-post-scenarios.aspx www.sample.com 200 0 0 51237 871 32]
    
  4. Класс LogLine , в свою очередь, имеет некоторые полезные методы, например is_error(), которые возвращают, имеет ли запись журнала код ошибки. Этот класс позволяет вычислить количество ошибок в извлеченных строках журнала, а затем записать все ошибки в другой файл.

    errors = logLines.filter(lambda p: p.is_error())
    numLines = logLines.count()
    numErrors = errors.count()
    print 'There are', numErrors, 'errors and', numLines, 'log entries'
    errors.map(lambda p: str(p)).saveAsTextFile('wasbs:///HdiSamples/HdiSamples/WebsiteLogSampleData/SampleLog/909f2b-2.log')
    

    Выходные данные должны содержать состояние There are 30 errors and 646 log entries.

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

    def avgTimeTakenByKey(rdd):
        return rdd.combineByKey(lambda line: (line.time_taken, 1),
                                lambda x, line: (x[0] + line.time_taken, x[1] + 1),
                                lambda x, y: (x[0] + y[0], x[1] + y[1]))\
                    .map(lambda x: (x[0], float(x[1][0]) / float(x[1][1])))
    
    avgTimeTakenByKey(logLines.map(lambda p: (p.cs_uri_stem, p))).top(25, lambda x: x[1])
    

    Выходные данные должны отображаться следующим образом:

    [(u'/blogposts/mvc4/step13.png', 197.5),
    (u'/blogposts/mvc2/step10.jpg', 179.5),
    (u'/blogposts/extractusercontrol/step5.png', 170.0),
    (u'/blogposts/mvc4/step8.png', 159.0),
    (u'/blogposts/mvcrouting/step22.jpg', 155.0),
    (u'/blogposts/mvcrouting/step3.jpg', 152.0),
    (u'/blogposts/linqsproc1/step16.jpg', 138.75),
    (u'/blogposts/linqsproc1/step26.jpg', 137.33333333333334),
    (u'/blogposts/vs2008javascript/step10.jpg', 127.0),
    (u'/blogposts/nested/step2.jpg', 126.0),
    (u'/blogposts/adminpack/step1.png', 124.0),
    (u'/BlogPosts/datalistpaging/step2.png', 118.0),
    (u'/blogposts/mvc4/step35.png', 117.0),
    (u'/blogposts/mvcrouting/step2.jpg', 116.5),
    (u'/blogposts/aboutme/basketball.jpg', 109.0),
    (u'/blogposts/anonymoustypes/step11.jpg', 109.0),
    (u'/blogposts/mvc4/step12.png', 106.0),
    (u'/blogposts/linq8/step0.jpg', 105.5),
    (u'/blogposts/mvc2/step18.jpg', 104.0),
    (u'/blogposts/mvc2/step11.jpg', 104.0),
    (u'/blogposts/mvcrouting/step1.jpg', 104.0),
    (u'/blogposts/extractusercontrol/step1.png', 103.0),
    (u'/blogposts/sqlvideos/sqlvideos.jpg', 102.0),
    (u'/blogposts/mvcrouting/step21.jpg', 101.0),
    (u'/blogposts/mvc4/step1.png', 98.0)]
    
  6. Эти сведения также можно представить в виде графика. На первом шаге к созданию графика давайте сначала создадим временную таблицу AverageTime. Таблица группирует журналы по времени, чтобы узнать, были ли какие-либо необычные пики задержки в любое время.

    avgTimeTakenByMinute = avgTimeTakenByKey(logLines.map(lambda p: (p.datetime.minute, p))).sortByKey()
    schema = StructType([StructField('Minutes', IntegerType(), True),
                        StructField('Time', FloatType(), True)])
    
    avgTimeTakenByMinuteDF = sqlContext.createDataFrame(avgTimeTakenByMinute, schema)
    avgTimeTakenByMinuteDF.registerTempTable('AverageTime')
    
  7. Затем можно запустить следующий SQL-запрос, чтобы получить все записи в таблице AverageTime .

    %%sql -o averagetime
    SELECT * FROM AverageTime
    

    Магия %%sql, которая идет за -o averagetime, гарантирует, что выходные данные запроса сохраняются локально на сервере Jupyter (обычно это головной узел кластера). Выходные данные сохраняются в виде кадра данных Pandas с заданным названием averagetime.

    Вы должны увидеть выходные данные, как показано на следующем рисунке:

    Выходные данные запроса hdinsight Jupyter SQL. yter sql query output" border="true":::

    Для получения дополнительной информации о %%sql магии см. Параметры, поддерживаемые магией %%sql.

  8. Теперь можно использовать Matplotlib, библиотеку, используемую для создания визуализации данных, для создания диаграммы. Поскольку диаграмма должна быть создана из локально сохраненного кадра данных averagetime, фрагмент кода должен начинаться с магической команды %%local. Это гарантирует, что код выполняется локально на сервере Jupyter.

    %%local
    %matplotlib inline
    import matplotlib.pyplot as plt
    
    plt.plot(averagetime['Minutes'], averagetime['Time'], marker='o', linestyle='--')
    plt.xlabel('Time (min)')
    plt.ylabel('Average time taken for request (ms)')
    

    Вы должны увидеть выходные данные, как показано на следующем рисунке:

    График анализа веб-журнала apache Spark. График анализа журналов eb" border="true":::

  9. После завершения работы приложения необходимо завершить работу записной книжки, чтобы освободить ресурсы. Для этого в меню File (Файл) записной книжки выберите пункт Close and Halt (Закрыть и остановить). Это действие завершит работу и закроет записную книжку.

Дальнейшие действия

Ознакомьтесь со следующими статьями: