使用 Pandas 進(jìn)行 JIRA 分析
問題
很難說 atlassian jira 是最受歡迎的問題跟蹤器和項(xiàng)目管理解決方案之一。你可以喜歡它,也可以討厭它,但如果你被某家公司聘用為軟件工程師,那么很有可能會(huì)遇到 jira。
如果您正在從事的項(xiàng)目非常活躍,可能會(huì)有數(shù)千個(gè)各種類型的 jira 問題。如果您領(lǐng)導(dǎo)著一個(gè)工程師團(tuán)隊(duì),您可能會(huì)對(duì)分析工具感興趣,這些工具可以幫助您根據(jù) jira 中存儲(chǔ)的數(shù)據(jù)了解項(xiàng)目中發(fā)生的情況。 jira 集成了一些報(bào)告工具以及第三方插件。但其中大多數(shù)都是非常基本的。例如,很難找到相當(dāng)靈活的“預(yù)測(cè)”工具。
項(xiàng)目越大,您對(duì)集成報(bào)告工具的滿意度就越低。在某些時(shí)候,您最終將使用 api 來提取、操作和可視化數(shù)據(jù)。在過去 15 年的 jira 使用過程中,我看到了圍繞該領(lǐng)域的數(shù)十個(gè)采用各種編程語言的此類腳本和服務(wù)。
許多日常任務(wù)可能需要一次性數(shù)據(jù)分析,因此每次都編寫服務(wù)并沒有什么回報(bào)。您可以將 jira 視為數(shù)據(jù)源并使用典型的數(shù)據(jù)分析工具帶。例如,您可以使用 jupyter,獲取項(xiàng)目中最近的錯(cuò)誤列表,準(zhǔn)備“特征”列表(對(duì)分析有價(jià)值的屬性),利用 pandas 計(jì)算統(tǒng)計(jì)數(shù)據(jù),并嘗試使用 scikit-learn 預(yù)測(cè)趨勢(shì)。在這篇文章中,我想解釋一下如何做到這一點(diǎn)。
準(zhǔn)備
jira api 訪問
這里我們要說的是云版jira。但如果您使用的是自托管版本,主要概念幾乎是相同的。
首先,我們需要?jiǎng)?chuàng)建一個(gè)密鑰來通過 rest api 訪問 jira。為此,請(qǐng)轉(zhuǎn)到配置文件管理 – id.atlassian/manage-profile/profile-and-visibility 如果選擇“安全”選項(xiàng)卡,您將找到“創(chuàng)建和管理 api 令牌”鏈接:
在此處創(chuàng)建一個(gè)新的 api 令牌并安全地存儲(chǔ)它。我們稍后會(huì)使用這個(gè)令牌。
jupyter 筆記本
處理數(shù)據(jù)集最方便的方法之一是使用 jupyter。如果您不熟悉這個(gè)工具,請(qǐng)不要擔(dān)心。我將展示如何使用它來解決我們的問題。對(duì)于本地實(shí)驗(yàn),我喜歡使用 jetbrains 的 dataspell,但也有免費(fèi)的在線服務(wù)。 kaggle 是數(shù)據(jù)科學(xué)家中最知名的服務(wù)之一。但是,他們的筆記本不允許您建立外部連接以通過 api 訪問 jira。另一項(xiàng)非常受歡迎的服務(wù)是 google 的 colab。它允許您進(jìn)行遠(yuǎn)程連接并安裝額外的 python 模塊。
jira 有一個(gè)非常易于使用的 rest api。您可以使用您最喜歡的 http 請(qǐng)求方式進(jìn)行 api 調(diào)用并手動(dòng)解析響應(yīng)。然而,我們將利用一個(gè)優(yōu)秀且非常流行的 jira 模塊來實(shí)現(xiàn)此目的。
實(shí)際使用的工具
數(shù)據(jù)分析
讓我們結(jié)合所有部分來提出解決方案。
進(jìn)入google colab界面并創(chuàng)建一個(gè)新筆記本。創(chuàng)建筆記本后,我們需要將之前獲得的 jira 憑據(jù)存儲(chǔ)為“秘密”。單擊左側(cè)工具欄中的“密鑰”圖標(biāo)打開相應(yīng)的對(duì)話框并添加兩個(gè)具有以下名稱的“秘密”:jira_user 和 jira_password。在屏幕底部,您可以看到如何訪問這些“秘密”:
接下來是安裝額外的 python 模塊以進(jìn)行 jira 集成。我們可以通過在筆記本單元范圍內(nèi)執(zhí)行 shell 命令來做到這一點(diǎn):
!pip install jira
輸出應(yīng)如下所示:
collecting jira
downloading jira-3.8.0-py3-none-any.whl (77 kb)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 77.5/77.5 kb 1.3 mb/s eta 0:00:00
requirement already satisfied: defusedxml in /usr/local/lib/python3.10/dist-packages (from jira) (0.7.1)
...
installing collected packages: requests-toolbelt, jira
successfully installed jira-3.8.0 requests-toolbelt-1.0.0
我們需要獲取“秘密”/憑證:
from google.colab import userdata
jira_url = '******.atlassian'
jira_user = userdata.get('jira_user')
jira_password = userdata.get('jira_password')
并驗(yàn)證與 jira cloud 的連接:
from jira import jira jira = jira(jira_url, basic_auth=(jira_user, jira_password)) projects = jira.projects() projects
如果連接正常并且憑據(jù)有效,您應(yīng)該會(huì)看到一個(gè)非空的項(xiàng)目列表:
[<jira project: key="proj1" name="name here.." id="10234">, <jira project: key="proj2" name="friendly name.." id="10020">, <jira project: key="proj3" name="one more project" id="10045">, ... </jira></jira></jira>
這樣我們就可以從 jira 連接并獲取數(shù)據(jù)了。下一步是獲取一些數(shù)據(jù)以使用 pandas 進(jìn)行分析。讓我們嘗試獲取某個(gè)項(xiàng)目在過去幾周內(nèi)已解決問題的列表:
jira_filter = 19762
issues = jira.search_issues(
f'filter={jira_filter}',
maxresults=false,
fields='summary,issuetype,assignee,reporter,aggregatetimespent',
)
我們需要將數(shù)據(jù)集轉(zhuǎn)換為pandas數(shù)據(jù)框:
import pandas as pd
df = pd.dataframe([{
'key': issue.key,
'assignee': issue.fields.assignee and issue.fields.assignee.displayname or issue.fields.reporter.displayname,
'time': issue.fields.aggregatetimespent,
'summary': issue.fields.summary,
} for issue in issues])
df.set_index('key', inplace=true)
df
輸出可能如下所示:
我們想分析一下解決問題通常需要多長時(shí)間。人都是不理想的,所以有時(shí)他們會(huì)忘記記錄工作。如果您嘗試使用 jira 內(nèi)置工具分析此類數(shù)據(jù),則會(huì)帶來麻煩。但我們用pandas做一些調(diào)整并不是問題。例如,我們可以將“時(shí)間”字段從秒轉(zhuǎn)換為小時(shí),并用中值替換缺失的值(注意,如果有很多間隙,dropna 可能更合適):
df['time'].fillna(df['time'].median(), inplace=true) df['time'] = df['time'] / 3600
我們可以輕松地可視化分布以找出異常情況:
df['time'].plot.bar(xlabel='', xticks=[])
查看受讓人解決的問題的分布也很有趣:
top_solvers = df.groupby('assignee').count()[['time']]
top_solvers.rename(columns={'time': 'tickets'}, inplace=true)
top_solvers.sort_values('tickets', ascending=false, inplace=true)
top_solvers.plot.barh().invert_yaxis()
它可能看起來像下面這樣:
預(yù)測(cè)
讓我們嘗試預(yù)測(cè)完成所有未決問題所需的時(shí)間。當(dāng)然,我們可以在沒有機(jī)器學(xué)習(xí)的情況下,通過使用簡單的近似和平均時(shí)間來解決問題。因此,預(yù)計(jì)所需時(shí)間就是未解決問題的數(shù)量乘以解決問題的平均時(shí)間。例如,解決一個(gè)問題的平均時(shí)間為 2 小時(shí),而我們有 9 個(gè)未解決的問題,因此解決所有問題所需的時(shí)間為 18 小時(shí)(近似值)。這是一個(gè)足夠好的預(yù)測(cè),但我們可能知道解決的速度取決于產(chǎn)品、團(tuán)隊(duì)和問題的其他屬性。如果我們想改進(jìn)預(yù)測(cè),我們可以利用機(jī)器學(xué)習(xí)來解決這個(gè)任務(wù)。
高級(jí)方法如下所示:
獲取“學(xué)習(xí)”數(shù)據(jù)集
清理數(shù)據(jù)
準(zhǔn)備“特征”,又名“特征工程”
訓(xùn)練模型
使用模型來預(yù)測(cè)目標(biāo)數(shù)據(jù)集的某些值
第一步,我們將使用過去 30 周的門票數(shù)據(jù)集。出于說明目的,此處對(duì)某些部分進(jìn)行了簡化。在現(xiàn)實(shí)生活中,用于學(xué)習(xí)的數(shù)據(jù)量應(yīng)該足夠大才能建立有用的模型(例如,在我們的例子中,我們需要分析數(shù)千個(gè)問題)。
issues = jira.search_issues(
f'project = pps and status in (resolved) and created >= -30w',
maxresults=false,
fields='summary,issuetype,customfield_10718,customfield_10674,aggregatetimespent',
)
closed_tickets = pd.dataframe([{
'key': issue.key,
'team': issue.fields.customfield_10718,
'product': issue.fields.customfield_10674,
'time': issue.fields.aggregatetimespent,
} for issue in issues])
closed_tickets.set_index('key', inplace=true)
closed_tickets['time'].fillna(closed_tickets['time'].median(), inplace=true)
closed_tickets
就我而言,大約有 800 張門票,并且只有兩個(gè)“學(xué)習(xí)”字段:“團(tuán)隊(duì)”和“產(chǎn)品”。
下一步是獲取我們的目標(biāo)數(shù)據(jù)集。我為什么這么早做?我想一次性清理兩個(gè)數(shù)據(jù)集并進(jìn)行“特征工程”。否則,結(jié)構(gòu)之間的不匹配可能會(huì)導(dǎo)致問題。
issues = jira.search_issues(
f'project = pps and status in (open, reopened)',
maxresults=false,
fields='summary,issuetype,customfield_10718,customfield_10674',
)
open_tickets = pd.dataframe([{
'key': issue.key,
'team': issue.fields.customfield_10718,
'product': issue.fields.customfield_10674,
} for issue in issues])
open_tickets.set_index('key', inplace=true)
open_tickets
請(qǐng)注意,我們這里沒有“時(shí)間”列,因?yàn)槲覀兿胍A(yù)測(cè)它。讓我們?nèi)∠⒔Y(jié)合兩個(gè)數(shù)據(jù)集來準(zhǔn)備“特征”。
open_tickets['time'] = 0 tickets = pd.concat([closed_tickets, open_tickets]) tickets
“團(tuán)隊(duì)”和“產(chǎn)品”列包含字符串值。處理這個(gè)問題的方法之一是將每個(gè)值轉(zhuǎn)換為帶有布爾標(biāo)志的單獨(dú)字段。
products = pd.get_dummies(tickets['product'], prefix='product')
tickets = pd.concat([tickets, products], axis=1)
tickets.drop('product', axis=1, inplace=true)
teams = pd.get_dummies(tickets['team'], prefix='team')
tickets = pd.concat([tickets, teams], axis=1)
tickets.drop('team', axis=1, inplace=true)
tickets
結(jié)果可能如下所示:
組合數(shù)據(jù)集準(zhǔn)備完畢后,我們可以將其分成兩部分:
closed_tickets = tickets[:len(closed_tickets)] open_tickets = tickets[len(closed_tickets):][:]
現(xiàn)在是時(shí)候訓(xùn)練我們的模型了:
from sklearn.model_selection import train_test_split from sklearn.tree import decisiontreeregressor features = closed_tickets.drop(['time'], axis=1) labels = closed_tickets['time'] features_train, features_val, labels_train, labels_val = train_test_split(features, labels, test_size=0.2) model = decisiontreeregressor() model.fit(features_train, labels_train) model.score(features_val, labels_val)
最后一步是使用我們的模型進(jìn)行預(yù)測(cè):
open_tickets['time'] = model.predict(open_tickets.drop('time', axis=1, errors='ignore'))
open_tickets['time'].sum() / 3600
最終的輸出,就我而言,是 25 小時(shí),這比我們最初的粗略估計(jì)要高。這是一個(gè)基本的例子。但是,通過使用 ml 工具,您可以顯著擴(kuò)展分析 jira 數(shù)據(jù)的能力。
有時(shí),jira 內(nèi)置工具和插件不足以進(jìn)行有效分析。此外,許多第 3 方插件相當(dāng)昂貴,每年花費(fèi)數(shù)千美元,而且您仍然很難讓它們按照您想要的方式工作。然而,您可以通過 jira api 獲取必要的信息,輕松利用眾所周知的數(shù)據(jù)分析工具,并超越這些限制。我花了很多時(shí)間使用各種 jira 插件,試圖為項(xiàng)目創(chuàng)建好的報(bào)告,但它們經(jīng)常錯(cuò)過一些重要的部分。在 jira api 之上構(gòu)建工具或功能齊全的服務(wù)通常看起來也有些過頭了。這就是為什么 jupiter、pandas、matplotlib、scikit-learn 等典型數(shù)據(jù)分析和 ml 工具在這里可能效果更好。
相關(guān)推薦
-
高級(jí) Ansible 技術(shù)和實(shí)際應(yīng)用:日復(fù)一日的 DevOps 工具系列
歡迎來到“50 天 50 個(gè) devops 工具”系列的第 31 天!在上一篇文章中,我們向您介紹了 ansible,涵蓋其基本架構(gòu)、設(shè)置和一些簡單的手冊(cè)。今天,我們將更深入地了解 ansible 的
-
Golang – 使用 GoFakeIt 生成假數(shù)據(jù)
介紹在軟件開發(fā)中,測(cè)試對(duì)于確保代碼按預(yù)期工作至關(guān)重要。然而,由于隱私問題、數(shù)據(jù)可用性以及收集和清理數(shù)據(jù)所需的巨大努力,獲取用于測(cè)試目的的真實(shí)數(shù)據(jù)可能具有挑戰(zhàn)性。這就是生成虛假數(shù)據(jù)變得無價(jià)的地方。在 g
-
golang框架在分布式數(shù)據(jù)庫系統(tǒng)中的應(yīng)用
go 框架在分布式數(shù)據(jù)庫系統(tǒng)中具有廣泛的應(yīng)用,可用框架包括 badgerdb、boltdb、cockroachdb、rethinkdb 和 cassandra。這些框架提供了高性能、可擴(kuò)展性和易用性,
-
C++ 函數(shù)性能分析工具的選型與使用指南
c++++ 函數(shù)性能分析可選擇 valgrind 或 gprof 工具。對(duì)復(fù)雜程序推薦 vtune amplifier。使用 valgrind 可安裝、編譯程序、運(yùn)行程序并分析結(jié)果,以找出性能瓶頸。實(shí)
-
Ansible 入門 – 初學(xué)者指南:日復(fù)一日的 DevOps 工具系列
歡迎來到“50 天 50 個(gè) devops 工具”系列的第 30 天!今天,我們將探索 ansible,它是 devops 工具包中最重要的工具之一。本博客將向您介紹 ansible 的基礎(chǔ)知識(shí),分解















