com.microsoft.applicationinsights.test.framework.ApplicationTelemetryManager.java Source code

Java tutorial

Introduction

Here is the source code for com.microsoft.applicationinsights.test.framework.ApplicationTelemetryManager.java

Source

/*
 * ApplicationInsights-Java
 * Copyright (c) Microsoft Corporation
 * All rights reserved.
 *
 * MIT License
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the ""Software""), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Software, and to permit
 * persons to whom the Software is furnished to do so, subject to the following conditions:
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 * THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
 * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

package com.microsoft.applicationinsights.test.framework;

import com.microsoft.applicationinsights.test.framework.telemetries.DocumentType;
import com.microsoft.applicationinsights.test.framework.telemetries.TelemetryItem;
import com.microsoft.applicationinsights.test.framework.telemetries.TelemetryItemFactory;
import com.microsoft.applicationinsights.internal.util.LocalStringsUtils;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.queue.CloudQueueMessage;
import org.apache.commons.lang3.time.StopWatch;
import org.json.JSONObject;

import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeoutException;

/**
 * Created by yonisha on 6/16/2015.
 */
public class ApplicationTelemetryManager {

    private static final String RUN_ID_QUERY_PARAM_NAME = "runId";
    private static final int MS_IN_SECOND = 1000;

    private final int pollingTimeoutInSeconds;
    private final int queuePollingIntervalInSeconds;
    private List<TelemetryItem> cachedTelemetries = new ArrayList<TelemetryItem>();
    private ApplicationTelemetryQueue applicationTelemetryQueue;
    private ApplicationBlobClient applicationBlobClient;

    public ApplicationTelemetryManager(String storageAccountConnectionString, String queueName,
            int pollingTimeoutInSeconds, int queuePollingIntervalInSeconds, int queueMessageBatchSize)
            throws StorageException, InvalidKeyException, URISyntaxException {
        this.applicationTelemetryQueue = new ApplicationTelemetryQueue(storageAccountConnectionString, queueName,
                queueMessageBatchSize, pollingTimeoutInSeconds);
        this.applicationBlobClient = new ApplicationBlobClient(storageAccountConnectionString);
        this.pollingTimeoutInSeconds = pollingTimeoutInSeconds;
        this.queuePollingIntervalInSeconds = queuePollingIntervalInSeconds;
    }

    public List<TelemetryItem> getApplicationTelemetries(String runId, int numberOfExpectedTelemetries)
            throws Exception {

        List<TelemetryItem> telemetriesForRunId = getTelemetriesFromCacheWithRunId(runId);

        if (telemetriesForRunId.size() < numberOfExpectedTelemetries) {
            int missingTelemetriesCount = numberOfExpectedTelemetries - telemetriesForRunId.size();
            updateTelemetryCache(runId, missingTelemetriesCount);
        }

        telemetriesForRunId = getTelemetriesFromCacheWithRunId(runId);

        if (telemetriesForRunId.size() < numberOfExpectedTelemetries) {
            String message = String.format(
                    "Got only %d out of %d expected telemetries within the timeout (%d seconds)",
                    telemetriesForRunId.size(), numberOfExpectedTelemetries, this.pollingTimeoutInSeconds);

            throw new TimeoutException(message);
        }

        return telemetriesForRunId;
    }

    private List<TelemetryItem> getTelemetriesFromCacheWithRunId(String runId) {
        List<TelemetryItem> telemetryForRunId = new ArrayList<TelemetryItem>();

        for (TelemetryItem telemetryItem : this.cachedTelemetries) {
            String runIdProperty = telemetryItem.getProperty(RUN_ID_QUERY_PARAM_NAME);
            if (runIdProperty != null && runIdProperty.equalsIgnoreCase(runId)) {
                telemetryForRunId.add(telemetryItem);
            }
        }

        return telemetryForRunId;
    }

    private void updateTelemetryCache(String runId, int numberOfExpectedTelemetries) throws Exception {
        long maxWaitTimeInMillis = this.pollingTimeoutInSeconds * MS_IN_SECOND;

        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        int countOfTelemetriesWithExpectedRunId = 0;
        while (countOfTelemetriesWithExpectedRunId < numberOfExpectedTelemetries
                && stopWatch.getTime() < maxWaitTimeInMillis) {
            ArrayList<CloudQueueMessage> messages = applicationTelemetryQueue.retrieveMessages();

            ArrayList<TelemetryBlob> telemetryBlobs = getBlobUrisFromQueueMessages(messages);
            for (TelemetryBlob telemetryBlob : telemetryBlobs) {
                List<JSONObject> telemetriesAsJsonObjects = applicationBlobClient
                        .getTelemetriesAsJsonObjects(telemetryBlob.getBlobUri());

                for (JSONObject json : telemetriesAsJsonObjects) {
                    TelemetryItem telemetryItem = TelemetryItemFactory
                            .createTelemetryItem(telemetryBlob.getDocType(), json);
                    this.cachedTelemetries.add(telemetryItem);

                    String runIdProperty = telemetryItem.getProperty(RUN_ID_QUERY_PARAM_NAME);
                    if (!LocalStringsUtils.isNullOrEmpty(runIdProperty) && runIdProperty.equalsIgnoreCase(runId)) {
                        countOfTelemetriesWithExpectedRunId++;
                    }
                }
            }

            applicationTelemetryQueue.deleteMessages(messages);

            if (countOfTelemetriesWithExpectedRunId < numberOfExpectedTelemetries) {
                sleepSafe();
            }
        }
    }

    /**
     * Gets a list of blob URIs from Azure queue messages
     * @param messages The Azure queue messages
     * @return An ArrayList of blob URIs
     * @throws Exception
     */
    private ArrayList<TelemetryBlob> getBlobUrisFromQueueMessages(ArrayList<CloudQueueMessage> messages)
            throws Exception {
        ArrayList<TelemetryBlob> telemetryBlobs = new ArrayList<TelemetryBlob>();

        for (CloudQueueMessage message : messages) {
            JSONObject messageContentAsJson = new JSONObject(message.getMessageContentAsString());
            String msgDocType = messageContentAsJson.getString("DocumentType");
            telemetryBlobs.add(
                    new TelemetryBlob(DocumentType.valueOf(msgDocType), messageContentAsJson.getString("BlobUri")));
        }

        return telemetryBlobs;
    }

    private void sleepSafe() {
        int timeToSleepInMilliseconds = this.queuePollingIntervalInSeconds * MS_IN_SECOND;

        try {
            System.out.println("Sleeping for " + this.queuePollingIntervalInSeconds + " seconds...");
            Thread.sleep(timeToSleepInMilliseconds);
        } catch (InterruptedException ex) {
        }
    }
}