pythonjiraticket-system

Python: Get Jira Tickets that returned an error


I'm using the atlassian rest API and creating issues through it. For accessing the API I'm using the JIRA-API-Wrapper see: https://pypi.org/project/jira/.

In my application I'm uploading a bunch of tickets. Due to performance reasons I'm using concurrent.futures. The tickets are uploaded via the following code:

fields = [{'project': 'Project', 'summary': 'New summary', 'issuetype': {'name': 'Task'}}, ....]
with concurrent.futures.ThreadPoolExecutor() as executor:
     data = executor.map(jira.create_issue, fields)

My problem is, that I'm not really sure how to get the information, when a ticket couldn't be uploaded for some reason. Everytime a ticket couldn't be uploaded, the JIRA-Wrapper returns a JIRAError-Exception. Therefore, I somehow have to count whenever I get a JIRAError. But unfortunally I'm not sure how to count the errors.

I know that the result can be retrieved via:

for i in data:
      counter = counter + 1
      print(i)

But because data contains the JIRAErrors the above code fails. This is why I tried the following.

try:
    for i in data:
       print(i)
 except:
        print(fields[counter])

But when the exception appears the code just continues. Therefore I tried solutions with a while-loop, but they also didn't get the right solution.

Is there a way to get the tickets, which couldn't be uploaded?


Solution

  • I haven't used jira-python myself. I wrote my own python client that I've been using for years. I'll have to give this a try myself.

    According to the documentation to create bulk issues: https://jira.readthedocs.io/en/latest/examples.html#issues

    issue_list = [
    {
        'project': {'id': 123},
        'summary': 'First issue of many',
        'description': 'Look into this one',
        'issuetype': {'name': 'Bug'},
    },
    {
        'project': {'key': 'FOO'},
        'summary': 'Second issue',
        'description': 'Another one',
        'issuetype': {'name': 'Bug'},
    },
    {
        'project': {'name': 'Bar'},
        'summary': 'Last issue',
        'description': 'Final issue of batch.',
        'issuetype': {'name': 'Bug'},
    }]
    issues = jira.create_issues(field_list=issue_list)
    

    Additionally, there is a note about the failures which you are interested in:

    Using bulk create will not throw an exception for a failed issue creation. It will return a list of dicts that each contain a possible error signature if that issue had invalid fields. Successfully created issues will contain the issue object as a value of the issue key.

    So to see the ones that failed, you would iterate through issues and look for error signatures.

    As far as performance issues, you could look at jira.create_issues(data, prefectch=false)

    https://jira.readthedocs.io/en/latest/api.html#jira.JIRA.create_issues

    prefetch (bool) – whether to reload the created issue Resource for each created issue so that all of its data is present in the value returned from this method.

    However, if you must use concurrent.futures, note that it will likely fail when calling via jira.create_issue if jira object has a state that needs to be saved between calls to create_issue when being run async.

    If a func call raises an exception, then that exception will be raised when its value is retrieved from the iterator.

    I would recommend using a separate jira object for each create_issue if you do not trust the create_issues() function.

    def create_issue(fields):
      print(fields)
      j_obj = JIRA(...)
      try:
        ret = j_obj.create_issue(fields)
      except:
        # Do something here
        ret = False
      return ret
    
    with concurrent.futures.ThreadPoolExecutor() as executor:
      data = executor.map(create_issue, issue_list)
      items = [item for item in data]
      print(items)
      # Interact with result
      pdb.set_trace()
    

    When you break into the trace, any successful issues created will be an Issue type, any failures will show up as False. This is just an example, and you can decide what you want to return, in whatever format you need.