인시던트와 JIRA 양방향 연동 모범 사례¶
작성자: Su Tongtong, Liu Rui
인시던트는 Guance에서 제공하는, 내부 인시던트를 효과적으로 조정하고 관리하기 위한 커뮤니케이션 관리 도구입니다.
JIRA는 기업 내부 프로젝트 관리 도구입니다.
Info
애플리케이션이나 시스템에 이상이 발생하면 일반적으로 시스템의 정상적인 운영을 위해 신속하게 처리해야 합니다. 인시던트와 JIRA의 양방향 연동을 통해 기업 내 관련 담당자가 문제 장애의 원인을 신속하게 파악 및 분석하고, 장애 처리 과정을 추적 및 기록하여 의사소통 효율성을 높이고 장애 처리 비용을 크게 절감할 수 있습니다.
사전 준비¶
- Jira 플랫폼 (관리자 권한 필요)
- Guance 워크스페이스 계정
- DataFlux Func Guance 특별판
Jira¶
Jira 플랫폼에서 해당 프로젝트의 project, 프로젝트 주소, api_token, username을 가져옵니다. 이후 Guance 스크립트에서 사용됩니다.
관리자만 위 작업을 수행할 수 있습니다.
Guance¶
API Key 생성¶
API Key는 문서 API Key를 참조하세요.
key name은 Jira 시스템으로 설정하는 것이 좋습니다. 이렇게 하면 해당 댓글 정보가 Guance 또는 Jira에서 왔는지 구분하기 쉬우며, key name은 Guance issue 내에서 user로 표시됩니다.
Func 스크립트 작성¶
- Func 로그인
배포된 DataFlux Func Guance 특별판에 로그인합니다.
-
Python 의존성 추가
-
관리 메뉴를 클릭합니다.
- 실험적 기능을 클릭하고 PIP 도구 활성화 스위치를 켭니다. 이미 활성화된 경우 이 단계를 건너뜁니다.
-
PIP 도구를 클릭하고 Python 패키지 설치에서 jira를 입력한 후 기본 데이터 소스를 선택합니다. 기본 데이터 소스에 해당 의존성이 없으면 다른 데이터 소스로 전환할 수 있습니다. 설치 버튼을 클릭하여 의존성 설치를 완료합니다.
-
스크립트 작성
-
개발 메뉴를 클릭합니다.
- 새 스크립트 세트 버튼을 클릭하고 스크립트 ID를 입력합니다. 사용자 정의할 수 있으며 여기서는
Issue_to_jira를 입력합니다. 저장 버튼을 클릭합니다. Issue_to_jira를 선택하고 새 스크립트를 클릭합니다. 이 ID도 임의로 작성할 수 있습니다.- 다음 스크립트 내용을 붙여넣고 설정 정보를 조정합니다.
import requests
import json
import time
from datetime import datetime, timedelta
from jira import JIRA
# Guance 설정, df_api_key 수정 필요
base_url = 'https://openapi.guance.com'
channel_list_url = base_url + '/api/v1/channel/quick_list'
issue_list_url = base_url + '/api/v1/issue/list'
create_issue_reply_url = base_url + '/api/v1/issue/reply/create'
df_api_key = 'vy2EV......fuTtn'
# JIRA 설정, 아래 설정은 모두 필수 항목이며 자신의 환경으로 수정
username = 'sutt'
api_token = 'ATATT3xFfGF0eVvhZUkO0tTas8JnNYEsxGIJqWGinVyQL0ME......B6E'
jira_server_url = 'https://***.net/'
project_key = 'projectName'
#JIRA 연결
def connect_to_jira(username, api_token, jira_server_url):
try:
jira_connection = JIRA(basic_auth=(username, api_token), server=jira_server_url)
print("JIRA 연결 성공!")
return jira_connection
except Exception as e:
print(f"JIRA 연결 오류: {e}")
return None
jira_instance = connect_to_jira(username, api_token, jira_server_url)
def sync_issues_from_guance_to_jira():
headers = {
'DF-API-KEY': df_api_key,
'Content-Type': 'application/json;charset=UTF-8'
}
one_minute_ago = datetime.now() - timedelta(minutes=1)
one_minute_ago_time = int(one_minute_ago.timestamp())
current_time = int(time.time())
response = requests.get(channel_list_url, headers=headers)
if response.status_code == 200:
channel_list = response.json()["content"]
for channel in channel_list:
if channel["name"] == "default":
body = {
'channelUUID': channel["uuid"],
'startTime': one_minute_ago_time,
'endTime': current_time
}
issue_response = requests.post(issue_list_url, headers=headers, data=json.dumps(body))
print(issue_response.text) # 응답 내용 출력, 디버깅에 도움
if issue_response.status_code == 200:
issue_lists = issue_response.json()['content']
for issue in issue_lists:
issue_uuid = issue["uuid"]
print(f"Guance의 UUID: {issue_uuid}") # UUID 디버깅 출력
issue_data = {
'project': {'key': project_key},
'summary': issue["name"],
'description': issue["description"],
'issuetype': {'name': '결함'},
'priority': {'name': 'Medium'},
'labels': [issue_uuid] # label을 사용하여 issue_id 저장
}
created_issue = jira_instance.create_issue(fields=issue_data)
print(f"JIRA issue 생성됨: {created_issue.key}")
def create_issue_reply(issue_uuid, content):
headers = {
'DF-API-KEY': df_api_key,
'Content-Type': 'application/json;charset=UTF-8'
}
body = {
'issueUUID': issue_uuid,
'content': content,
'extend': {}
}
response = requests.post(create_issue_reply_url, headers=headers, data=json.dumps(body))
if response.status_code == 200:
print(f"issueUUID에 대한 댓글 생성 성공: {issue_uuid}")
else:
print(f"issueUUID에 대한 댓글 생성 실패: {issue_uuid}. 상태 코드: {response.status_code}")
def sync_comments_from_jira_to_guance():
end_time = datetime.now()
start_time = end_time - timedelta(minutes=1)
start_time_str = start_time.strftime('%Y-%m-%d %H:%M')
end_time_str = end_time.strftime('%Y-%m-%d %H:%M')
jql_str = f'project = {project_key} AND updated >= "{start_time_str}" AND updated <= "{end_time_str}"'
recently_updated_issues = jira_instance.search_issues(jql_str)
has_updates = False
for issue in recently_updated_issues:
comments = jira_instance.comments(issue)
new_comments = [comment for comment in comments if start_time_str <= comment.created.split('.')[0].replace("T", " ") <= end_time_str]
issue_labels = issue.fields.labels
guance_issue_id = None
for label in issue_labels:
if label.startswith("issue"):
guance_issue_id = label
break
if guance_issue_id and new_comments:
has_updates = True
for comment in new_comments:
create_issue_reply(guance_issue_id, comment.body)
if not has_updates:
print("지난 1분 동안 업데이트된 이슈나 새로운 댓글이 없습니다.")
@DFF.API('Create_JIRA_Issue_Reply2')
def guance():
print("시작")
sync_issues_from_guance_to_jira()
sync_comments_from_jira_to_guance()
- 스크립트 게시
게시 버튼을 클릭하면 게시가 완료됩니다. 게시가 완료되면 API가 성공적으로 게시되어 외부에서 서비스를 제공할 수 있습니다.
- 자동 트리거 설정
자동 트리거 설정을 통해 API를 정기적으로 실행할 수 있습니다.
- 관리 메뉴에서 자동 트리거 설정 버튼을 클릭합니다.
- 오른쪽 상단의 생성 버튼을 클릭하여 새로 생성합니다.
- 실행할 스크립트를 선택하고 매개변수는 지정하지 않아도 됩니다. 해당 실행 빈도를 선택합니다. 여기서는 1분마다 반복으로 조정하고 저장합니다.
Issue 생성¶
Guance에는 두 가지 방식으로 issue를 생성할 수 있습니다.
- 직접 생성
- 모니터를 통해 생성
직접 생성¶
- Guance 콘솔에 로그인합니다.
- 인시던트 메뉴를 클릭하고 오른쪽 상단의 Issue 생성 버튼을 클릭한 후 issue 정보를 입력하고 저장합니다.
모니터를 통해 생성¶
모니터를 통해 생성은 모니터에서 이벤트 정보를 생성하여 issue를 생성하는 방식입니다.
- Guance 콘솔에 로그인합니다.
- 왼쪽의 모니터링 메뉴를 클릭합니다.
- 새 모니터를 추가하거나 기존 모니터를 조정할 수 있습니다. 해당 모니터를 편집하고 Issue 동기화 생성 스위치를 켠 후 저장합니다.
결과 화면¶
Jira 결과:¶
Jira issue가 자동으로 생성되었습니다. 댓글을 작성하면 Guance에서 issue 처리 과정을 확인할 수 있습니다.
Guance 결과¶
Guance에서도 Jira issue 처리 과정이 동기화됩니다.



