private async Task HandleGitHubEvent(string gitHubEvent, DateTimeOffset messageEnqueueTime)
        {
            var eventJtoken = JToken.Parse(gitHubEvent);
            var eventType   = eventJtoken["eventType"].ToString();

            if (!Enum.TryParse(
                    eventType,
                    true,
                    out GitHubEventActions parsedEvent))
            {
                return;
            }

            if (gitHubEventHandlers.TryGetValue(parsedEvent, out var selectedEventHandler))
            {
                await selectedEventHandler.HandleEvent(gitHubEvent);
            }
            else
            {
                // this should never happen
                // there must always be a handler for an accepted eventType
                logger.LogError("Received unknown event in GitHubEventHost. {eventType}", eventType);
                telemetry.RecordMetric("GitHubEventHost-UnknownEvent", 1);
            }

            var messageProcessingCompleteDelay = DateTimeOffset.UtcNow - messageEnqueueTime;

            telemetry.RecordMetric(
                "EndMessageProcessing-Delay",
                (long)messageProcessingCompleteDelay.TotalSeconds,
                ("EventType", eventType));
        }
Example #2
0
        public async Task<byte[]> GetAsync(string key, CancellationToken token = new CancellationToken())
        {
            logger.LogInformation($"get blob cache: key={key}");
            var tokenInfo = await blobClient.GetBlobInfo(key, token);
            if (tokenInfo == null)
            {
                logger.LogInformation($"blob cache miss: key={key}");
                appTelemetry.RecordMetric("blob-cache-miss", 1, ("key", key));
                return null;
            }

            if (tokenInfo.CreatedOn.Add(cacheSettings.TimeToLive) < DateTimeOffset.UtcNow)
            {
                logger.LogInformation($"blob cache expired: key={key}");
                appTelemetry.RecordMetric("blob-cache-expired", 1, ("key", key));
                return null;
            }

            await blobClient.DownloadAsync(null, key, tempFolder, token);
            var downloadedBlogFile = Path.Combine(tempFolder, key);
            if (!File.Exists(downloadedBlogFile))
                throw new InvalidOperationException($"blob download file not found: {downloadedBlogFile}");

            var bytes = await File.ReadAllBytesAsync(downloadedBlogFile, token);
            File.Delete(downloadedBlogFile);
            logger.LogInformation($"blob cache downloaded: key={key}");
            return bytes;
        }
        public async Task HandleEvent(string gitHubEvent)
        {
            var payload =
                new Octokit.Internal.SimpleJsonSerializer().Deserialize <PullRequestEventPayload>(gitHubEvent);

            logger.LogInformation(
                "Quantifying pull request: {pullRequestUrl}|{pullRequestId}|{sha}",
                payload.PullRequest.HtmlUrl,
                payload.PullRequest.Id,
                payload.PullRequest.Head.Sha);
            telemetry.RecordMetric(
                "PullRequest-QuantifyRequest",
                1);

            var quantifierResult = await QuantifyPullRequest(payload);

            logger.LogInformation(
                "Quantified pull request: {pullRequestUrl}|{pullRequestId}|{sha}|" +
                "{label}|{formula}|{absoluteLinesAdded}|{absoluteLinesDeleted}|" +
                "{quantifiedLinesAdded}|{quantifiedLinesDeleted}|" +
                "{percentileAddition}|{percentileDeletion}|{formulaPercentile}",
                payload.PullRequest.HtmlUrl,
                payload.PullRequest.Id,
                payload.PullRequest.Head.Sha,
                quantifierResult.Label,
                quantifierResult.Formula,
                quantifierResult.QuantifierInput.Changes.Sum(c => c.AbsoluteLinesAdded),
                quantifierResult.QuantifierInput.Changes.Sum(c => c.AbsoluteLinesDeleted),
                quantifierResult.QuantifiedLinesAdded,
                quantifierResult.QuantifiedLinesDeleted,
                quantifierResult.PercentileAddition,
                quantifierResult.PercentileDeletion,
                quantifierResult.FormulaPercentile);
        }
Example #4
0
        public async Task SubscribeAsync(
            Func <string, DateTimeOffset, Task> messageHandler,
            Func <Exception, Task> errorHandler,
            CancellationToken cancellationToken)
        {
            // add handler to process messages
            processor.ProcessMessageAsync += async args =>
            {
                using var operation = telemetry.StartOperation <RequestTelemetry>(this, args.Message.CorrelationId);

                var messageProcessingStartDelay = DateTimeOffset.UtcNow - args.Message.EnqueuedTime;
                telemetry.RecordMetric(
                    "StartMessageProcessing-Delay",
                    (long)messageProcessingStartDelay.TotalSeconds);

                await messageHandler(args.Message.Body.ToString(), args.Message.EnqueuedTime);

                // delete the message
                await args.CompleteMessageAsync(args.Message, cancellationToken);
            };

            // add handler to process any errors
            processor.ProcessErrorAsync += async args => { await errorHandler(args.Exception); };

            // start processing
            await processor.StartProcessingAsync(cancellationToken);
        }
        public async Task <byte[]> GetAsync(string key, CancellationToken token = new CancellationToken())
        {
            logger.LogInformation($"get spillable memory cache: {key}");
            try
            {
                if (memoryCache.TryGetValue(key, out var value) && value is byte[] cachedValue)
                {
                    logger.LogInformation($"read cache from memory, key={key}");
                    appTelemetry.RecordMetric("memory-cache-hit", 1, ("key", key));
                    return(cachedValue);
                }

                appTelemetry.RecordMetric("memory-cache-miss", 1, ("key", key));

                var cacheFile = Path.Combine(cacheFolder, key);
                if (File.Exists(cacheFile))
                {
                    if (File.GetCreationTimeUtc(cacheFile).Add(cacheSettings.TimeToLive) < DateTimeOffset.UtcNow)
                    {
                        logger.LogInformation($"read cache from file, key={key}");
                        appTelemetry.RecordMetric("file-cache-expired", 1, ("key", key));
                        return(null);
                    }
                }
                else
                {
                    appTelemetry.RecordMetric("file-cache-miss", 1, ("key", key));
                    return(null);
                }

                var fileContent = await File.ReadAllBytesAsync(cacheFile, token);

                appTelemetry.RecordMetric("file-cache-hit", 1, ("key", key));
                var size         = (int)Math.Ceiling((double)fileContent.Length / 1000000); // MB
                var entryOptions = new MemoryCacheEntryOptions()
                                   .SetSize(size)
                                   .SetSlidingExpiration(cacheSettings.TimeToLive);
                memoryCache.Set(key, fileContent, entryOptions);

                return(fileContent);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, $"unable to get cache: {key}");
                return(null);
            }
        }
Example #6
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                log.LogTrace("heartbeat");
                metrics.RecordMetric("Heartbeat", 1);

                var sleepSeconds = 15;

                while (sleepSeconds-- > 0 && !stoppingToken.IsCancellationRequested)
                {
                    await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
                }
            }

            log.LogInformation("KeepAlive stopped!");
        }
        public Task HandleEvent(string gitHubEvent)
        {
            var payload =
                new Octokit.Internal.SimpleJsonSerializer().Deserialize <InstallationEventPayload>(gitHubEvent);

            logger.LogInformation(
                "Installation event: {accountId} | {accountLogin} | {accountUrl} | {accountType} | " +
                "{action} | {repositorySelection} | {repositories}",
                payload.Installation.Account.Id,
                payload.Installation.Account.Login,
                payload.Installation.Account.Url,
                payload.Installation.Account.Type.ToString(),
                payload.Action,
                payload.Installation.RepositorySelection,
                payload.Repositories != null ? string.Join(" , ", payload.Repositories.Select(r => r.FullName)) : string.Empty);
            telemetry.RecordMetric(
                "Installation-Event",
                1,
                ("Action", payload.Action));

            return(Task.CompletedTask);
        }
Example #8
0
        public async Task <T> GetOrUpdateAsync <T>(
            string key,
            Func <Task <DateTimeOffset> > getLastModificationTime,
            Func <Task <T> > getItem,
            CancellationToken cancel) where T : class, new()
        {
            logger.LogInformation($"get cached item, key={key}");
            var value = await multilayerCache.GetAsync(key, cancel);

            CachedItem <T> cachedItem;

            async Task <T> RefreshItem()
            {
                var item = await getItem();

                cachedItem = new CachedItem <T>(item);
                string serializeObject = Serialize(cachedItem);

                value = Encoding.UTF8.GetBytes(serializeObject);
                logger.LogInformation($"updating cache {key}...");
#pragma warning disable 4014
                // ReSharper disable once MethodSupportsCancellation
                multilayerCache.SetAsync(key, value, cacheEntryOptions);
#pragma warning restore 4014
                return(item);
            }

            if (value == null)
            {
                appTelemetry.RecordMetric("cache-miss", 1, ("key", key));
                return(await RefreshItem());
            }

            var json = Encoding.UTF8.GetString(value);
            cachedItem = JsonConvert.DeserializeObject <CachedItem <T> >(json);
            var needRefresh = false;
            if (cachedItem.CreatedOn.Add(settings.TimeToLive) < DateTimeOffset.UtcNow)
            {
                appTelemetry.RecordMetric("cache-expired", 1, ("key", key));
                needRefresh = true;
            }
            else
            {
                var lastUpdateTime = await getLastModificationTime();

                if (lastUpdateTime != default && lastUpdateTime > cachedItem.CreatedOn)
                {
                    needRefresh = true;
                }
            }

            if (needRefresh)
            {
#pragma warning disable 4014
                // ReSharper disable once MethodSupportsCancellation
                Task.Factory.StartNew(RefreshItem);
#pragma warning restore 4014
            }

            return(cachedItem.Value);
        }