🌻
コピペとコマンド実行のみでSentryのIssuesをCSV形式で書き出す
こんにちは
It's summerですね🍉
導入
みなさまエラー監視ツールは何を使われてますでしょうか。
弊社はモバイルアプリにSentryを使っています。
まだ部分的にしか適用しておらず、エラー数もそこまで多くないためDeveloperプラン($0)で利用しています。
当該プランの場合、コンソール画面からのCSV書き出しに対応していないためAPI経由で取得する必要があります。
事前準備
正味、ChatGPT先生がはき出してくれたコードなので大きな顔はできませんが備忘録として
api_token
, organization_slug
, project_slug
はSentryのSettingsから確認し、置き換えてください。
api_token
https://your_org.sentry.io/settings/account/api/auth-tokens/
の新しいトークンを生成から生成
organization_slug
https://your_org.sentry.io/settings/organization/
のOrganization Slug
project_slug
https://your_org.sentry.io/settings/projects/your_project_name/
のA name for this project
具体的な話
-
sentry_issues_export.py
とか適当にファイルを作り下記の内容で保存します - 当該ファイルのあるディレクトリで以下を実行します
python3 export_sentry_issues.py
sentry_issues_export.py
import requests
import csv
from datetime import datetime, timedelta
# Sentry APIの設定
api_token = 'your_api_token'
organization_slug = 'your_org_slug'
project_slug = 'your_project_slug'
sentry_api_url = f'https://sentry.io/api/0/projects/{organization_slug}/{project_slug}/issues/'
# ヘッダーの設定
headers = {
'Authorization': f'Bearer {api_token}',
'Content-Type': 'application/json',
}
# 対象期間の設定(例:過去30日間)
end_date = datetime.utcnow()
start_date = end_date - timedelta(days=30)
start = start_date.isoformat() + 'Z'
end = end_date.isoformat() + 'Z'
# Issueを取得する
issues = []
cursor = None
while True:
params = {
'limit': 100,
'start': start,
'end': end,
'query': 'is:unresolved', # ここでは未解決のIssueをフィルタリング
}
if cursor:
params['cursor'] = cursor
response = requests.get(sentry_api_url, headers=headers, params=params)
data = response.json()
issues.extend(data)
# 次のページがあるかどうか確認
link_header = response.headers.get('Link')
if 'results="false"' in link_header:
break
cursor = link_header.split('; rel="next",')[1].split('cursor=')[1].split('&')[0]
# Issueごとにイベントを集計する関数
def get_event_count(issue_id):
url = f'https://sentry.io/api/0/issues/{issue_id}/events/'
events = []
cursor = None
while True:
params = {
'limit': 100,
'start': start,
'end': end,
}
if cursor:
params['cursor'] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
events.extend(data)
link_header = response.headers.get('Link')
if 'results="false"' in link_header:
break
cursor = link_header.split('; rel="next",')[1].split('cursor=')[1].split('&')[0]
return len(events)
# 各Issueのイベント数を集計
for issue in issues:
issue['event_count'] = get_event_count(issue['id'])
# CSVに書き出す
with open('sentry_issues.csv', 'w', newline='') as csvfile:
fieldnames = ['id', 'title', 'status', 'culprit', 'permalink', 'firstSeen', 'lastSeen', 'event_count']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for issue in issues:
writer.writerow({
'id': issue['id'],
'title': issue['title'],
'status': issue['status'],
'culprit': issue['culprit'],
'permalink': issue['permalink'],
'firstSeen': issue['firstSeen'],
'lastSeen': issue['lastSeen'],
'event_count': issue['event_count'],
})
取得項目
まぁ見たまんまやんけみたいな感じですが、以下の項目を取得するようにしてます
- id
- IssueのID
- title
- Issueのタイトル
- e.g.
App Hanging: App hanging for at least 2000 ms.
とか
- e.g.
- Issueのタイトル
- status
- Issueのステータス
- e.g.
unresolved(未解決)
とか
- e.g.
- Issueのステータス
- culprit
- Issueの発生場所的な
- e.g.
logger.dart in Logger.error
とか
- e.g.
- Issueの発生場所的な
- permalink
- Issueへのリンク
- e.g.
https://your_org.sentry.io/issues/123456xxx/
とか
- e.g.
- Issueへのリンク
- firstSeen, lastSeen
- Issueの初回発生と直近発生のタイムスタンプ
- e.g.
2024-07-05T08:29:53.046000Z
とか
- e.g.
- Issueの初回発生と直近発生のタイムスタンプ
- event_count
- Issueのイベント数
-
count
だと初回発生からの累計発生回数を取得してきてしまったので、私の場合はイベント数で取得するようにしました
-
- Issueのイベント数
間違いやここもっと良くできるよ的なことがあればコメントくださいませ🙏🏻
Discussion