В связи с ситуацией и отключением плагинов табеля рабочего времени в Jira я начал изучать тему получения нужной информации по трудозатратам через Jira API. Даже нашел несколько статей на эту тему на уважаемом ресурсе. Но, как оказалось, некоторые моменты устарели, а некоторые были упущены авторами, либо они на них просто не наткнулись.
Итак, для работы с Jira через python есть уже готовая библиотека с документацией.
Задумка возникла следующая: писать в базу PG данные по трудозатратам и визуализировать их с помощью Yandex DataLens. Дополнительно для экономистов и PM готовить выгрузку в EXCEL. Соответственно, изначально получилось вот так:
from pickle import TRUE
from jira import JIRA
import re
import time
import traceback
from datetime import datetime , timedelta
import psycopg2
import pandas as pd
Далее приведу примеры того, что поменялось с момента написания аналогичных статей.
Подключение к Jira
Подключится удалось только через логин и ... внимание — токен. Аутентификация через логин-пароль или только через токен была неуспешной.
Соответственно в Jira под админом создаете токен. Его имя неважно, оно нигде не используется. Далее используете его и логин (я использовал свой админский).
login = 'your_jira_login@gmail.com'
token_val = 'you_jira_token_generated_for_app'
jira_options = {'server': 'https://you_project.atlassian.net'}
jira = JIRA(options=jira_options, basic_auth= (login,token_val))
Далее есть куча примеров, и описано в документации, как получать список issue. Тут также важный момент, что по умолчанию Jira отдает не более 100 issues за запрос, и важно отключить это ограничение, иначе данные будут неполные. Выясняется это, когда начинаешь тестировать и сравнивать выгруженный результат со старыми выгрузками из плагина Timesheet (нужно добавить maxResults=0 в метод search_issues).
jsql_str = f"worklogDate >= {work_date_start_str} AND worklogDate <= {work_date_end_str} ORDER BY created DESC"
issues_list = jira.search_issues(jql_str = jsql_str,maxResults=0)
Следующие грабли связаны с получением журнала логов. Аналогично, есть лимит на получение записей work_log. Тут ограничение установлено в 20 записей. Просто установкой параметра здесь не обойтись, и нужно использовать вместо issue.fields.worklog.worklogs — jira.worklogs(issue = issue.key). Он не имеет ограничений на количество записей. Другого способа обойти ограничение я не нашел.
work_log_df = []
for work_logs in jira.worklogs(issue = issue.key): # надо делать именно так. чтобы обойти ограничение в 20 записей на issue
print (work_logs.started)
print (work_logs.created)
print (work_logs.self)
worklog_date_str = re.search(r'(\d{4}-\d{2}-\d{2})', work_logs.started)
worklog_date = datetime.strptime(worklog_date_str.group(0), '%Y-%m-%d')
if work_logs.timeSpent is not None and worklog_date >= work_date_from and worklog_date <= work_date_to:
work_line = {}
#print(issue.key)
isuekey = issue.key
work_line['key'] = isuekey
#print(issue.fields.project.key)
projkey = issue.fields.project.key
proj_name = issue.fields.project.name
work_line['project'] = projkey
work_line['project_name'] = proj_name
Далее собираем данные для Excel и вставки в БД. Данные в БД удаляются перед вставкой за выбранный период, после чего определяется курсор для вставки. В этой версии вставляем по одной строке:
try:
conn = psycopg2.connect('postgresql://jiraapi:user@host:port/jiradb')
print("Connect to database successfully")
cur = conn.cursor()
sql = """delete from public.jira_tasks where work_date >= %s and work_date <= %s;"""
cur.execute(sql,(work_date_start_str,work_date_end_str))
conn.commit()
cur.close()
print("Data in period deleted")
cur = conn.cursor()
sql = """INSERT INTO public.jira_tasks(project,project_name,task,work_time,work_time_sec,wuser,work_date) VALUES(%s,%s,%s,%s,%s,%s,%s);"""
except:
print("Can't connect to database")
Для удобства анализа данных в EXCEL сразу выводим месяц и дату в файл:
work_line['worklog_date'] = worklog_date
work_line['work_hours'] = round(swork_time_sec / 3600,2)
work_line['month'] = worklog_date.strftime("%m")
work_line['day'] = worklog_date.strftime("%d")
work_line['year'] = worklog_date.strftime("%Y")
Непосредственно запись в БД и вывод файла в EXCEL с обработкой возможных ошибок.
cur.execute(sql, (projkey,proj_name,isuekey,swork_time,swork_time_sec,sauthor,worklog_date))
work_log_df.append(work_line)
n = n + 1
conn.commit()
cur.close()
if n >= 1:
file_name = 'WorkLog_' + str(n) + '_' + work_date_start_str + '_' + work_date_end_str + '.xlsx'
pd.DataFrame(work_log_df).to_excel(file_name, index=False)
print ('Выгружено ' + str(n) + ' записей')
else:
Print('Нет данных для выгрузки')
except:
cur.close()
print('Ошибка при записи данных', traceback.format_exc())
Работа с DataLens
Решил попробовать, что такое DataLens от Yandex.
Первое, что надо сделать — создать «подключение к БД». Выбираем Postgress из возможных вариантов.
После создания подключения создаем датасет. Тут все просто. Выбираем наше подключение, ниже выводятся доступные таблицы и view. Вытаскиваем нужный в область справа.
После создания датасета можно делать диаграммы, а затем из готовых создавать дашборд. Набор диаграмм стандартный, жаль, что нет ничего типа календаря. Пришлось использовать сводную таблицу. И не успел разобраться с drill_down, и есть ли он вообще в DataLens, пока непонятно.
После того как вытащили диаграммы на дашборд, можно создать единые фильтры для всего дашборда.
В итоге получилось вот так:
Вторая часть дашборда:
К сожалению, периодически возникает ошибка при обращении к датасету и иногда какие-то «глюки», но в целом BI работает. DataLense + Excel дали функционал по аналитике даже немного больший, чем плагины, НО, конечно, анализировать трудозатраты и сразу закрывать пропуски непосредственно в Jira разработчикам было удобнее )