Analisis log telemetri Application Insights dengan Apache Spark di Microsoft Azure HDInsight
Pelajari cara menggunakan Apache Spark di Microsoft Azure HDInsight untuk menganalisis data telemetri Wawasan Aplikasi.
Visual Studio Application Insights adalah layanan analitik yang memantau aplikasi web Anda. Data telemetri yang dihasilkan oleh Application Insights dapat diekspor ke Azure Storage. Setelah data berada di Azure Storage, Microsoft Azure HDInsight dapat digunakan untuk menganalisisnya.
Prasyarat
Aplikasi yang dikonfigurasi untuk menggunakan Application Insights.
Keakraban dengan membuat klaster Microsoft Azure HDInsight berbasis Linux. Untuk informasi selengkapnya, lihat Buat Apache Spark di Microsoft Azure HDInsight.
Browser web.
Sumber daya berikut digunakan dalam mengembangkan dan menguji dokumen ini:
Data telemetri Application Insights dihasilkan menggunakan aplikasi webNode.js dikonfigurasi untuk menggunakan Application Insights.
Spark berbasis Linux pada kluster Microsoft Azure HDInsight versi 3.5 digunakan untuk menganalisis data.
Arsitektur dan perencanaan
Diagram berikut mengilustrasikan arsitektur layanan dari contoh ini:
Azure Storage
Application Insights dapat dikonfigurasi untuk terus mengekspor informasi telemetri ke blob. Microsoft Azure HDInsight kemudian dapat membaca data yang disimpan dalam blob. Namun, ada beberapa persyaratan yang harus Anda ikuti:
Lokasi:Jika Akun Penyimpanan dan Microsoft Azure HDInsight berada di lokasi yang berbeda, itu dapat meningkatkan latensi. Ini juga meningkatkan biaya, karena biaya keluar diterapkan pada data yang berpindah antar wilayah.
Peringatan
Penggunaan akun penyimpanan di lokasi yang berbeda dari kluster Microsoft Azure HDInsight tidak didukung.
Jenis blob:Microsoft Azure HDInsight hanya mendukung blob blok. Application Insights default untuk menggunakan blob blok, jadi harus bekerja secara default dengan Microsoft Azure HDInsight.
Untuk informasi tentang penambahan penyimpanan ke kluster yang sudah ada, lihat dokumen penambahan akun penyimpanan tambahan.
Skema data
Application Insights menyediakan informasi model data ekspor untuk format data telemetri yang diekspor ke blob. Langkah-langkah dalam dokumen ini menggunakan Spark SQL untuk bekerja dengan data. Spark SQL dapat secara otomatis menghasilkan skema untuk struktur data JSON yang dicatat oleh Application Insights.
Ekspor data telemetri
Ikuti langkah-langkah dalam konfigurasikan Ekspor Berkelanjutan untuk mengonfigurasi Application Insights Anda untuk mengekspor informasi telemetri ke blob Azure Storage.
Konfigurasikan Microsoft Azure HDInsight untuk mengakses data
Jika Anda membuat kluster Microsoft Azure HDInsight, tambahkan akun penyimpanan selama pembuatan kluster.
Untuk menambahkan Akun Azure Storage ke kluster yang sudah ada, gunakan informasi di Tambahkan dokumen Tambahkan Akun Penyimpanan.
Analisis data: PySpark
Dari browser web, arahkan ke
https://CLUSTERNAME.azurehdinsight.net/jupyter
di mana NAMAKLUSTER adalah nama kluster Anda.Di sudut kanan atas halaman Jupyter, pilih Baru,lalu PySpark. Tab browser baru yang berisi Jupyter Notebook berbasis Python terbuka.
Di bidang pertama (disebut sel) di halaman, masukkan teks berikut:
sc._jsc.hadoopConfiguration().set('mapreduce.input.fileinputformat.input.dir.recursive', 'true')
Kode ini mengonfigurasi Spark untuk secara rekursif mengakses struktur direktori untuk data input. Telemetri Application Insights dicatat ke struktur direktori yang mirip dengan
/{telemetry type}/YYYY-MM-DD/{##}/
.Gunakan SHIFT+ENTER untuk menjalankan kode. Di sisi kiri sel, ‘*‘ muncul di antara tanda kurung untuk menunjukkan bahwa kode dalam sel ini sedang dijalankan. Setelah selesai, ‘*’ berubah menjadi angka, dan output yang mirip dengan teks berikut ditampilkan di bawah sel:
Creating SparkContext as 'sc' ID YARN Application ID Kind State Spark UI Driver log Current session? 3 application_1468969497124_0001 pyspark idle Link Link ✔ Creating HiveContext as 'sqlContext' SparkContext and HiveContext created. Executing user code ...
Sel baru dibuat di bawah sel pertama. Masukkan teks berikut ini di sel baru. Ganti
CONTAINER
danSTORAGEACCOUNT
dengan nama akun Azure Storage dan nama kontainer blob yang berisi data Application Insights.%%bash hdfs dfs -ls wasbs://CONTAINER@STORAGEACCOUNT.blob.core.windows.net/
Gunakan SHIFT+ENTER untuk menjalankan sel ini. Anda melihat hasil yang mirip dengan teks berikut:
Found 1 items drwxrwxrwx - 0 1970-01-01 00:00 wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_2bededa61bc741fbdee6b556571a4831
Jalur wasb yang dikembalikan adalah lokasi data telemetri Application Insights. Ubah
hdfs dfs -ls
baris dalam sel untuk menggunakan jalur wasb yang dikembalikan, lalu gunakan SHIFT+ENTER untuk menjalankan sel lagi. Kali ini, hasilnya harus menampilkan direktori yang berisi data telemetri.Catatan
Untuk sisa langkah-langkah di bagian
wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_{ID}/Requests
ini, direktori digunakan. Struktur direktori Anda mungkin berbeda.Di sel berikutnya, masukkan kode berikut: Ganti
WASB_PATH
dengan jalur dari langkah sebelumnya.jsonFiles = sc.textFile('WASB_PATH') jsonData = sqlContext.read.json(jsonFiles)
Kode ini membuat dataframe dari file JSON yang diekspor oleh proses ekspor berkelanjutan. Gunakan SHIFT+ENTER untuk menjalankan kode ini.
Di sel berikutnya, masukkan dan jalankan yang berikut ini untuk menampilkan skema yang dibuat Spark untuk file JSON:
jsonData.printSchema()
Skema untuk setiap jenis telemetri berbeda. Contoh berikut adalah skema yang dihasilkan untuk permintaan web (data yang disimpan dalam
Requests
subdirektori):root |-- context: struct (nullable = true) | |-- application: struct (nullable = true) | | |-- version: string (nullable = true) | |-- custom: struct (nullable = true) | | |-- dimensions: array (nullable = true) | | | |-- element: string (containsNull = true) | | |-- metrics: array (nullable = true) | | | |-- element: string (containsNull = true) | |-- data: struct (nullable = true) | | |-- eventTime: string (nullable = true) | | |-- isSynthetic: boolean (nullable = true) | | |-- samplingRate: double (nullable = true) | | |-- syntheticSource: string (nullable = true) | |-- device: struct (nullable = true) | | |-- browser: string (nullable = true) | | |-- browserVersion: string (nullable = true) | | |-- deviceModel: string (nullable = true) | | |-- deviceName: string (nullable = true) | | |-- id: string (nullable = true) | | |-- osVersion: string (nullable = true) | | |-- type: string (nullable = true) | |-- location: struct (nullable = true) | | |-- city: string (nullable = true) | | |-- clientip: string (nullable = true) | | |-- continent: string (nullable = true) | | |-- country: string (nullable = true) | | |-- province: string (nullable = true) | |-- operation: struct (nullable = true) | | |-- name: string (nullable = true) | |-- session: struct (nullable = true) | | |-- id: string (nullable = true) | | |-- isFirst: boolean (nullable = true) | |-- user: struct (nullable = true) | | |-- anonId: string (nullable = true) | | |-- isAuthenticated: boolean (nullable = true) |-- internal: struct (nullable = true) | |-- data: struct (nullable = true) | | |-- documentVersion: string (nullable = true) | | |-- id: string (nullable = true) |-- request: array (nullable = true) | |-- element: struct (containsNull = true) | | |-- count: long (nullable = true) | | |-- durationMetric: struct (nullable = true) | | | |-- count: double (nullable = true) | | | |-- max: double (nullable = true) | | | |-- min: double (nullable = true) | | | |-- sampledValue: double (nullable = true) | | | |-- stdDev: double (nullable = true) | | | |-- value: double (nullable = true) | | |-- id: string (nullable = true) | | |-- name: string (nullable = true) | | |-- responseCode: long (nullable = true) | | |-- success: boolean (nullable = true) | | |-- url: string (nullable = true) | | |-- urlData: struct (nullable = true) | | | |-- base: string (nullable = true) | | | |-- hashTag: string (nullable = true) | | | |-- host: string (nullable = true) | | | |-- protocol: string (nullable = true)
Gunakan yang berikut ini untuk mendaftarkan dataframe sebagai tabel sementara dan menjalankan kueri terhadap data:
jsonData.registerTempTable("requests") df = sqlContext.sql("select context.location.city from requests where context.location.city is not null") df.show()
Kueri ini mengembalikan informasi kota untuk 20 rekaman teratas di mana konteks.lokasi.kota tidak null.
Catatan
Struktur konteks hadir di semua telemetri yang dicatat oleh Application Insights. Elemen kota mungkin tidak diisi dalam log Anda. Gunakan skema untuk mengidentifikasi elemen lain yang bisa Anda kueri yang mungkin berisi data untuk log Anda.
Kueri ini menampilkan informasi yang mirip dengan teks berikut:
+---------+ | city| +---------+ | Bellevue| | Redmond| | Seattle| |Charlotte| ... +---------+
Analisis data: Scala
Dari browser web, arahkan ke
https://CLUSTERNAME.azurehdinsight.net/jupyter
di mana NAMAKLUSTER adalah nama kluster Anda.Di sudut kanan atas halaman Jupyter, pilih Baru, lalu Scala. Tab browser baru yang berisi Jupyter Notebook berbasis Python terbuka.
Di bidang pertama (disebut sel) di halaman, masukkan teks berikut:
sc.hadoopConfiguration.set("mapreduce.input.fileinputformat.input.dir.recursive", "true")
Kode ini mengonfigurasi Spark untuk secara rekursif mengakses struktur direktori untuk data input. Telemetri Application Insights dicatat ke struktur direktori yang mirip dengan
/{telemetry type}/YYYY-MM-DD/{##}/
.Gunakan SHIFT+ENTER untuk menjalankan kode. Di sisi kiri sel, ‘*‘ muncul di antara tanda kurung untuk menunjukkan bahwa kode dalam sel ini sedang dijalankan. Setelah selesai, ‘*’ berubah menjadi angka, dan output yang mirip dengan teks berikut ditampilkan di bawah sel:
Creating SparkContext as 'sc' ID YARN Application ID Kind State Spark UI Driver log Current session? 3 application_1468969497124_0001 spark idle Link Link ✔ Creating HiveContext as 'sqlContext' SparkContext and HiveContext created. Executing user code ...
Sel baru dibuat di bawah sel pertama. Masukkan teks berikut ini di sel baru. Ganti
CONTAINER
danSTORAGEACCOUNT
dengan nama akun Azure Storage dan nama kontainer blob yang berisi data Application Insights.%%bash hdfs dfs -ls wasbs://CONTAINER@STORAGEACCOUNT.blob.core.windows.net/
Gunakan SHIFT+ENTER untuk menjalankan sel ini. Anda melihat hasil yang mirip dengan teks berikut:
Found 1 items drwxrwxrwx - 0 1970-01-01 00:00 wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_2bededa61bc741fbdee6b556571a4831
Jalur wasb yang dikembalikan adalah lokasi data telemetri Application Insights. Ubah
hdfs dfs -ls
baris dalam sel untuk menggunakan jalur wasb yang dikembalikan, lalu gunakan SHIFT+ENTER untuk menjalankan sel lagi. Kali ini, hasilnya harus menampilkan direktori yang berisi data telemetri.Catatan
Untuk sisa langkah-langkah di bagian
wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_{ID}/Requests
ini, direktori digunakan. Direktori ini mungkin tidak ada kecuali data telemetri Anda adalah untuk aplikasi web.Di sel berikutnya, masukkan kode berikut: Ganti
WASB\_PATH
dengan jalur dari langkah sebelumnya.var jsonFiles = sc.textFile('WASB_PATH') val sqlContext = new org.apache.spark.sql.SQLContext(sc) var jsonData = sqlContext.read.json(jsonFiles)
Kode ini membuat dataframe dari file JSON yang diekspor oleh proses ekspor berkelanjutan. Gunakan SHIFT+ENTER untuk menjalankan kode ini.
Di sel berikutnya, masukkan dan jalankan yang berikut ini untuk menampilkan skema yang dibuat Spark untuk file JSON:
jsonData.printSchema
Skema untuk setiap jenis telemetri berbeda. Contoh berikut adalah skema yang dihasilkan untuk permintaan web (data yang disimpan dalam
Requests
subdirektori):root |-- context: struct (nullable = true) | |-- application: struct (nullable = true) | | |-- version: string (nullable = true) | |-- custom: struct (nullable = true) | | |-- dimensions: array (nullable = true) | | | |-- element: string (containsNull = true) | | |-- metrics: array (nullable = true) | | | |-- element: string (containsNull = true) | |-- data: struct (nullable = true) | | |-- eventTime: string (nullable = true) | | |-- isSynthetic: boolean (nullable = true) | | |-- samplingRate: double (nullable = true) | | |-- syntheticSource: string (nullable = true) | |-- device: struct (nullable = true) | | |-- browser: string (nullable = true) | | |-- browserVersion: string (nullable = true) | | |-- deviceModel: string (nullable = true) | | |-- deviceName: string (nullable = true) | | |-- id: string (nullable = true) | | |-- osVersion: string (nullable = true) | | |-- type: string (nullable = true) | |-- location: struct (nullable = true) | | |-- city: string (nullable = true) | | |-- clientip: string (nullable = true) | | |-- continent: string (nullable = true) | | |-- country: string (nullable = true) | | |-- province: string (nullable = true) | |-- operation: struct (nullable = true) | | |-- name: string (nullable = true) | |-- session: struct (nullable = true) | | |-- id: string (nullable = true) | | |-- isFirst: boolean (nullable = true) | |-- user: struct (nullable = true) | | |-- anonId: string (nullable = true) | | |-- isAuthenticated: boolean (nullable = true) |-- internal: struct (nullable = true) | |-- data: struct (nullable = true) | | |-- documentVersion: string (nullable = true) | | |-- id: string (nullable = true) |-- request: array (nullable = true) | |-- element: struct (containsNull = true) | | |-- count: long (nullable = true) | | |-- durationMetric: struct (nullable = true) | | | |-- count: double (nullable = true) | | | |-- max: double (nullable = true) | | | |-- min: double (nullable = true) | | | |-- sampledValue: double (nullable = true) | | | |-- stdDev: double (nullable = true) | | | |-- value: double (nullable = true) | | |-- id: string (nullable = true) | | |-- name: string (nullable = true) | | |-- responseCode: long (nullable = true) | | |-- success: boolean (nullable = true) | | |-- url: string (nullable = true) | | |-- urlData: struct (nullable = true) | | | |-- base: string (nullable = true) | | | |-- hashTag: string (nullable = true) | | | |-- host: string (nullable = true) | | | |-- protocol: string (nullable = true)
Gunakan yang berikut ini untuk mendaftarkan dataframe sebagai tabel sementara dan menjalankan kueri terhadap data:
jsonData.registerTempTable("requests") var city = sqlContext.sql("select context.location.city from requests where context.location.city isn't null limit 10").show()
Kueri ini mengembalikan informasi kota untuk 20 rekaman teratas di mana konteks.lokasi.kota tidak null.
Catatan
Struktur konteks hadir di semua telemetri yang dicatat oleh Application Insights. Elemen kota mungkin tidak diisi dalam log Anda. Gunakan skema untuk mengidentifikasi elemen lain yang bisa Anda kueri yang mungkin berisi data untuk log Anda.
Kueri ini menampilkan informasi yang mirip dengan teks berikut:
+---------+ | city| +---------+ | Bellevue| | Redmond| | Seattle| |Charlotte| ... +---------+
Langkah berikutnya
Untuk contoh selengkapnya menggunakan Apache Spark untuk bekerja dengan data dan layanan di Azure, lihat dokumen berikut ini:
- Apache Spark dengan BI: Melakukan analisis data interaktif menggunakan Spark di HDInsight dengan alat BI
- Apache Spark dengan Pembelajaran Mesin: Menggunakan Apache Spark di HDInsight untuk menganalisis suhu bangunan menggunakan data HVAC
- Apache Spark dengan Pembelajaran Mesin: Menggunakan Spark di Microsoft Azure HDInsight untuk memprediksi hasil pemeriksaan makanan
- Analisis log situs web menggunakan Apache Spark di HDInsight
Untuk informasi tentang membuat dan menjalankan aplikasi Spark, lihat dokumen berikut: