public void Get(IList <JQLFilterDTO> jqlFilters) { if (jqlFilters == null || jqlFilters.Any()) { try { string path = AppDomain.CurrentDomain.BaseDirectory + "Files/"; Directory.CreateDirectory(path); using (var file = new StreamWriter(path + "Azure.csv")) { foreach (var jqlFilter in jqlFilters) { _logger.Info($"Наичнаю получать тикеты по фильтру {jqlFilter.System.Name}"); var issues = _jiraClient.EnumerateIssuesByQuery(jqlFilter.JqlString, null, 0).ToList(); issues = _removingExcess.remove(issues); _logger.Info($"Получил из фильтра {jqlFilter.System.Name} тикетов {issues.Count()}"); using (var fileGrader = new StreamWriter(path + jqlFilter.System.Name + ".csv")) { _logger.Info($"Начинаю запись в файл {jqlFilter.System.Name}.csv"); foreach (var issue in issues) { var number = issue.key; var summary = _clearText.CleanUp(issue.fields.summary, _clearServiceUrl); var description = _clearText.CleanUp(issue.fields.description, _clearServiceUrl); var text = summary + " " + description; string line = $"{jqlFilter.System.Name};{text}"; file.WriteLine(line); string lineForGrader = $"{jqlFilter.System.Name};{number};{summary};{description}"; fileGrader.WriteLine(lineForGrader); } _logger.Info($"Закончил запись в файл {jqlFilter.System.Name}.csv"); } } _logger.Info($"Закончил запись в файл Azure.csv"); } } catch (Exception ex) { _logger.Error(ex, "Ошибка при записи данных в файл"); } } }
public void CheckJira() { using (var repository = new Repository <DbContext>()) //создаю репозиторий для работы с БД { try { var jira = new JiraClient(jiraParam.ValueString, userLoginParam.ValueString, userPasswordParam.ValueString); //объявляю клиент jira while (true) { var lastProcessedChangeDateParameter = repository.Get <Parametr>(p => p.Name == "processedchangedate"); var lastProcessedChangeDate = lastProcessedChangeDateParameter.ValueDate; //до какой даты изменения вычитаны var endCheckChangeDate = lastProcessedChangeDate.AddHours(1); //за сколько часов будем вычитывать изменения if (endCheckChangeDate > System.DateTime.Now) { endCheckChangeDate = System.DateTime.Now; } try { var issuses = jira.EnumerateIssuesByQuery( "project = SUPPORT AND updated >= \"" + lastProcessedChangeDate.ToString("yyyy-MM-dd HH:mm") + "\" AND updated <= \"" + endCheckChangeDate.ToString("yyyy-MM-dd HH:mm") + "\" ORDER BY key", null, 0).ToList(); //получил тикеты foreach (var issue in issuses) { // вычитываю SLA. Проверяю на null, если так, то делаю null var assignIssueFailed = issue.fields.customfield_13041.completedCycles.FirstOrDefault() == null? (bool?)null : issue.fields.customfield_13041.completedCycles.FirstOrDefault().breached; var assignTime = issue.fields.customfield_13041.completedCycles.FirstOrDefault() == null ? (long?)null : issue.fields.customfield_13041.completedCycles.FirstOrDefault().elapsedTime.millis; var slaTakeInWorkFailed = issue.fields.customfield_13042.completedCycles.FirstOrDefault() == null ? (bool?)null : issue.fields.customfield_13042.completedCycles.FirstOrDefault().breached; var takeInWorkTime = issue.fields.customfield_13042.completedCycles.FirstOrDefault() == null ? (long?)null : issue.fields.customfield_13042.completedCycles.FirstOrDefault().elapsedTime.millis; //этот SLA циклический, поэтому вычитываю все значения в цикле. //Если хоть раз нарушен, то считаем нарушенным //Время - среднее значение bool?slaWaitForAnswer = null; long?waitForAnswerTime = null; var slaWaitForAnswerList = issue.fields.customfield_13941.completedCycles; foreach (JiraApiOpenSourseLibrary.CompletedCycle slaCompletedCycle in slaWaitForAnswerList) { slaWaitForAnswer = slaWaitForAnswer != null ? slaWaitForAnswer & slaCompletedCycle.breached : slaCompletedCycle.breached; waitForAnswerTime = waitForAnswerTime != null ? waitForAnswerTime + slaCompletedCycle.elapsedTime.millis : slaCompletedCycle.elapsedTime.millis; } if (waitForAnswerTime != null) { waitForAnswerTime /= slaWaitForAnswerList.Count; } //обрабатываю тип тикета TicketType ticketTypeFromDb = null; if (issue.fields.issuetype != null) { ticketTypeFromDb = repository.Get <TicketType>( ticketType => ticketType.id == issue.fields.issuetype.id); if (ticketTypeFromDb == null) { ticketTypeFromDb = (new TicketType() { id = issue.fields.issuetype.id, name = issue.fields.issuetype.name }); repository.Create(ticketTypeFromDb); } } //обрабатываю тип статус тикета Status statusFromDb = null; if (issue.fields.status != null) { statusFromDb = repository.Get <Status>(status => status.id == issue.fields.status.id); if (statusFromDb == null) { statusFromDb = (new Status() { id = issue.fields.status.id, name = issue.fields.status.name }); repository.Create(statusFromDb); } } //Отправитель Reporter reporterFromDb = null; if (issue.fields.reporter != null) { reporterFromDb = repository.Get <Reporter>( user => user.emailAddress == issue.fields.reporter.emailAddress); if (reporterFromDb == null) { reporterFromDb = (new Reporter() { name = issue.fields.reporter.name, emailAddress = issue.fields.reporter.emailAddress, displayName = issue.fields.reporter.displayName, }); repository.Create(reporterFromDb); } } //Исполнитель Assignee assigneeFromDb = null; if (issue.fields.assignee != null) { assigneeFromDb = repository.Get <Assignee>( user => user.emailAddress == issue.fields.assignee.emailAddress); if (assigneeFromDb == null) { assigneeFromDb = (new Assignee() { name = issue.fields.assignee.name, emailAddress = issue.fields.assignee.emailAddress, displayName = issue.fields.assignee.displayName, }); repository.Create(assigneeFromDb); } } //Приоритет Priority priorityFromDb = null; if (issue.fields.priority != null) { priorityFromDb = repository.Get <Priority>(priority => priority.id == issue.fields.priority.id); if (priorityFromDb == null) { priorityFromDb = (new Priority() { id = issue.fields.priority.id, name = issue.fields.priority.name }); repository.Create(priorityFromDb); } } //Список меток, связь многие ко многим var ticketLablesList = new List <Lable>(); foreach (string lbl in issue.fields.labels) { var replable = repository.Get <Lable>(lable => lable.value == lbl); if (replable == null) { ticketLablesList.Add(new Lable() { value = lbl }); } else { ticketLablesList.Add(replable); } } //обрабатываю сам тикет var ticketFromDB = repository.Get <Ticket>(ticket => ticket.Key == issue.key); if (ticketFromDB == null) { repository.Create(new Ticket() { Assignee = assigneeFromDb, Created = issue.fields.created, Key = issue.key, Lable = ticketLablesList, Priority = priorityFromDb, Reporter = reporterFromDb, Status = statusFromDb, Summary = issue.fields.summary, TicketType = ticketTypeFromDb, Updated = issue.fields.updated, ResolutionDate = issue.fields.resolutiondate, AssignTime = assignTime, TakeInWorkTime = takeInWorkTime, WaitForAnswerTime = waitForAnswerTime, SlaAssignIssueFailed = assignIssueFailed, SlaTakeInWorkFailed = slaTakeInWorkFailed, SlaWaitForAnswerFailed = slaWaitForAnswer }); } else { ticketFromDB.Assignee = assigneeFromDb; ticketFromDB.Created = issue.fields.created; ticketFromDB.Key = issue.key; if (ScrambledEquals(ticketFromDB.Lable, ticketLablesList)) { ticketFromDB.Lable = ticketLablesList; } ticketFromDB.Priority = priorityFromDb; ticketFromDB.Reporter = reporterFromDb; ticketFromDB.Status = statusFromDb; ticketFromDB.Summary = issue.fields.summary; ticketFromDB.TicketType = ticketTypeFromDb; ticketFromDB.Updated = issue.fields.updated; ticketFromDB.ResolutionDate = issue.fields.resolutiondate; ticketFromDB.AssignTime = assignTime; ticketFromDB.TakeInWorkTime = takeInWorkTime; ticketFromDB.WaitForAnswerTime = waitForAnswerTime; ticketFromDB.SlaAssignIssueFailed = assignIssueFailed; ticketFromDB.SlaTakeInWorkFailed = slaTakeInWorkFailed; ticketFromDB.SlaWaitForAnswerFailed = slaWaitForAnswer; repository.Update(); } } } catch (Exception ex) { repository.Create(new Log { Date = DateTime.Now, MessageTipe = "error", Operation = "ProcessTicket", Exception = ex.GetType() + ": " + ex.Message }); Thread.Sleep(int.Parse(intervalParam.ValueString)); } lastProcessedChangeDateParameter.ValueDate = endCheckChangeDate; repository.Update(); Thread.Sleep(int.Parse(intervalParam.ValueString)); } } catch (Exception e) { Thread.Sleep(int.Parse(intervalParam.ValueString)); repository.Create(new Log { Date = DateTime.Now, MessageTipe = "error", Operation = "CheckJiraError", Exception = e.GetType() + ": " + e.Message }); } } }
void CheckJira() { using (var repository = new Repository <DbContext>()) //создаю репозиторий для работы с БД { var jira = new JiraClient(jiraParam.Value, userLoginParam.Value, userPasswordParam.Value); //объявляю клиент jira while (true) //бесконечный цикл по проверке тикетов, переданных разработчикам { repository.Create(new Log { Date = DateTime.Now, MessageTipe = "info", Operation = "Начал получать тикеты из фильтра \"" + filterParam.Value + " \"", Exception = "" }); IEnumerable <Issue> issues = null; //список тикетов в Escallation int cnt = 0; //количество тикетов в Escallation try { issues = jira.EnumerateIssuesByQuery(filterParam.Value, null, 0).ToList(); cnt = issues.Count(); } catch (Exception ex) { repository.Create(new Log { Date = DateTime.Now, MessageTipe = "error", Operation = "Не удалось получить тикеты из Jira", Exception = ex.Message }); continue; //прерываю щикл } repository.Create(new Log { Date = DateTime.Now, MessageTipe = "info", Operation = "Получено тикетов " + cnt, Exception = "" }); foreach (var issue in issues) //смотрю все тикеты { try { if (issue.fields.labels.Contains("watch")) //если есть метка watch перехожу к следующему тикету { continue; //прерываю цикл foreach } //здесь уже метки watch у тикета нет var links = issue.fields.issuelinks; //смотрю, есть ли линки у тикета if (links != null) { int countOfLinks = links.Count; //суммарное количество ссылок int countOfClosedLinks = 0; //количество ссылок на закрытые тикеты foreach (var link in links) { var inwardIssue = link.inwardIssue; //есть входящие и исходящие связи в тикете var outwardIssue = link.outwardIssue; if (link.inwardIssue.id != null) //считаем входящие связи с закрытыми тикетами { var ticket = jira.LoadIssue(inwardIssue); if ((!ticket.key.Contains("WAPI") && !ticket.key.Contains("OLAP") && !ticket.key.Contains("ONLINE") && ticket.fields.status.name == "Закрыто") || (ticket.key.Contains("WAPI") && ticket.fields.status.name == "Выпущено") || (ticket.key.Contains("OLAP") && ticket.fields.status.name == "Выпущено") || (ticket.key.Contains("ONLINE") && ticket.fields.status.name == "Выпущено")) { countOfClosedLinks++; } } if (link.outwardIssue.id != null) //считаем исходящие связи с закрытыми тикетами { var ticket = jira.LoadIssue(outwardIssue); if ((!ticket.key.Contains("WAPI") && !ticket.key.Contains("OLAP") && !ticket.key.Contains("ONLINE") && ticket.fields.status.name == "Закрыто") || (ticket.key.Contains("WAPI") && ticket.fields.status.name == "Выпущено") || (ticket.key.Contains("OLAP") && ticket.fields.status.name == "Выпущено") || (ticket.key.Contains("ONLINE") && ticket.fields.status.name == "Выпущено")) { countOfClosedLinks++; } } } if (countOfLinks == countOfClosedLinks) //смотрим что суммарное количество линков равно сумме линков к решёнными и закрытым тикетам { //у тикета нет метода Refresh, поэтому я смотрю, что его статус всё еще Решён if (jira.EnumerateIssuesByQuery("key = " + issue.key, null, 0) .FirstOrDefault() .fields.status.name == "Решено") { continue; } issue.fields.labels.Add("watch"); jira.CreateComment(issue, "Все связанные тикеты на команду разработки были решены или закрыты." + Environment.NewLine + "Необходимо убедиться, что проблема решена и закрыть данный тикет, сообщив пользователю, когда исправление будет в релизе.", new Visibility { type = "role", value = "Service Desk Collaborators" }); repository.Create(new Log { Date = DateTime.Now, MessageTipe = "info", Operation = "Тикету " + issue.key + " добавлена метка watch", Exception = "" }); } } Thread.Sleep(1000); //ждём секунду, чтобы не перенапряч jira } catch (Exception e) { repository.Create(new Log { Date = DateTime.Now, MessageTipe = "error", Operation = "Ошибка при обработке тикета " + issue.key, Exception = e.Message }); } } Thread.Sleep(10000); //ждём 10 секунд, прежде чем снова начать проверять все тикеты в Escalation } } }