تحليل سجلات الموقع مكتبة Python مُخصصة في مجموعة Apache Spark على HDInsight

يوضح دفتر الملاحظات هذا كيفية تحليل بيانات السجل باستخدام مكتبة مُخصصة مع Apache Spark على HDInsight. المكتبة المُخصصة التي نستخدمها هي مكتبة Python تسمى iislogparser.py.

المتطلبات الأساسية

مجموعة Apache Spark على HDInsight. للحصول على إرشادات، يرجى مراجعة إنشاء مجموعات Apache Spark في Azure HDInsight.

حفظ البيانات الأولية كـ RDD

نستخدم في هذا القسم دفتر Jupyter المقترن بنظام مجموعة Apache Spark في HDInsight لتشغيل الوظائف التي تعالج بيانات العينة الأولية وحفظها كجدول خلية. نموذج البيانات هو ملف (hvac.csv) csv. متوفر على كافة نظم المجموعات بشكل افتراضي.

بمجرد حفظ بياناتك كجدول Apache Hive، سنقوم في القسم التالي بالاتصال بجدول Apache Hive باستخدام أدوات BI مثل Power BI وTableau.

  1. من متصفح ويب، انتقل إلى https://CLUSTERNAME.azurehdinsight.net/jupyter، حيث CLUSTERNAME هو اسم نظام المجموعة.

  2. قم بإنشاء دفتر ملاحظات جديد. حدد "جديد" ثم "PySpark".

    Create a new Apache Jupyter Notebook. Notebook" border="true":::

  3. يتم إنشاء دفتر ملاحظات جديد وفتحه باسم Untitled.pynb. حدد اسم دفتر الملاحظات في الجزء العلوي، وأدخل اسماً مألوفاً.

    Provide a name for the notebook.

  4. نظرًا لأنك أنشأت دفتر ملاحظات باستخدام PySpark kernel، لن تحتاج إلى إنشاء أي سياقات بشكل صريح. سوف يتم إنشاء سياق Spark وسياق Hive تلقائيًّا من أجلك عندما تقوم بتشغيل خلية التعليمات البرمجية الأولى. يمكنك البدء باستيراد الأنواع المطلوبة لهذا السيناريو. الصق القصاصة البرمجية التالية في خلية فارغة، ثم اضغط على SHIFT + ENTER .

    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. يمكنك كذلك تقديم هذه المعلومات في شكل رسم. دعونا أولًا نقوم بإنشاء جدول متوسط الوقت مؤقت كخطوة أولى لإنشاء رسم. يقوم الجدول بتجميع السجلات حسب الوقت لمعرفة ما إذا كانت هناك أي طفرات زمن انتقال غير عادية في أي فترة زمنية.

    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 التالي للحصول على كافة السجلات في جدول متوسط الوقت.

    %%sql -o averagetime
    SELECT * FROM AverageTime
    

    سحر %%sqlمتبوعًا بـ -o averagetime يضمن استمرار ناتج الاستعلام محليًا على خادم Jupyter (عادة العُقدة الرئيسية لنظام المجموعة). يتم استمرار الناتج كإطار بيانات Pandas باسم محدد وهو متوسط الوقت.

    يجب أن تشاهد ناتج مثل الصورة التالية:

    hdinsight jupyter sql query output. إخراج استعلام yter sql" border="true":::

    لمزيد من المعلومات حول سحر %%sql، راجع المعلمات المدعومة بسحر sql%%.

  8. يمكنك الآن استخدام Matplotlib، وهي مكتبة تُستخدم لإنشاء تصور للبيانات، لإنشاء رسم. نظرًا لأنه يجب إنشاء الرسم من إطار بيانات متوسط الوقت مُستمر محليًا، يجب أن تبدأ القصاصة البرمجية بسحر %%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 web log analysis plot. مخطط تحليل سجل eb" border="true":::

  9. بعد الانتهاء من تشغيل التطبيق، يجب إيقاف تشغيل دفتر الملاحظات لتحرير الموارد. للقيام بذلك، من قائمة ملف في دفتر الملاحظات، حدد إغلاق وإيقاف. سيتم إيقاف تشغيل هذا الإجراء وإغلاق دفتر الملاحظات.

الخطوات التالية

اضطلع على المقالات التالية: