异常追踪与 JIRA 实现双向联动

本文详细描述了如何利用观测云和JIRA进行异常追踪,通过API实现故障报告、项目管理和自动化流程,提升团队协作效率。

前言

当应用程序或系统出现异常时,通常需要及时处理以保证系统的正常运行。通过异常追踪与 JIRA 双向联动,可以让企业内部相关人员快速了解、分析问题故障发生的原因、追溯并记录故障的处理过程,有效提高人员的沟通效率,极大降低了故障处理成本。

异常追踪是观测云推出的、基于内部异常有效协调的沟通管理工具。JIRA 为企业内部项目管理工具。

准备工作

Jira

获取 Jira 平台对应项目的 project、项目地址、api_token、username,后续观测云脚本需要用到。

只有管理员才有权限进行以上操作

观测云

创建 API Key

API Key 可参考文档:API Key 管理 - 观测云文档

其中 key name 设置为 Jira 系统,有利于区分该评论信息来源于观测云或者是 Jira,且 key name 会作为 user 展示在观测云 issue 当中。

Func 脚本编写

  • 登陆 Func:登陆到已经部署的 Dataflux Func 观测云特别版
  • 添加 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

# 观测云配置,注意修改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"UUID from Guance: {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"Created 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"Successfully created a reply for issueUUID: {issue_uuid}")
    else:
        print(f"Failed to create a reply for issueUUID: {issue_uuid}. Status code: {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("在过去的一分钟内没有更新的事务或者新的评论。")

@DFF.API('Create_JIRA_Issue_Reply2')
def guance():
    print("do start")
    sync_issues_from_guance_to_jira()
    sync_comments_from_jira_to_guance()

  • 发布脚本:点击发布按钮即完成发布。发布完成后,表示 API 已经发布成功,可以对外进行服务
  • 自动触发配置:定时执行 API
    • 管理菜单进入,点击自动触发配置按钮
    • 点击右上角新建按钮进行新建
    • 选择执行的脚本,参数可以不指定,勾选对应的执行频率,这里调整为按每分钟重复保存即可

创建 issue

观测云有两种创建 issue 的方式:直接创建通过监控器创建

直接创建
  • 登陆观测云控制台
  • 点击异常追踪菜单,点击右上角新建 Issue按钮,填写 issue 信息,保存即可
通过监控器创建

通过监控器创建即通过监控器产生事件信息,进行创建 issue。

  • 登陆观测云控制台
  • 点击左侧监控菜单
  • 可以新增监控器,也可以调整原有的监控器。编辑对应的监控器,开启同步创建 Issue 开关,保存

效果图

Jira 效果

自动产生 Jira issue,当进行评论后,可以在观测云上展示 issue 的处理过程。

观测云效果

观测云上也会同步 Jira issue 处理过程。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值