How do I analyse a HAR file for Blue Ocean?

Article ID:115000088492
4 minute readKnowledge base

Issue

  • When analyse errors in Blue Ocean one important part is the HAR file that the customer can provide. This file is so important since it will show the communication between the front end and the REST API (including the REST response)

  • Another important part to truly debug Blue Ocean is the console OUTPUT from the customer after activating Blue Ocean logging on the client site.

Environment

  • CloudBees Jenkins Enterprise

  • Jenkins

  • Jenkins LTS

Resolution

We assume you are familiar with generating a HAR file, if not have a look at Generating a HAR file for troubleshooting

Having created the HAR you can then import it in e.g "HTTP Archive Viewer".

Step by step

First import the HAR file.

import import

Then you can review the different resources that had been requested.

import

Finding problems

Normally the first thing is to determine what the exact problem is. For this, you first look in the HAR file and look for responses that have status code >400. Those statuses indicate problems with the backend and require further investigating in the backend. In case there are no such errors, you would need to debug the response in more detail.

Debug problems

Depending on the problem you see you will need to look in the different rest answer. For example if you are debugging the detail view of a pipeline, you most likely want to look for https://example.com:8080/jenkins/blue/rest/organizations/jenkins/pipelines/${pipelineName}/branches/${branchName}/runs/${id}/nodes/ to examine the different nodes of the run.

You can now use the response data and create a new "ide-scripting" console script. Since the response of the server has to be a valid json object you can simply create a variable like the following:

const nodes = [{ "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl", "_links": { "self": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/5/" }, "actions": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/5/actions/" }, "steps": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/5/steps/" } }, "actions": [], "displayName": "hey", "durationInMillis": 7559, "id": "5", "input": null, "result": "SUCCESS", "startTime": "2017-03-24T20:48:21.435+0100", "state": "FINISHED", "causeOfBlockage": null, "edges": [{"_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl$EdgeImpl", "id": "7"}] }, { "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl", "_links": { "self": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/7/" }, "actions": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/7/actions/" }, "steps": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/7/steps/" } }, "actions": [], "displayName": "parallel", "durationInMillis": 17974, "id": "7", "input": null, "result": "SUCCESS", "startTime": "2017-03-24T20:48:29.006+0100", "state": "FINISHED", "causeOfBlockage": null, "edges": [{ "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl$EdgeImpl", "id": "10" }, {"_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl$EdgeImpl", "id": "11"}] }, { "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl", "_links": { "self": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/10/" }, "actions": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/10/actions/" }, "steps": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/10/steps/" } }, "actions": [], "displayName": "firstBranch", "durationInMillis": 17973, "id": "10", "input": null, "result": "SUCCESS", "startTime": "2017-03-24T20:48:29.007+0100", "state": "FINISHED", "causeOfBlockage": null, "edges": [{"_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl$EdgeImpl", "id": "21"}] }, { "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl", "_links": { "self": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/11/" }, "actions": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/11/actions/" }, "steps": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/11/steps/" } }, "actions": [], "displayName": "secondBranch", "durationInMillis": 17972, "id": "11", "input": null, "result": "SUCCESS", "startTime": "2017-03-24T20:48:29.008+0100", "state": "FINISHED", "causeOfBlockage": null, "edges": [{"_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl$EdgeImpl", "id": "21"}] }, { "_class": "io.jenkins.Blue Ocean.rest.impl.pipeline.PipelineNodeImpl", "_links": { "self": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/21/" }, "actions": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/21/actions/" }, "steps": { "_class": "io.jenkins.Blue Ocean.rest.hal.Link", "href": "/blue/rest/organizations/jenkins/pipelines/scherler/branches/karaoke-parallel/runs/59/nodes/21/steps/" } }, "actions": [], "displayName": "ho", "durationInMillis": 9413, "id": "21", "input": null, "result": "SUCCESS", "startTime": "2017-03-24T20:48:46.993+0100", "state": "FINISHED", "causeOfBlockage": null, "edges": [] }];

You may have to "clean" the response since it may be formatted as JSON Object. I am using the regexp "\s\n\s" to remove all unneeded line breaks and whitespace characters, so I get one big line. You can use your IDE to format the code again.

In case you want to reduce the information of the nodes to their id and their edges, you can do the following:

const cleaned = nodes.map((item) => {return {id: item.id, edges: item.edges}}); console.log(cleaned); // outputs
[ { id: '5', edges: [ [Object] ] }, { id: '7', edges: [ [Object], [Object] ] }, { id: '10', edges: [ [Object] ] }, { id: '11', edges: [ [Object] ] }, { id: '21', edges: [] } ]

Or if you want to filter the above for a certain state and a specific id you can do e.g.

const cleaned = nodes .filter((item) => item.state === "FINISHED" && item.id==="21") .map((item) => {return {id: item.id, edges: item.edges}}) ;
[ { id: '21', edges: [] } ]

You get the idea to validate/debug the data via scripting, however this is only really useful if you exactly know what you are looking for.

To find out Blue Ocean offers some useful tools for power user which can help to find out what is going wrong/on.

Console debugging

You may have noticed that when you open the console in chrome that there is a teaser message like Browser configuration of @jenkins-cd/logging is explained at https://tfennelly.github.io/jenkins-js-logging/index.html#browser-config we highly recommend that link as reference on how you can further debug the app. With the logging Blue Ocean added some basic information that can help to track down the problem.

You can either use the Chrome Extension plugin or directly the localStorage to change the log levels.

import

After you refresh you will see much more information in the console.

import

Preferences for debugging

Blue Ocean will (not yet merged to master) support setting of preferences in the localStorage of the browser. We are applying the same principals as we did with logging earlier. The user can configure different parts of the applications by setting preferences.

import

Especially the runDetails.pipeline.updateOnFinish preference should come in handy if set to never. This will allow to stop "karaoke mode" (following a live build) and prevent that the run will be refreshed. Which then allows to analyse the state on which it was stopped much easier.