Web page status monitor

Timothy Ryner April 24, 2023

Our organization has hundreds of sites & web apps, and no widely available “Uptime Robot” for teams to automatically notify them of accessibility issues. Everyone develops their own internal solutions, if anything at all. I’m looking to use Jira and Scriptrunner to deliver this kind of service. 

The plan is:

  • create a new project “PING”
  • use two custom fields “Website” (URL) & “Response” (Number)
  • Use a simple workflow “Site Up” & “Site Down”
  • allow users to create new issues for their site, they provide the URLs and Response info.

I need help writing the script. Not groovy fluent, so I’m going to start trying to piece this together. 

  • Use a Scriptrunner Job to run a script every few minutes.
  • Script looks at each issue in the PING project, grabs the URL and Response values and runs a connection check. 
    When the response matches, transition to “Site Up”. When the response doesn’t match or times out, transition to “Site Down”. 

We also have the Automation plugin at our disposal, but not sure it’s necessary or simplifies much. 

This is going to be a fun project, and I think a lot of people could get some good use from it!  Any help from the community is greatly appreciated!!

2 answers

0 votes
Andrew Laden
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 27, 2023

This really sounds like a case of "when all you have is a hammer, everything looks like a nail".

Trying to use Jira as a active monitoring system is well outside the box of what it is designed to do. Yes you could probably make it work, but it would take some serious hacking, and be less functional then solutions designed to to monitoring.

There are lots of good open source monitoring systems that can do what you want. I personally like zabbix. https://www.zabbix.com/ . Its has lots of functionality to check web pages built in. And it has its own notification engine, or you can feed it to ospgenie, and from there to jira if you want jira tickets.

Or you could use a cloud service like pingdom

Really think about if you want to be stuck owning this, as you will be the only one who understands it. Other then as an interesting science experiment, I don't think its worth it.

Timothy Ryner April 27, 2023

You’re not wrong that Jira is my hammer; I’ve solved dozens of unique problems with non-standard uses of the product over the years. 

I should have mentioned that I operate instances on 3 different networks that are completely air gapped, zero connection to the outside world. Additionally, getting new software in the door where I work is a bureaucratic nightmare.  Because of this, dozens (if not hundreds) of teams just develop their own solutions.  Python scripts and Lambda functions everywhere spitting out enough emails to choke a hundred inboxes. 

My Jira instance is already the center of many teams’ world for managing software, HR, inventory, business processes, and everything in between. Literally almost anything you can think of, one of my customers built a project to do track it. So it’s not inconvenient to advertise to my users an additional service. In fact, with Confluence and Tableau, I have several options to conceal what’s driving the actual service.

It won’t be “serious hacking”.  It’s a single, smartly written groovy script. Believe me, I hack stuff together all of the time. This ain’t that. 

I am envious that people can throw money at problems. I don’t have the same options. It’s just me, Jira, and a handful of plugins trying to help important people do important work. :)

Timothy Ryner April 27, 2023

And Jira being used for bug tracking hardly seems like a non-standard use. The bug is that the site is down. 

Andrew Laden
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 27, 2023

Tracking is one thing, monitoring is another. But hey, I get it, you use what you have.

Can't really help on the groovy part of the script. Though frankly, you could probably just use the rest API and write in python or whatever you have available. Could then run that out of Cron or whatever. Would perform better, (or at least not impact your Jira instance as much, since it wont be running the same JVM even if it runs on the same host, which it doesn't even have to.) Don't even need scriptrunner or automation for that.

Put the results in a two dimensional dashboard gadget for a nice display.

Good luck on it. Interested to see how it comes out.

Timothy Ryner April 28, 2023

Your correct that a simpler version simply involving Python would work.  My issue with that is it doesn't allow other teams to also track their sites without me needing to rewrite the script to accommodate new teams.  I'm trying to provide a simple, org-wide solution that can scale from one user to one thousand without any involvement from me. 

The idea here is that my customers can:

  • simply submit an issue to track their website
  • the script simply runs against all issues in the project, no reconfiguring from me for new sites
  • they get notifications of website problems directly in Jira (using Inbox plugin for in-app notifications), instead of yet another email notification.

This has the added benefit for of me:

  • being able to administer the service from the Jira site, not from an SSH session
  • being able to see success/failure directly in the Scriptrunner console
  • being able simplify the script at some point by using an automation rule to trigger it, so I have a no-code way of managing triggers and conditions.
  • and if it gets super popular, and I get system slowdowns, I can throw compute at that problem (it's the one way I can spend money).

Thanks for the convo.  I won't have to rewrite these points when it's released and leadership wants an overview.  :)

0 votes
Timothy Ryner April 25, 2023

Probably goes without saying, but ChatGPT4 writes a realistic looking script that never quite lands.  It was worth a try! :) 

 

import com.atlassian.jira.bc.issue.search.SearchService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.search.SearchResults
import com.atlassian.jira.web.bean.PagerFilter
import com.atlassian.jira.bc.issue.IssueService
import java.net.HttpURLConnection
import java.net.URL

def jiraAuthenticationContext = ComponentAccessor.jiraAuthenticationContext
def issueManager = ComponentAccessor.issueManager
def issueService = ComponentAccessor.getComponent(IssueService)
def searchService = ComponentAccessor.getComponent(SearchService)
def currentUser = jiraAuthenticationContext.loggedInUser
def checkWebsite(url) {
    def connection = (HttpURLConnection) new URL(url).openConnection()
    connection.setRequestMethod("GET")
    connection.connect()
    return connection.getResponseCode()
}

def updateIssueStatus(issue, statusCode, issueService, currentUser) {
    def siteUpStatusId = 19900
    def siteDownStatusId = 19901
    def currentStatusId = issue.status.id
    def newStatusId = statusCode == 200 ? siteUpStatusId : siteDownStatusId
    if (currentStatusId != newStatusId) {
        def issueInputParameters = issueService.newIssueInputParameters()
        issueInputParameters.setStatusId(newStatusId.toString())
        def validationResult = issueService.validateTransition(currentUser, issue.id, newStatusId, issueInputParameters)
        if (validationResult.isValid()) {
            issueService.transition(currentUser, validationResult)
            println "Issue ${issue.key} status updated to ${newStatusId}"
        } else {
            println "Validation errors for issue ${issue.key}: ${validationResult.errorCollection}"
        }
    }
}
def projectKey = "PING"
def websiteCustomFieldId = "customfield_12011"
def query = "project = ${projectKey}"
def searchResult = searchService.parseQuery(currentUser, query)
def pagerFilter = PagerFilter.getUnlimitedFilter()
SearchResults results = searchService.search(currentUser, searchResult.query, pagerFilter)
results.getResults().each { issue ->
    def websiteUrl = issue.getCustomFieldValue(ComponentAccessor.customFieldManager.getCustomFieldObject(websiteCustomFieldId))
    if (websiteUrl) {
        def statusCode = checkWebsite(websiteUrl)
        println "Website: ${websiteUrl}, Status code: ${statusCode}"
        updateIssueStatus(issue, statusCode, issueService, currentUser)
    } else {
        println "No website URL found for issue: ${issue.key}"
    }
}
return "Script executed successfully"

Suggest an answer

Log in or Sign up to answer