Delen via


Telemetrielogboeken van Application Insights analyseren met Apache Spark in HDInsight

Meer informatie over het gebruik van Apache Spark in HDInsight om Telemetriegegevens van Application Insight te analyseren.

Visual Studio Application Insights is een analyseservice waarmee uw webtoepassingen worden bewaakt. Telemetriegegevens die door Application Insights worden gegenereerd, kunnen worden geëxporteerd naar Azure Storage. Zodra de gegevens zich in Azure Storage bevinden, kan HDInsight worden gebruikt om deze te analyseren.

Vereisten

  • Een toepassing die is geconfigureerd voor het gebruik van Application Insights.

  • Bekendheid met het maken van een HDInsight-cluster op basis van Linux. Zie Apache Spark maken in HDInsight voor meer informatie.

  • Een webbrowser.

De volgende bronnen zijn gebruikt voor het ontwikkelen en testen van dit document:

Architectuur en planning

In het volgende diagram ziet u de servicearchitectuur van dit voorbeeld:

Gegevens stromen van Application Insights naar blobopslag en vervolgens Spark.

Azure Storage

Application Insights kan worden geconfigureerd voor het continu exporteren van telemetriegegevens naar blobs. HDInsight kan vervolgens gegevens lezen die zijn opgeslagen in de blobs. Er zijn echter enkele vereisten die u moet volgen:

  • Locatie: Als het opslagaccount en HDInsight zich op verschillende locaties bevinden, kan de latentie toenemen. Het verhoogt ook de kosten, omdat uitgaande kosten worden toegepast op gegevens die tussen regio's worden verplaatst.

    Waarschuwing

    Het gebruik van een opslagaccount op een andere locatie dan HDInsight wordt niet ondersteund.

  • Blobtype: HDInsight ondersteunt alleen blok-blobs. Application Insights gebruikt standaard blok-blobs, dus moet standaard werken met HDInsight.

Zie het document Extra opslagaccounts toevoegen voor meer informatie over het toevoegen van opslag aan een bestaand cluster.

Gegevensschema

Application Insights biedt gegevensmodelgegevens exporteren voor de telemetriegegevensindeling die wordt geëxporteerd naar blobs. In de stappen in dit document wordt Spark SQL gebruikt om met de gegevens te werken. Spark SQL kan automatisch een schema genereren voor de JSON-gegevensstructuur die is vastgelegd door Application Insights.

Telemetriegegevens exporteren

Volg de stappen in Continue export configureren om uw Application Insights te configureren voor het exporteren van telemetriegegevens naar een Azure Storage-blob.

HDInsight configureren voor toegang tot de gegevens

Als u een HDInsight-cluster maakt, voegt u het opslagaccount toe tijdens het maken van het cluster.

Als u het Azure Storage-account wilt toevoegen aan een bestaand cluster, gebruikt u de informatie in het document Extra opslagaccounts toevoegen.

De gegevens analyseren: PySpark

  1. Navigeer in een webbrowser naar https://CLUSTERNAME.azurehdinsight.net/jupyter de locatie waar CLUSTERNAME de naam van uw cluster is.

  2. Selecteer Nieuw in de rechterbovenhoek van de Jupyter-pagina en vervolgens PySpark. Er wordt een nieuw browsertabblad geopend met een Jupyter Notebook op basis van Python.

  3. Voer in het eerste veld (een cel genoemd) op de pagina de volgende tekst in:

    sc._jsc.hadoopConfiguration().set('mapreduce.input.fileinputformat.input.dir.recursive', 'true')
    

    Met deze code configureert u Spark om recursief toegang te krijgen tot de mapstructuur voor de invoergegevens. Application Insights-telemetrie wordt vastgelegd in een mapstructuur die vergelijkbaar is met de /{telemetry type}/YYYY-MM-DD/{##}/.

  4. Gebruik Shift+ENTER om de code uit te voeren. Aan de linkerkant van de cel wordt een '*' tussen de haken weergegeven om aan te geven dat de code in deze cel wordt uitgevoerd. Zodra dit is voltooid, wordt de *-waarde gewijzigd in een getal en wordt de uitvoer weergegeven die vergelijkbaar is met de volgende tekst onder de cel:

    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 ...
    
  5. Er wordt een nieuwe cel gemaakt onder de eerste cel. Voer de volgende tekst in de nieuwe cel in. Vervang en STORAGEACCOUNT door CONTAINER de naam van het Azure Storage-account en de naam van de blobcontainer die Application Insights-gegevens bevat.

    %%bash
    hdfs dfs -ls wasbs://CONTAINER@STORAGEACCOUNT.blob.core.windows.net/
    

    Gebruik Shift+ENTER om deze cel uit te voeren. U ziet een resultaat dat lijkt op de volgende tekst:

    Found 1 items
    drwxrwxrwx   -          0 1970-01-01 00:00 wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_2bededa61bc741fbdee6b556571a4831
    

    Het geretourneerde wasbs-pad is de locatie van de Application Insights-telemetriegegevens. Wijzig de hdfs dfs -ls regel in de cel om het pad naar wasbs te gebruiken en gebruik vervolgens Shift+Enter om de cel opnieuw uit te voeren. Deze keer moeten in de resultaten de mappen worden weergegeven die telemetriegegevens bevatten.

    Notitie

    Voor de rest van de stappen in deze sectie is de wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_{ID}/Requests map gebruikt. Uw mapstructuur kan afwijken.

  6. Voer in de volgende cel de volgende code in: Vervang WASB_PATH het pad uit de vorige stap.

    jsonFiles = sc.textFile('WASB_PATH')
    jsonData = sqlContext.read.json(jsonFiles)
    

    Met deze code maakt u een dataframe op basis van de JSON-bestanden die door het continue exportproces worden geëxporteerd. Gebruik Shift+ENTER om deze cel uit te voeren.

  7. Voer in de volgende cel het volgende in en voer het volgende uit om het schema weer te geven dat Spark heeft gemaakt voor de JSON-bestanden:

    jsonData.printSchema()
    

    Het schema voor elk type telemetrie verschilt. Het volgende voorbeeld is het schema dat wordt gegenereerd voor webaanvragen (gegevens die zijn opgeslagen in de Requests submap):

    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)
    
  8. Gebruik het volgende om het dataframe als een tijdelijke tabel te registreren en een query uit te voeren op de gegevens:

    jsonData.registerTempTable("requests")
    df = sqlContext.sql("select context.location.city from requests where context.location.city is not null")
    df.show()
    

    Deze query retourneert de plaatsgegevens voor de top 20 records waarbij context.location.city niet null is.

    Notitie

    De contextstructuur is aanwezig in alle telemetriegegevens die zijn vastgelegd door Application Insights. Het plaatselement wordt mogelijk niet ingevuld in uw logboeken. Gebruik het schema om andere elementen te identificeren die u kunt opvragen die mogelijk gegevens voor uw logboeken bevatten.

    Deze query retourneert informatie die vergelijkbaar is met de volgende tekst:

    +---------+
    |     city|
    +---------+
    | Bellevue|
    |  Redmond|
    |  Seattle|
    |Charlotte|
    ...
    +---------+
    

De gegevens analyseren: Scala

  1. Navigeer in een webbrowser naar https://CLUSTERNAME.azurehdinsight.net/jupyter de locatie waar CLUSTERNAME de naam van uw cluster is.

  2. Selecteer In de rechterbovenhoek van de Jupyter-pagina de optie Nieuw en vervolgens Scala. Er wordt een nieuw browsertabblad met een Jupyter Notebook op basis van Scala weergegeven.

  3. Voer in het eerste veld (een cel genoemd) op de pagina de volgende tekst in:

    sc.hadoopConfiguration.set("mapreduce.input.fileinputformat.input.dir.recursive", "true")
    

    Met deze code configureert u Spark om recursief toegang te krijgen tot de mapstructuur voor de invoergegevens. Application Insights-telemetrie wordt geregistreerd in een mapstructuur die vergelijkbaar is met /{telemetry type}/YYYY-MM-DD/{##}/.

  4. Gebruik Shift+ENTER om de code uit te voeren. Aan de linkerkant van de cel wordt een '*' tussen de haken weergegeven om aan te geven dat de code in deze cel wordt uitgevoerd. Zodra dit is voltooid, wordt de *-waarde gewijzigd in een getal en wordt de uitvoer weergegeven die vergelijkbaar is met de volgende tekst onder de cel:

    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 ...
    
  5. Er wordt een nieuwe cel gemaakt onder de eerste cel. Voer de volgende tekst in de nieuwe cel in. Vervang en STORAGEACCOUNT door CONTAINER de naam van het Azure Storage-account en de blobcontainernaam die Application Insights-logboeken bevat.

    %%bash
    hdfs dfs -ls wasbs://CONTAINER@STORAGEACCOUNT.blob.core.windows.net/
    

    Gebruik Shift+ENTER om deze cel uit te voeren. U ziet een resultaat dat lijkt op de volgende tekst:

    Found 1 items
    drwxrwxrwx   -          0 1970-01-01 00:00 wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_2bededa61bc741fbdee6b556571a4831
    

    Het geretourneerde wasbs-pad is de locatie van de Application Insights-telemetriegegevens. Wijzig de hdfs dfs -ls regel in de cel om het pad naar wasbs te gebruiken en gebruik vervolgens Shift+Enter om de cel opnieuw uit te voeren. Deze keer moeten in de resultaten de mappen worden weergegeven die telemetriegegevens bevatten.

    Notitie

    Voor de rest van de stappen in deze sectie is de wasbs://appinsights@contosostore.blob.core.windows.net/contosoappinsights_{ID}/Requests map gebruikt. Deze map bestaat mogelijk niet, tenzij uw telemetriegegevens voor een web-app zijn.

  6. Voer in de volgende cel de volgende code in: Vervang WASB\_PATH het pad uit de vorige stap.

    var jsonFiles = sc.textFile('WASB_PATH')
    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
    var jsonData = sqlContext.read.json(jsonFiles)
    

    Met deze code maakt u een dataframe op basis van de JSON-bestanden die door het continue exportproces worden geëxporteerd. Gebruik Shift+ENTER om deze cel uit te voeren.

  7. Voer in de volgende cel het volgende in en voer het volgende uit om het schema weer te geven dat Spark heeft gemaakt voor de JSON-bestanden:

    jsonData.printSchema
    

    Het schema voor elk type telemetrie verschilt. Het volgende voorbeeld is het schema dat wordt gegenereerd voor webaanvragen (gegevens die zijn opgeslagen in de Requests submap):

    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)
    
  8. Gebruik het volgende om het dataframe als een tijdelijke tabel te registreren en een query uit te voeren op de gegevens:

    jsonData.registerTempTable("requests")
    var city = sqlContext.sql("select context.location.city from requests where context.location.city isn't null limit 10").show()
    

    Deze query retourneert de plaatsgegevens voor de top 20 records waarbij context.location.city niet null is.

    Notitie

    De contextstructuur is aanwezig in alle telemetriegegevens die zijn vastgelegd door Application Insights. Het plaatselement wordt mogelijk niet ingevuld in uw logboeken. Gebruik het schema om andere elementen te identificeren die u kunt opvragen die mogelijk gegevens voor uw logboeken bevatten.

    Deze query retourneert informatie die vergelijkbaar is met de volgende tekst:

    +---------+
    |     city|
    +---------+
    | Bellevue|
    |  Redmond|
    |  Seattle|
    |Charlotte|
    ...
    +---------+
    

Volgende stappen

Zie de volgende documenten voor meer voorbeelden van het gebruik van Apache Spark om te werken met gegevens en services in Azure:

Zie de volgende documenten voor informatie over het maken en uitvoeren van Spark-toepassingen: