public GitHubWebhookProcessor(IGlobalConfigurationProvider globalConfigurationProvider, IGitHubClientProvider gitHubClientProvider, IRepositoryConfigurationProvider repositoryConfigurationProvider, SecretClient secretClient, GitHubRateLimiter limiter, IPullRequestTracker pullRequestTracker) { this.globalConfigurationProvider = globalConfigurationProvider; this.gitHubClientProvider = gitHubClientProvider; this.repositoryConfigurationProvider = repositoryConfigurationProvider; this.secretClient = secretClient; this.limiter = limiter; this.pullRequestTracker = pullRequestTracker; }
public RepositoryConfigurationProvider(IGitHubClientProvider gitHubClientProvider, IMemoryCache cache, GitHubRateLimiter limiter) { this.gitHubClientProvider = gitHubClientProvider; this.cache = cache; this.limiter = limiter; }
public CheckRunHandler(IGlobalConfigurationProvider globalConfigurationProvider, IGitHubClientProvider gitHubCLientProvider, IRepositoryConfigurationProvider repositoryConfigurationProvider, ILogger logger, GitHubRateLimiter limiter) : base(globalConfigurationProvider, gitHubCLientProvider, repositoryConfigurationProvider, logger, limiter) { }
public PullRequestTimeoutFunction(IPullRequestTracker pullRequestTracker, IGitHubClientProvider gitHubClientProvider, GitHubRateLimiter limiter, IRepositoryConfigurationProvider repositoryConfigurationProvider, IGlobalConfigurationProvider globalConfigurationProvider) { this.pullRequestTracker = pullRequestTracker; this.gitHubClientProvider = gitHubClientProvider; this.limiter = limiter; this.repositoryConfigurationProvider = repositoryConfigurationProvider; this.globalConfigurationProvider = globalConfigurationProvider; }
public Handler(IGlobalConfigurationProvider globalConfiguratoinProvider, IGitHubClientProvider gitHubClientProvider, IRepositoryConfigurationProvider repositoryConfigurationProvider, ILogger logger, GitHubRateLimiter limiter) { this.GlobalConfigurationProvider = globalConfiguratoinProvider; this.GitHubClientProvider = gitHubClientProvider; this.RepositoryConfigurationProvider = repositoryConfigurationProvider; this.Logger = logger; this.Limiter = limiter; }
public PullRequestHandler(IGlobalConfigurationProvider globalConfigurationProvider, IGitHubClientProvider gitHubClientProvider, IRepositoryConfigurationProvider repositoryConfigurationProvider, ILogger logger, GitHubRateLimiter limiter, IPullRequestTracker pullRequestTracker) : base(globalConfigurationProvider, gitHubClientProvider, repositoryConfigurationProvider, logger, limiter) { this.pullRequestTracker = pullRequestTracker; }
public GitHubClientProvider(IGlobalConfigurationProvider globalConfigurationProvider, IMemoryCache cache, CryptographyClient cryptographyClient, GitHubRateLimiter limiter) { this.globalConfigurationProvider = globalConfigurationProvider; this.cache = cache; this.cryptographyClient = cryptographyClient; this.limiter = limiter; }
public async Task Traffic([QueueTrigger("traffic")] string queueItem, ExecutionContext executionContext, ILogger logger) { DateTime functionStartDate = DateTime.UtcNow; string sessionId = Guid.NewGuid().ToString(); JsonSerializerSettings serializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None }; Repository repositoryDetails = JsonConvert.DeserializeObject <Repository>(queueItem, serializerSettings); FunctionContextWriter <FunctionContext> contextWriter = new FunctionContextWriter <FunctionContext>(); string identifier = $"Traffic"; FunctionContext context = new FunctionContext() { CollectorType = CollectorType.Traffic.ToString(), FunctionStartDate = functionStartDate, SessionId = sessionId, InvocationId = executionContext.InvocationId.ToString(), }; StatsTracker statsTracker = null; string outputPaths = string.Empty; bool success = false; ITelemetryClient telemetryClient = new GitHubApplicationInsightsTelemetryClient(this.telemetryClient, context, logger); try { telemetryClient.TrackEvent("SessionStart", GetRepositoryCollectorSessionStartEventProperties(context, identifier, repositoryDetails)); ICache <RateLimitTableEntity> rateLimiterCache = new AzureTableCache <RateLimitTableEntity>(telemetryClient, "ratelimiter"); await rateLimiterCache.InitializeAsync().ConfigureAwait(false); IRateLimiter rateLimiter = new GitHubRateLimiter(this.configManager.UsesGitHubAuth(context.CollectorType) ? repositoryDetails.OrganizationLogin : "******", rateLimiterCache, this.httpClient, telemetryClient, maxUsageBeforeDelayStarts: 50.0, this.apiDomain); ICache <ConditionalRequestTableEntity> requestsCache = new AzureTableCache <ConditionalRequestTableEntity>(telemetryClient, "requests"); await requestsCache.InitializeAsync().ConfigureAwait(false); GitHubHttpClient httpClient = new GitHubHttpClient(this.httpClient, rateLimiter, requestsCache, telemetryClient); IAuthentication authentication = this.configManager.GetAuthentication(CollectorType.Traffic, httpClient, repositoryDetails.OrganizationLogin, this.apiDomain); StorageManager storageManager; List <IRecordWriter> recordWriters; using (storageManager = this.configManager.GetStorageManager(context.CollectorType, telemetryClient)) { recordWriters = storageManager.InitializeRecordWriters(identifier, context, contextWriter, this.adlsClient.AdlsClient); IRecordStatsTracker recordStatsTracker = null; foreach (IRecordWriter recordWriter in recordWriters) { recordWriter.SetOutputPathPrefix($"{repositoryDetails.OrganizationId}/{repositoryDetails.RepositoryId}"); if (recordStatsTracker == null) { recordStatsTracker = recordWriter; } } statsTracker = new StatsTracker(telemetryClient, httpClient, recordStatsTracker, StatsTrackerRefreshFrequency); TrafficProcessor processor = new TrafficProcessor(authentication, recordWriters, httpClient, telemetryClient, this.apiDomain); await processor.ProcessAsync(repositoryDetails).ConfigureAwait(false); } await storageManager.FinalizeRecordWritersAsync().ConfigureAwait(false); outputPaths = RecordWriterExtensions.GetOutputPaths(recordWriters); success = true; } catch (Exception exception) when(!(exception is FatalException)) { telemetryClient.TrackException(exception, "Traffic failed."); throw exception; } finally { SendSessionEndEvent(telemetryClient, context.FunctionStartDate, outputPaths, GetRepositoryCollectorSessionStartEventProperties(context, identifier, repositoryDetails), success); statsTracker?.Stop(); } }
private async Task ExecuteTrafficCollector(ExecutionContext executionContext, ILogger logger) { DateTime functionStartDate = DateTime.UtcNow; string sessionId = Guid.NewGuid().ToString(); string identifier = "TrafficTimer"; CloudQueue trafficCloudQueue = await AzureHelpers.GetStorageQueueAsync("traffic").ConfigureAwait(false); IQueue trafficQueue = new CloudQueueWrapper(trafficCloudQueue); FunctionContext context = new FunctionContext() { CollectorType = CollectorType.TrafficTimer.ToString(), FunctionStartDate = functionStartDate, SessionId = sessionId, InvocationId = executionContext.InvocationId.ToString(), }; StatsTracker statsTracker = null; bool success = false; ITelemetryClient telemetryClient = new GitHubApplicationInsightsTelemetryClient(this.telemetryClient, context, logger); try { telemetryClient.TrackEvent("SessionStart", GetCollectorCommonSessionStartEventProperties(context, identifier)); ICache <RateLimitTableEntity> rateLimiterCache = new AzureTableCache <RateLimitTableEntity>(telemetryClient, "ratelimiter"); await rateLimiterCache.InitializeAsync().ConfigureAwait(false); ICache <ConditionalRequestTableEntity> requestsCache = new AzureTableCache <ConditionalRequestTableEntity>(telemetryClient, "requests"); await requestsCache.InitializeAsync().ConfigureAwait(false); string organizations = await AzureHelpers.GetBlobContentAsync("github-settings", "organizations.json").ConfigureAwait(false); JArray organizationsArray = JArray.Parse(organizations); foreach (JToken organizationToken in organizationsArray) { JObject organization = (JObject)organizationToken; string organizationLogin = organization.SelectToken("$.OrganizationLogin").Value <string>(); long organizationId = organization.SelectToken("$.OrganizationId").Value <long>(); IRateLimiter rateLimiter = new GitHubRateLimiter(this.configManager.UsesGitHubAuth(context.CollectorType) ? organizationLogin : "******", rateLimiterCache, this.httpClient, telemetryClient, maxUsageBeforeDelayStarts: 80.0, this.apiDomain); GitHubHttpClient httpClient = new GitHubHttpClient(this.httpClient, rateLimiter, requestsCache, telemetryClient); statsTracker = new StatsTracker(telemetryClient, httpClient, StatsTrackerRefreshFrequency); IAuthentication authentication = this.configManager.GetAuthentication(CollectorType.TrafficTimer, httpClient, organizationLogin, this.apiDomain); CollectorBase <GitHubCollectionNode> collector = new GitHubCollector(httpClient, authentication, telemetryClient, new List <IRecordWriter>()); GitHubCollectionNode repositoriesNode = new GitHubCollectionNode() { RecordType = DataContract.RepositoryInstanceRecordType, ApiName = DataContract.RepositoriesApiName, GetInitialUrl = additionalMetadata => OnboardingProcessor.InitialRepositoriesUrl(organizationLogin, this.apiDomain), ProcessRecordAsync = async record => { string repositoryName = record.SelectToken("$.name").Value <string>(); long repositoryId = record.SelectToken("$.id").Value <long>(); Repository repository = new Repository(organizationId, repositoryId, organizationLogin, repositoryName); await trafficQueue.PutObjectAsJsonStringAsync(repository, TimeSpan.MaxValue).ConfigureAwait(false); return(new List <RecordWithContext>()); }, }; await collector.ProcessAsync(repositoriesNode).ConfigureAwait(false); } success = true; } catch (Exception exception) when(!(exception is FatalException)) { telemetryClient.TrackException(exception, "TrafficTimer failed."); throw exception; } finally { SendSessionEndEvent(telemetryClient, context.FunctionStartDate, outputPaths: string.Empty, GetCollectorCommonSessionStartEventProperties(context, identifier), success); statsTracker?.Stop(); } }
public async Task ProcessWebHookActivity([ActivityTrigger] IDurableActivityContext durableContext) { OrchestrationContext context = durableContext.GetInput <OrchestrationContext>(); string requestBody = context.RequestBody; WebhookProcessorContext functionContext = context.Downgrade(); WebhookProcessorContextWriter contextWriter = new WebhookProcessorContextWriter(); JObject record = JObject.Parse(requestBody); string organizationName; Dictionary <string, string> additionalTelemetryProperties = new Dictionary <string, string>(); foreach (KeyValuePair <string, string> property in GetMainCollectorSessionStartEventProperties(functionContext, identifier: functionContext.EventType, functionContext.LogicAppRunId)) { additionalTelemetryProperties.Add(property.Key, property.Value); } string outputPaths = string.Empty; bool success = false; ITelemetryClient telemetryClient = new GitHubApplicationInsightsTelemetryClient(this.telemetryClient, functionContext); try { // Not all payloads have a "repository" attribute e.g., membership, organization, project, project_card, etc. paylods. Look under $organization attribute first, if available. JToken organizationNameToken = record.SelectToken("$.organization.login"); if (organizationNameToken == null) { organizationNameToken = record.SelectToken("$.repository.owner.login"); } if (organizationNameToken == null) { // NOTE: BELOW RELEVANT IF WE ARE RELYING ON APP WEBHOOKS // In theory, all event payloads will have repository.owner.login (see https://developer.github.com/webhooks/event-payloads/#webhook-payload-object-common-properties) // However, there are certain app-specific webhooks (e.g. new_permissions_accepted, which is not documented/can't be found by a search engine) that lack this. // note: other example app-specific webhooks - app installed into repo, app uninstalled from repo, etc. throw new FatalTerminalException("Could not find organization name in webhook payload."); } organizationName = organizationNameToken.Value <string>(); IEventsBookkeeper eventsBookkeeper = new EventsBookkeeper(telemetryClient); await eventsBookkeeper.InitializeAsync().ConfigureAwait(false); ICache <RecordTableEntity> recordsCache = new AzureTableCache <RecordTableEntity>(telemetryClient, "records"); await recordsCache.InitializeAsync().ConfigureAwait(false); ICache <RepositoryItemTableEntity> collectorCache = new AzureTableCache <RepositoryItemTableEntity>(telemetryClient, "github"); await collectorCache.InitializeAsync().ConfigureAwait(false); ICache <RateLimitTableEntity> rateLimiterCache = new AzureTableCache <RateLimitTableEntity>(telemetryClient, "ratelimiter"); await rateLimiterCache.InitializeAsync().ConfigureAwait(false); ICache <ConditionalRequestTableEntity> requestsCache = new AzureTableCache <ConditionalRequestTableEntity>(telemetryClient, "requests"); await requestsCache.InitializeAsync().ConfigureAwait(false); IRateLimiter rateLimiter = new GitHubRateLimiter(this.configManager.UsesGitHubAuth(context.CollectorType) ? organizationName : "*", rateLimiterCache, this.httpClient, telemetryClient, maxUsageBeforeDelayStarts: 90.0, this.apiDomain); GitHubHttpClient httpClient = new GitHubHttpClient(this.httpClient, rateLimiter, requestsCache, telemetryClient); IAuthentication authentication = this.configManager.GetAuthentication(CollectorType.Main, httpClient, organizationName, this.apiDomain); StorageManager storageManager; List <IRecordWriter> recordWriters; using (storageManager = this.configManager.GetStorageManager(context.CollectorType, telemetryClient)) { recordWriters = storageManager.InitializeRecordWriters(identifier: functionContext.EventType, functionContext, contextWriter, this.adlsClient.AdlsClient); WebHookProcessor processor = new WebHookProcessor(requestBody, functionContext, authentication, httpClient, recordWriters, eventsBookkeeper, recordsCache, collectorCache, telemetryClient, this.apiDomain); additionalTelemetryProperties = await processor.ProcessAsync().ConfigureAwait(false); foreach (KeyValuePair <string, string> property in GetMainCollectorSessionStartEventProperties(functionContext, identifier: functionContext.EventType, functionContext.LogicAppRunId)) { additionalTelemetryProperties.Add(property.Key, property.Value); } } await storageManager.FinalizeRecordWritersAsync().ConfigureAwait(false); outputPaths = RecordWriterExtensions.GetOutputPaths(recordWriters); success = true; } catch (Exception exception) when(!(exception is FatalException)) { telemetryClient.TrackException(exception, "ProcessWebHookActivity failed."); throw exception; } finally { SendSessionEndEvent(telemetryClient, functionContext.FunctionStartDate, outputPaths, additionalTelemetryProperties, success); } }