internal async Task <bool> ConfigureAsync(InstanceName instance, string name, bool?disable = null, bool?impersonate = null, bool?bypassrules = null, CancellationToken cancellationToken = default) { var webFunctionApp = await GetWebApp(instance, cancellationToken); var configuration = await AggregatorConfiguration.ReadConfiguration(webFunctionApp); var ruleConfig = configuration.GetRuleConfiguration(name); if (disable.HasValue) { ruleConfig.IsDisabled = disable.Value; } if (impersonate.HasValue) { ruleConfig.Impersonate = impersonate.Value; } if (bypassrules.HasValue) { ruleConfig.BypassRules = impersonate.Value; } ruleConfig.WriteConfiguration(webFunctionApp); return(true); }
internal async Task <bool> ChangeAppSettingsAsync(InstanceName instance, DevOpsLogon devopsLogonData, SaveMode saveMode, CancellationToken cancellationToken) { var webFunctionApp = await GetWebApp(instance, cancellationToken); var configuration = await AggregatorConfiguration.ReadConfiguration(webFunctionApp); configuration.DevOpsTokenType = devopsLogonData.Mode; configuration.DevOpsToken = devopsLogonData.Token; configuration.SaveMode = saveMode; configuration.WriteConfiguration(webFunctionApp); return(true); }
internal async Task <bool> ChangeAppSettings(InstanceName instance, VstsLogon vstsLogonData) { var webFunctionApp = await azure .AppServices .WebApps .GetByResourceGroupAsync( instance.ResourceGroupName, instance.FunctionAppName); var configuration = new AggregatorConfiguration(); configuration.VstsTokenType = vstsLogonData.Mode; configuration.VstsToken = vstsLogonData.Token; configuration.Write(webFunctionApp); return(true); }
internal async Task <bool> ChangeAppSettingsAsync(InstanceName instance, DevOpsLogon devopsLogonData, SaveMode saveMode, CancellationToken cancellationToken) { var webFunctionApp = await azure .AppServices .WebApps .GetByResourceGroupAsync( instance.ResourceGroupName, instance.FunctionAppName, cancellationToken); var configuration = new AggregatorConfiguration { DevOpsTokenType = devopsLogonData.Mode, DevOpsToken = devopsLogonData.Token, SaveMode = saveMode }; configuration.Write(webFunctionApp); return(true); }
internal async Task <IEnumerable <RuleOutputData> > ListAsync(InstanceName instance, CancellationToken cancellationToken) { var kudu = GetKudu(instance); _logger.WriteInfo($"Retrieving Functions in {instance.PlainName}..."); var webFunctionApp = await GetWebApp(instance, cancellationToken); cancellationToken.ThrowIfCancellationRequested(); var configuration = await AggregatorConfiguration.ReadConfiguration(webFunctionApp); using (var client = new HttpClient()) { KuduFunction[] kuduFunctions; using (var request = await kudu.GetRequestAsync(HttpMethod.Get, $"api/functions", cancellationToken)) using (var response = await client.SendAsync(request, cancellationToken)) { var stream = await response.Content.ReadAsStreamAsync(); if (!response.IsSuccessStatusCode) { _logger.WriteError($"{response.ReasonPhrase} {await response.Content.ReadAsStringAsync()}"); return(Enumerable.Empty <RuleOutputData>()); } using (var sr = new StreamReader(stream)) using (var jtr = new JsonTextReader(sr)) { var js = new JsonSerializer(); kuduFunctions = js.Deserialize <KuduFunction[]>(jtr); } } List <RuleOutputData> ruleData = new List <RuleOutputData>(); foreach (var kuduFunction in kuduFunctions) { var ruleName = kuduFunction.Name; var ruleFileUrl = $"api/vfs/site/wwwroot/{ruleName}/{ruleName}.rule"; _logger.WriteInfo($"Retrieving Function Rule Details {ruleName}..."); using (var request = await kudu.GetRequestAsync(HttpMethod.Get, ruleFileUrl, cancellationToken)) using (var response = await client.SendAsync(request, cancellationToken)) { var stream = await response.Content.ReadAsStreamAsync(); if (!response.IsSuccessStatusCode) { _logger.WriteError($"{response.ReasonPhrase} {await response.Content.ReadAsStringAsync()}"); continue; } var ruleCode = new List <string>(); using (var sr = new StreamReader(stream)) { string line; while ((line = sr.ReadLine()) != null) { ruleCode.Add(line); } } var ruleConfiguration = configuration.GetRuleConfiguration(ruleName); var(preprocessedRule, _) = RuleFileParser.Read(ruleCode.ToArray()); ruleData.Add(new RuleOutputData(instance, ruleConfiguration, preprocessedRule.LanguageAsString())); } } return(ruleData); } }
public static StatsdnetConfiguration Parse(string configFile) { var config = new StatsdnetConfiguration(); var xml = XDocument.Parse(File.ReadAllText(configFile)); var statsdnet = xml.Element("statsdnet"); config.Name = statsdnet.Attribute("name").Value; if (statsdnet.Attributes().Any(p => p.Name == "hideSystemStats")) { config.HideSystemStats = statsdnet.ToBoolean("hideSystemStats"); } // Add listeners foreach (var item in statsdnet.Element("listeners").Elements()) { ListenerConfiguration listener = null; switch (item.Name.LocalName) { case "udp": listener = new UDPListenerConfiguration(item.ToInt("port")); break; case "tcp": listener = new TCPListenerConfiguration(item.ToInt("port")); break; case "http": listener = new HTTPListenerConfiguration(item.ToInt("port")); if (item.Attribute("headerKey") != null) { ((HTTPListenerConfiguration)listener).HeaderKey = item.Attribute("headerKey").Value; } break; case "statsdnet": listener = new StatsdnetListenerConfiguration(item.ToInt("port")); break; case "mssql-relay": listener = new MSSQLRelayListenerConfiguration(item.Attribute("connectionString").Value, item.ToInt("batchSize"), item.ToBoolean("deleteAfterSend"), item.ToTimeSpan("pollInterval")); break; default: throw new ArgumentOutOfRangeException("Not sure what this listener is: " + item.Name); } config.Listeners.Add(listener); } // Add Backends foreach (var item in statsdnet.Element("backends").Elements()) { string name = item.Name.LocalName; config.BackendConfigurations[name] = item; } // Add aggregators var flushInterval = statsdnet.Element("aggregation").ToTimeSpan("flushInterval"); config.FlushInterval = flushInterval; var aggregatorGroup = new AggregatorConfiguration(); foreach (var item in statsdnet.Element("aggregation").Elements()) { switch (item.Name.LocalName) { case "gauges": config.Aggregators.Add("gauges", new GaugeAggregatorConfig(ns: item.Attribute("namespace").Value, removeZeroGauges: item.ToBoolean("removeZeroGauges"))); break; case "counters": config.Aggregators.Add("counters", new CounterAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "sets": config.Aggregators.Add("sets", new SetAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "calendargrams": config.Aggregators.Add("calendargrams", new CalendargramAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "timers": var timerConfig = new TimersAggregationConfig(ns: item.Attribute("namespace").Value, calculateSumSquares: item.ToBoolean("calculateSumSquares")); config.Aggregators.Add("timers", timerConfig); // Now add the percentiles foreach (var subItem in item.Elements()) { if (!timerConfig.AddPercentile(new PercentileConfig( name: subItem.Attribute("name").Value, threshold: subItem.ToInt("threshold"), flushInterval: subItem.ToTimeSpan("flushInterval") ))) { // TODO: log that a duplicate percentile was ignored } } break; } } return(config); }
public static StatsdnetConfiguration Parse(string configFile) { var config = new StatsdnetConfiguration(); var xml = XDocument.Parse(File.ReadAllText(configFile)); var statsdnet = xml.Element("statsdnet"); config.Name = statsdnet.Attribute("name").Value; if (statsdnet.Attributes().Any(p => p.Name == "hideSystemStats")) { config.HideSystemStats = statsdnet.ToBoolean("hideSystemStats"); } // Add listeners foreach (var item in statsdnet.Element("listeners").Elements()) { ListenerConfiguration listener = null; switch (item.Name.LocalName) { case "udp": listener = new UDPListenerConfiguration(item.ToInt("port")); break; case "tcp": listener = new TCPListenerConfiguration(item.ToInt("port")); break; case "http": listener = new HTTPListenerConfiguration(item.ToInt("port")); if (item.Attribute("headerKey") != null) { ((HTTPListenerConfiguration)listener).HeaderKey = item.Attribute("headerKey").Value; } break; case "statsdnet": listener = new StatsdnetListenerConfiguration(item.ToInt("port")); break; case "mssql-relay": listener = new MSSQLRelayListenerConfiguration(item.Attribute("connectionString").Value, item.ToInt("batchSize"), item.ToBoolean("deleteAfterSend"), item.ToTimeSpan("pollInterval")); break; default: throw new ArgumentOutOfRangeException("Not sure what this listener is: " + item.Name); } config.Listeners.Add(listener); } // Add Backends foreach (var item in statsdnet.Element("backends").Elements()) { string name = item.Name.LocalName; config.BackendConfigurations[name] = item; } // Add aggregators var flushInterval = statsdnet.Element("aggregation").ToTimeSpan("flushInterval"); config.FlushInterval = flushInterval; var aggregatorGroup = new AggregatorConfiguration(); foreach (var item in statsdnet.Element("aggregation").Elements()) { switch (item.Name.LocalName) { case "gauges": config.Aggregators.Add("gauges", new GaugeAggregatorConfig(ns: item.Attribute("namespace").Value, removeZeroGauges: item.ToBoolean("removeZeroGauges"))); break; case "counters": config.Aggregators.Add("counters", new CounterAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "sets": config.Aggregators.Add("sets", new SetAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "calendargrams": config.Aggregators.Add("calendargrams", new CalendargramAggregationConfig(ns: item.Attribute("namespace").Value)); break; case "timers": var timerConfig = new TimersAggregationConfig(ns: item.Attribute("namespace").Value, calculateSumSquares: item.ToBoolean("calculateSumSquares")); config.Aggregators.Add("timers", timerConfig); // Now add the percentiles foreach (var subItem in item.Elements()) { if (!timerConfig.AddPercentile(new PercentileConfig( name: subItem.Attribute("name").Value, threshold: subItem.ToInt("threshold"), flushInterval: subItem.ToTimeSpan("flushInterval") ))) { // TODO: log that a duplicate percentile was ignored } } break; } } return config; }
public async Task <IActionResult> PostAsync(WebHookEvent eventData, string ruleName, CancellationToken cancellationToken) { var aggregatorVersion = RequestHelper.AggregatorVersion; _log.LogInformation($"Aggregator v{aggregatorVersion} executing rule '{ruleName}'"); var webHookStartEvent = new EventTelemetry() { Name = "WebHookEvent Start" }; webHookStartEvent.Properties["rule"] = ruleName; webHookStartEvent.Properties["eventType"] = eventData?.EventType; webHookStartEvent.Properties["resourceVersion"] = eventData?.ResourceVersion; Telemetry.TrackEvent(webHookStartEvent); if (eventData == null) { return(BadRequest("Request body is empty")); } // sanity check if (!DevOpsEvents.IsValidEvent(eventData.EventType) || eventData.PublisherId != DevOpsEvents.PublisherId) { _log.LogDebug("return BadRequest"); return(BadRequest(new { Error = "Not a good Azure DevOps post..." })); } var helper = new RequestHelper(_log); var eventContext = helper.CreateContextFromEvent(eventData); if (eventContext.IsTestEvent()) { Response.AddCustomHeaders(aggregatorVersion, ruleName); return(RespondToTestEventMessage(aggregatorVersion, ruleName)); } var configContext = _configuration; var configuration = AggregatorConfiguration.ReadConfiguration(configContext) .UpdateFromUrl(ruleName, GetRequestUri()); var logger = new ForwarderLogger(_log); var ruleProvider = new AspNetRuleProvider(logger, _configuration); var ruleExecutor = new RuleExecutor(logger, configuration); using (_log.BeginScope($"WorkItem #{eventContext.WorkItemPayload.WorkItem.Id}")) { try { var rule = await ruleProvider.GetRule(ruleName); var ruleStartEvent = new EventTelemetry() { Name = "Rule Exec Start" }; ruleStartEvent.Properties["rule"] = rule.Name; ruleStartEvent.Properties["ImpersonateExecution"] = rule.ImpersonateExecution.ToString(); ruleStartEvent.Properties["EnableRevisionCheck"] = rule.Settings.EnableRevisionCheck.ToString(); ruleStartEvent.Properties["eventType"] = eventContext.EventType; Telemetry.TrackEvent(ruleStartEvent); var ruleExecTimer = new Stopwatch(); ruleExecTimer.Start(); var execResult = await ruleExecutor.ExecuteAsync(rule, eventContext, cancellationToken); ruleExecTimer.Stop(); var ruleEndEvent = new EventTelemetry() { Name = "Rule Exec End" }; ruleEndEvent.Properties["rule"] = ruleName; ruleEndEvent.Metrics["duration"] = ruleExecTimer.ElapsedMilliseconds; Telemetry.TrackEvent(ruleEndEvent); if (string.IsNullOrEmpty(execResult)) { return(Ok()); } else { _log.LogInformation($"Returning '{execResult}' from '{rule.Name}'"); return(Ok(execResult)); } } catch (Exception ex) { _log.LogWarning($"Rule '{ruleName}' failed: {ex.Message}"); Telemetry.TrackException(ex); return(BadRequest(ex.Message)); } } }