public async Task <string> ProcessDynatraceAlert() { Log.Info("In ProcessDynatraceAlert(), notificationObject.ImpactedEnties: " + this.NotificationObject?.ImpactedEntities); FixedEvent[] fixedEvents = await fixMostRecentDeploymentsOnEntities(NotificationObject?.ImpactedEntities, DEFAULT_TIME_SPAN); Log.Info("fixed events, updating problem ticket"); // we have our information and can now iterate and update the problem ticket foreach (var fixedEvent in fixedEvents) { Log.Info("fixedEvent: " + fixedEvent); // create comment body var commentBody = new FixedEventComment { comment = "Triggered release " + fixedEvent.OrigEvent?.deploymentName.Value + " " + fixedEvent.RollbackReleaseId + " in project " + fixedEvent.OrigEvent?.deploymentProject.Value, user = "******", context = "Azure Function" }; Log.Info("Created FixedEventComment object: " + JsonConvert.SerializeObject(commentBody)); // post comment body to dynatrace problem comments var fullUrl = this.DTTenantUrl + "/api/v1/problem/details/" + this.NotificationObject?.PID.Value + "/comments"; Log.Info("full url: " + fullUrl); var response = await DynatraceAPIHelper.Post(fullUrl, this.DTApiToken, JsonConvert.SerializeObject(commentBody)); var statusCode = response.StatusCode; var data = await response.Content.ReadAsStringAsync(); this.Log.Info("Push comment to Dynatrace: " + fullUrl + " " + statusCode + "-" + data); } return("Executed Handler successfully!"); }
/** * Returns the most recent CUSTOM_DEPLOYMENT event on these passed entites where the event.source == VSTS * */ private async Task <dynamic[]> getMostRecentDeploymentOnEntity(dynamic entities, int timespan) { this.Log.Info("Starting getMostRecentDeploymentOnEntity"); List <dynamic> resultEvents = new List <dynamic>(); this.Log.Info("Iterating through all entities"); foreach (var entity in entities) { this.Log.Info("Entity: " + entity); // build out dynatrace query to get most recent deployment event for each entity var dtEventUrl = this.DTTenantUrl + "/api/v1/events"; var to = DateTime.Now; var from = to.Subtract(new TimeSpan(0, 0, 0, 0, timespan)); var queryString = "?entitydId=" + entity?.entity + "&eventType=CUSTOM_DEPLOYMENT"; if (timespan > 0) { queryString += "&to=" + DynatraceAPIHelper.ConvertToJSSMilliseconds(to) + "&from=" + DynatraceAPIHelper.ConvertToJSSMilliseconds(from); } // execute query to dynatrace this.Log.Info("Executing query to Dynatrace: " + queryString); HttpResponseMessage response = await DynatraceAPIHelper.Post(dtEventUrl + queryString, this.DTApiToken, null); if (response.StatusCode == HttpStatusCode.OK) { this.Log.Info("Got valid response from dynatrace"); // get list of events from response dynamic data = await response.Content.ReadAsAsync <object>(); this.Log.Info("response data: " + data); var events = data?.events; // test code, should read this from the response //var dataString = "{\n \"nextEventStartTms\": null,\n \"nextEventId\": null,\n \"nextCursor\": null,\n \"from\": 1532067180000,\n \"to\": 1532110380000,\n \"totalEventCount\": 1,\n \"events\": [\n \n {\n \"eventId\": 7587387097431610000, \"startTime\": 1532086141275,\n \"endTime\": 153208614127,\n \n \"entityId\": \"SERVICE - 8AC3A0761537D748\",\n \"entityName\": \"SampleNodeJsService\",\n \"severityLevel\": null,\n \"impactLevel\": \"SERVICE\",\n \"eventType\": \"CUSTOM_DEPLOYMENT\",\n \"eventStatus\": \"CLOSED\",\n \"tags\": [\n {\n \"context\": \"CONTEXTLESS\",\n \"key\": \"DeploymentGroup\",\n \"value\": \"Production\"\n }\n ],\n \"id\": \"7587387097431610671_1532086141275\",\n \"customProperties\": {\n \"CodeDeploy.DeploymentGroup\": \"Production\",\n \"PipelineStage\": \"Production\",\n \"PipelineName\": \"SampleDevOpsPipeline\",\n \"CodeDeploy.DeploymentId\": \"d - 4P826EJDU\",\n \"CodeDeploy.Application\": \"SampleDevOpsApp\",\n \"PipelineAction\": \"PushDynatraceDeploymentEvent\"\n },\n \"deploymentProject\": \"SampleDevOpsPipeline\",\n \"remediationAction\": \"https://42g9h6vd6i.execute-api.us-east-1.amazonaws.com/v1/HandleDynatraceProblem\",\n \"deploymentVersion\": \"78\", \"deploymentName\": \"CodePipeline Deploying in Production\",\n \"source\": \"VSTS\"\n }\n ]\n }"; //dynamic data = JsonConvert.DeserializeObject(dataString); //var events = data?.events; // only look at most recent one that came from VSTS, once you find the first one, break out of for loop this.Log.Info("Iterating through all events, find first one from VSTS"); foreach (var problemEvent in events) { this.Log.Info("ProblemEvent: " + problemEvent); if (problemEvent?.source.Value.Equals("VSTS")) { // only push it if the same deployment id is not already on the list var exists = resultEvents.Any(item => item?.deploymentVersion == problemEvent?.deploymentVersion); if (!exists) { resultEvents.Add(problemEvent); } break; } } } } this.Log.Info("Finisehd with getMostRecentDeploymentOnEntity, resultEvents: " + resultEvents); return(resultEvents.ToArray()); }
public async Task <string> ProcessDynatraceAlert() { var DTTimeSpanMS = 60 * 1000 * Int32.Parse(this.DTTimeSpanMinutes); Log.Info("ProcessDynatraceAlert: notificationObject.ImpactedEnties: " + this.NotificationObject?.ImpactedEntities); FixedEvent[] fixedEvents = await fixMostRecentDeploymentsOnEntities(NotificationObject?.ImpactedEntities, DTTimeSpanMS); Log.Info("ProcessDynatraceAlert: fixed events, updating problem ticket"); // we have our information and can now iterate and update the problem ticket if (fixedEvents.Length > 0) { foreach (var fixedEvent in fixedEvents) { Log.Info("ProcessDynatraceAlert: fixedEvent: " + fixedEvent); // create comment body var commentBody = new FixedEventComment { comment = "Triggered release deploymentName: " + fixedEvent.OrigEvent?.deploymentName.Value + " RollbackReleaseId: " + fixedEvent.RollbackReleaseId + " in project " + fixedEvent.OrigEvent?.deploymentProject.Value, user = "******", context = "Azure Function" }; Log.Info("ProcessDynatraceAlert: Created FixedEventComment object: " + JsonConvert.SerializeObject(commentBody)); // post comment body to dynatrace problem comments var fullUrl = this.DTTenantUrl + "/api/v1/problem/details/" + this.NotificationObject?.PID.Value + "/comments"; Log.Info("full url: " + fullUrl); var response = await DynatraceAPIHelper.Post(fullUrl, this.DTApiToken, JsonConvert.SerializeObject(commentBody)); var statusCode = response.StatusCode; var data = await response.Content.ReadAsStringAsync(); this.Log.Info("ProcessDynatraceAlert: Push comment to Dynatrace: " + fullUrl + " " + statusCode + "-" + data); if ((int)statusCode != 200) { throw new Exception("ProcessDynatraceAlert: Error udpating Dynatrace deployment entity: " + data); } } } else { throw new Exception("ProcessDynatraceAlert: There are no recent Dynatrace deployment entities to update"); } return("Executed Handler successfully!"); }