JENKINS-36884# Analytics-tools plugin to integrated rollbar (#374)

* JENKINS-36884# Analytics-tools plugin to integrated rollbar

Also includes infrastrucutre to inject HTML head tags and HTTP header by any plugin that implements BluePageDecorator
and appropriate jelly files.

* Doc update

* Wrapped rollbar JS code inside IIFE.

* Use rollbar-browser package and build browser bundle

* Fixes and doc update

- Stapler includei jelly tag needs escaping $
- Added missing dependency in gulpfile.js
- require should load browser-rollbar
This commit is contained in:
vivek 2016-07-28 08:50:24 -07:00 committed by GitHub
parent 3958b8aaa3
commit e181cf5a91
15 changed files with 296 additions and 1 deletions

View File

@ -39,8 +39,11 @@ Provides implementation of Pipeline apis for Jenkins pipeline and multi-branch j
## blueocean-web
Web infrastructure that glues Jenkins and Blue Ocean plugin together on the /blue endpoint.
Core Web infrastructure that bootstraps BlueOcean UI and integrates REST API core blueocean-rest.
## blueocean-analytics-tools
Plugin to inject analytics tools as HTML header in blueocean UI.
# Building and running

View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2016 CloudBees Inc and a number of other of contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,21 @@
> Analytics Tools to be injected in to BlueOcean UI
# RollBar
* Enable RollBar
RollBar is disabled by default. Use BLUEOCEAN_ROLLBAR_ENABLED JVM property to enable.
````
mvn hpi:run -DBLUEOCEAN_ROLLBAR_ENABLED=true
````
## Usage ...
try {
foo();
$blueocean_Rollbar.debug('foo() called');
} catch (e) {
$blueocean_Rollbar.error('Problem calling foo()', e);
}

View File

@ -0,0 +1,7 @@
var builder = require('@jenkins-cd/js-builder');
//
// Create the rollbar bundle.
// See https://github.com/jenkinsci/js-builder
//
builder.bundle('src/main/js/rollbar.js');

View File

@ -0,0 +1,20 @@
{
"name": "blueocean-analytics-tools",
"version": "0.0.1",
"description": "Analytics tools that gets injected in BlueOcean UI",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Vivek Pandey <vivek.pandey@gmail.com> (https://github.com/vivek)",
"license": "MIT",
"dependencies": {
"@jenkins-cd/js-modules": "0.0.5",
"rollbar-browser": "1.9.1"
},
"devDependencies": {
"@jenkins-cd/js-builder": "0.0.35",
"babel-eslint": "^6.1.2",
"gulp": "3.9.1",
"eslint-plugin-react": "^5.0.1"
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.jenkins.blueocean</groupId>
<artifactId>blueocean-parent</artifactId>
<version>1.0-alpha-5-SNAPSHOT</version>
</parent>
<artifactId>blueocean-analytics-tools</artifactId>
<packaging>hpi</packaging>
<name>BlueOcean :: Analytics Tools</name>
<url>https://wiki.jenkins-ci.org/display/JENKINS/Blue+Ocean+Plugin</url>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>blueocean-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,22 @@
package io.jenkins.blueocean.analyticstools;
import hudson.Extension;
import io.jenkins.blueocean.BluePageDecorator;
import jenkins.model.Jenkins;
/**
* @author Vivek Pandey
*/
@Extension(ordinal = 10)
public class AnalyticsTools extends BluePageDecorator {
public boolean isRollBarEnabled(){
return Boolean.getBoolean("BLUEOCEAN_ROLLBAR_ENABLED");
}
/** gives Blueocean plugin version. blueocean-web being core module is looked at to determine the version */
public String getBlueOceanPluginVersion(){
return Jenkins.getInstance().getPlugin("blueocean-web").getWrapper().getVersion();
}
}

View File

@ -0,0 +1,59 @@
function getConfigAttribute(name) {
var headElements = document.getElementsByTagName('head');
if (headElements.length === 1) {
return headElements[0].getAttribute(name);
}
return undefined;
}
function normalizeURL(location) {
var normalizedUrl = 'http://anon.blueocean.io' + location;
var rootUrl = getConfigAttribute('data-rooturl');
if (rootUrl && location.startsWith(rootUrl)) {
normalizedUrl = 'http://anon.blueocean.io' + location.substring(rootUrl.length - 1, location.length);
}
return normalizedUrl;
}
var transformer = function (payload) {
payload.data.request.user_ip = '0.0.0.0';
payload.data.request.url = normalizeURL(window.location.pathname);
};
//
// Configure rollbar ...
// See https://github.com/rollbar/rollbar.js/tree/master/examples/browserify
//
var _rollbarConfig = {
accessToken: '81f3134dedf44871b9cc0a347b1313df',
captureUncaught: true,
code_version: window.$blueocean_pluginVersion, // see header.jelly
source_map_enabled: true,
guess_uncaught_frames: true,
transform: transformer
};
var rollbarBrowser = require('rollbar-browser');
var Rollbar = rollbarBrowser.init(_rollbarConfig);
// Looking at docs (https://github.com/rollbar/rollbar.js/tree/master/examples/browserify)
// it seems like they stuff it into a global. We are trying hard not to do that
// under any circumstances, but maybe this is an exception if it's only going to be
// used in a closed/controlled env.
//
// Soooo .... lets export it to global for now, but as $blueocean_Rollbar ...
//
window.$blueocean_Rollbar = Rollbar;
//
// Usage ...
//
//try {
// foo();
// $blueocean_Rollbar.debug('foo() called');
//} catch (e) {
// $blueocean_Rollbar.error('Problem calling foo()', e);
//}

View File

@ -0,0 +1,4 @@
<?jelly escape-by-default='true'?>
<div>
BlueOcean Analytics Tools plugin
</div>

View File

@ -0,0 +1,25 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler">
<j:if test="${it.rollBarEnabled}">
<!--
Still use a small bit of JS to inject the Rollbar access token.
I think this is ok for now because we're setting a global anyway - see
comment at the end of src/main/js/rollbar.js
-->
<script>
(function () {
window.$$blueocean_pluginVersion = '${it.blueOceanPluginVersion}';
})();
</script>
<!--
Running the plugin build (or just "gulp" from the command line) will
generate a browser bundle of what's in src/main/js/rollbar.js and we
can load that using an adjunct as follows.
See gulpfile.js and see the output from running the "gulp" command.
-->
<st:adjunct includes="org.jenkins.ui.jsmodules.blueocean_analytics_tools.rollbar"/>
</j:if>
</j:jelly>

View File

@ -44,6 +44,11 @@
<artifactId>blueocean-pipeline-api-impl</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>blueocean-analytics-tools</artifactId>
</dependency>
<!-- Test deps -->
<dependency>
<groupId>${project.groupId}</groupId>
@ -107,6 +112,7 @@
linkHPI('blueocean-commons');
linkHPI('blueocean-rest-impl');
linkHPI('blueocean-pipeline-api-impl')
linkHPI('blueocean-analytics-tools')
</source>
</configuration>
</plugin>

View File

@ -2,6 +2,8 @@ package io.jenkins.blueocean;
import hudson.ExtensionList;
import java.util.List;
/**
* Root of Blue Ocean UI
*
@ -34,4 +36,8 @@ public class BlueOceanUI {
public String getUrlBase() {
return urlBase;
}
public List<BluePageDecorator> getPageDecorators(){
return BluePageDecorator.all();
}
}

View File

@ -0,0 +1,61 @@
package io.jenkins.blueocean;
import hudson.Extension;
import hudson.ExtensionList;
import hudson.ExtensionPoint;
/**
* Participates in the rendering of HTML pages for all pages of Hudson.
*
* <p>
* This class provides a few hooks to augument the HTML generation process of Hudson, across
* all the HTML pages that Hudson delivers.
*
* <p>
* For example, if you'd like to add a Google Analytics stat to Hudson, then you need to inject
* a small script fragment to all Hudson pages. This extension point provides a means to do that.
*
* <h2>Life-cycle</h2>
* <p>
* Plugins that contribute this extension point
* should implement a new decorator and put {@link Extension} on the class.
*
* <h2>Associated Views</h2>
*
*
* <h3>header.jelly</h3>
* <p>
* This page is added right before the &lt;/head&gt; tag. Convenient place for additional stylesheet, &lt;meta&gt; tags, etc.
*
* <pre>
* &lt;j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler"&gt;
* &lt;script&gt;
* //your JS code
* &lt;/script&gt;
* &lt;/j:jelly&gt;
* </pre>
*
* <h3>httpHeaders.jelly</h3>
*
* For example, this httpHeader.jelly adds HTTP X-MY-HEADER
*
* <pre>
*
* &lt;?jelly escape-by-default='true'?&gt;
* &lt;j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler"&gt;
* &lt;st:header name="X-MY-HEADER" value="${it.someValue}"/&gt;
* &lt;/j:jelly&gt;
*
* </pre>
* <p>
* This is a generalization of the X-Jenkins header that aids auto-discovery.
* This fragment can write additional &lt;st:header name="..." value="..." /&gt; tags that go along with it.
*
* @author Vivek Pandey
*/
public abstract class BluePageDecorator implements ExtensionPoint {
public static ExtensionList<BluePageDecorator> all() {
return ExtensionList.lookup(BluePageDecorator.class);
}
}

View File

@ -1,6 +1,11 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:x="jelly:xml">
<st:contentType value="text/html;charset=UTF-8"/>
<!-- Add HTTP headers from extensions. See BluePageDecorator.java -->
<j:forEach var="pd" items="${it.pageDecorators}">
<st:include it="${pd}" page="httpHeaders.jelly" optional="true"/>
</j:forEach>
<x:doctype name="html"/>
<html>
@ -29,6 +34,11 @@
<link rel="stylesheet"
href="${resURL}/plugin/blueocean-web/assets/css/jenkins-design-language.css"
type="text/css"/>
<!-- Inject headers from other extensions. See BluePageDecorator.java -->
<j:forEach var="pd" items="${it.pageDecorators}">
<st:include it="${pd}" page="header.jelly" optional="true" />
</j:forEach>
</head>
<body>

View File

@ -105,6 +105,7 @@
<module>blueocean-dashboard</module>
<module>blueocean-personalization</module>
<module>blueocean-plugin</module>
<module>blueocean-analytics-tools</module>
</modules>
<repositories>
@ -172,6 +173,12 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>blueocean-analytics-tools</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>blueocean-plugin</artifactId>