PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/org/jenkins/plugins/statistics/gatherer/listeners/RunStatsListener.java

https://gitlab.com/vectorci/statistics-gatherer-plugin
Java | 286 lines | 228 code | 19 blank | 39 comment | 59 complexity | 4ac2661187b381ee102931bd788c76ea MD5 | raw file
  1. package org.jenkins.plugins.statistics.gatherer.listeners;
  2. import hudson.EnvVars;
  3. import hudson.Extension;
  4. import hudson.Launcher;
  5. import hudson.PluginWrapper;
  6. import hudson.model.*;
  7. import hudson.model.listeners.RunListener;
  8. import hudson.triggers.SCMTrigger;
  9. import hudson.triggers.TimerTrigger;
  10. import jenkins.model.Jenkins;
  11. import org.jenkins.plugins.statistics.gatherer.model.build.BuildStats;
  12. import org.jenkins.plugins.statistics.gatherer.model.build.SCMInfo;
  13. import org.jenkins.plugins.statistics.gatherer.model.build.SlaveInfo;
  14. import org.jenkins.plugins.statistics.gatherer.model.scm.ScmCheckoutInfo;
  15. import org.jenkins.plugins.statistics.gatherer.util.*;
  16. import org.json.JSONArray;
  17. import org.json.JSONObject;
  18. import java.io.IOException;
  19. import java.util.*;
  20. import java.util.logging.Level;
  21. import java.util.logging.Logger;
  22. /**
  23. * Listener used for storing the Build information to the DB.
  24. *
  25. * @author hthakkallapally
  26. */
  27. @Extension
  28. public class RunStatsListener extends RunListener<Run<?, ?>> {
  29. private static final Logger LOGGER = Logger.getLogger(RunStatsListener.class.getName());
  30. private static final String BUILD_FAILURE_URL_TO_APPEND = "/api/json?depth=2&tree=actions[foundFailureCauses[categories,description,id,name]]";
  31. public RunStatsListener() {
  32. //Necessary for jenkins
  33. }
  34. public RunStatsListener(Class<Run<?, ?>> targetType) {
  35. super(targetType);
  36. }
  37. @Override
  38. public void onStarted(Run<?, ?> run, TaskListener listener) {
  39. if (PropertyLoader.getBuildInfo()) {
  40. try {
  41. if (!(run instanceof AbstractBuild)) {
  42. return;
  43. }
  44. final String buildResult = run.getResult() == null ?
  45. "INPROGRESS" : run.getResult().toString();
  46. BuildStats build = new BuildStats();
  47. build.setContextId(run.getExecutor().getCurrentWorkUnit().context.hashCode());
  48. build.setStartTime(run.getTimestamp().getTime());
  49. build.setCiUrl(Jenkins.getInstance().getRootUrl());
  50. build.setJobName(run.getParent().getName());
  51. build.setFullJobName(run.getParent().getFullName());
  52. build.setNumber(run.getNumber());
  53. build.setResult(buildResult);
  54. build.setBuildUrl(run.getUrl());
  55. build.setQueueTime(run.getExecutor() != null ?
  56. run.getExecutor().getTimeSpentInQueue() : 0);
  57. build.setBuildCause(run.getCauses().get(0).getShortDescription());
  58. addUserDetails(run, build);
  59. addSCMInfo(run, listener, build);
  60. addParameters(run, build);
  61. addSlaveInfo(run, build, listener);
  62. RestClientUtil.postToService(getRestUrl(), build);
  63. LOGGER.log(Level.INFO, "Started build and its status is : " + buildResult +
  64. " and start time is : " + run.getTimestamp().getTime());
  65. } catch (Exception e) {
  66. LOGGER.log(Level.WARNING, "Failed to call API " + getRestUrl() +
  67. " for build " + run.getDisplayName(), e);
  68. }
  69. }
  70. }
  71. /**
  72. * Construct REST URL for build resource.
  73. *
  74. * @return API end point url.
  75. */
  76. private String getRestUrl() {
  77. return PropertyLoader.getBuildEndPoint();
  78. }
  79. /**
  80. * Add the slave info to build model.
  81. *
  82. * @param run
  83. * @param build
  84. */
  85. private void addSlaveInfo(Run<?, ?> run, BuildStats build, TaskListener listener) throws InterruptedException {
  86. SlaveInfo slaveInfo = new SlaveInfo();
  87. EnvVars environment = getEnvVars(run, listener);
  88. if (environment != null) {
  89. if (environment.get("NODE_NAME") != null) {
  90. slaveInfo.setSlaveName(environment.get("NODE_NAME"));
  91. }
  92. if (environment.get("NODE_LABELS") != null) {
  93. slaveInfo.setLabel(environment.get("NODE_LABELS"));
  94. }
  95. if (environment.get("EXECUTOR_NUMBER") != null) {
  96. slaveInfo.setExecutor(environment.get("EXECUTOR_NUMBER"));
  97. }
  98. }
  99. build.setSlaveInfo(slaveInfo);
  100. }
  101. private EnvVars getEnvVars(Run<?, ?> run, TaskListener listener) throws InterruptedException {
  102. EnvVars environment = null;
  103. try {
  104. environment = run.getEnvironment(listener);
  105. } catch (IOException e) {
  106. LOGGER.log(Level.WARNING, "Failed to retrieve environment" +
  107. " for " + run.getUrl(), e);
  108. } catch (InterruptedException e) {
  109. LOGGER.log(Level.WARNING, "Failed to retrieve environment" +
  110. " for " + run.getUrl(), e);
  111. throw e;
  112. }
  113. return environment;
  114. }
  115. /**
  116. * Get all the parameters used in the build.
  117. *
  118. * @param run
  119. * @param build
  120. */
  121. private void addParameters(Run<?, ?> run, BuildStats build) {
  122. ParametersAction paramsAction = run.getAction(ParametersAction.class);
  123. if (paramsAction != null) {
  124. EnvVars env = new EnvVars();
  125. for (ParameterValue value : paramsAction.getParameters()) {
  126. if (!value.isSensitive()) {
  127. value.buildEnvironment(run, env);
  128. }
  129. }
  130. build.setParameters(env);
  131. }
  132. }
  133. /**
  134. * Get the SCM info from the build and add it to model.
  135. *
  136. * @param run
  137. * @param listener
  138. * @param build
  139. */
  140. private void addSCMInfo(Run<?, ?> run, TaskListener listener,
  141. BuildStats build) throws InterruptedException {
  142. EnvVars environment = getEnvVars(run, listener);
  143. SCMInfo scmInfo = new SCMInfo();
  144. if (environment != null) {
  145. if (environment.get("GIT_URL") != null) {
  146. scmInfo.setUrl(environment.get("GIT_URL"));
  147. } else if (environment.get("SVN_URL") != null) {
  148. scmInfo.setUrl(environment.get("SVN_URL"));
  149. }
  150. if (environment.get("GIT_BRANCH") != null) {
  151. scmInfo.setBranch(environment.get("GIT_BRANCH"));
  152. } else if (environment.get("Branch") != null) {
  153. scmInfo.setBranch(environment.get("Branch"));
  154. }
  155. if (environment.get("GIT_COMMIT") != null) {
  156. scmInfo.setCommit(environment.get("GIT_COMMIT"));
  157. } else if (environment.get("SVN_REVISION") != null) {
  158. scmInfo.setCommit(environment.get("SVN_REVISION"));
  159. }
  160. }
  161. build.setScmInfo(scmInfo);
  162. }
  163. /**
  164. * Add user name and user id details to build model.
  165. *
  166. * @param run
  167. * @param build
  168. */
  169. private void addUserDetails(Run<?, ?> run, BuildStats build) {
  170. List<Cause> causes = run.getCauses();
  171. for (Cause cause : causes) {
  172. if (cause instanceof Cause.UserIdCause) {
  173. String userId = ((Cause.UserIdCause) cause).getUserId();
  174. userId = (userId == null || userId.isEmpty()) ? Constants.ANONYMOUS : userId;
  175. build.setStartedUserId(userId);
  176. String userName = ((Cause.UserIdCause) cause).getUserName();
  177. userName = (userName == null || userName.isEmpty()) ?
  178. Constants.ANONYMOUS : userName;
  179. build.setStartedUserName(userName);
  180. } else if (cause instanceof Cause.UpstreamCause) {
  181. build.setStartedUserId(JenkinsCauses.UPSTREAM);
  182. build.setStartedUserName(Constants.SYSTEM);
  183. } else if (cause instanceof SCMTrigger.SCMTriggerCause) {
  184. build.setStartedUserId(JenkinsCauses.SCM);
  185. build.setStartedUserName(Constants.SYSTEM);
  186. } else if (cause instanceof TimerTrigger.TimerTriggerCause) {
  187. build.setStartedUserId(JenkinsCauses.TIMER);
  188. build.setStartedUserName(Constants.SYSTEM);
  189. } else {
  190. build.setStartedUserId(Constants.UNKNOWN);
  191. build.setStartedUserName(Constants.SYSTEM);
  192. }
  193. }
  194. }
  195. @Override
  196. /**
  197. * Update the build status and duration.
  198. */
  199. public void onFinalized(final Run<?, ?> run) {
  200. if (PropertyLoader.getBuildInfo()) {
  201. try {
  202. if (!(run instanceof AbstractBuild)) {
  203. return;
  204. }
  205. final String buildResult = run.getResult() == null ?
  206. Constants.UNKNOWN : run.getResult().toString();
  207. BuildStats build = new BuildStats();
  208. build.setCiUrl(Jenkins.getInstance().getRootUrl());
  209. build.setJobName(run.getParent().getName());
  210. build.setFullJobName(run.getParent().getFullName());
  211. build.setNumber(run.getNumber());
  212. build.setResult(buildResult);
  213. build.setBuildUrl(run.getUrl());
  214. build.setDuration(run.getDuration());
  215. build.setEndTime(Calendar.getInstance().getTime());
  216. addBuildFailureCauses(build);
  217. RestClientUtil.postToService(getRestUrl(), build);
  218. LOGGER.log(Level.INFO, run.getParent().getName() + " build is completed " +
  219. "its status is : " + buildResult +
  220. " at time : " + new Date());
  221. } catch (Exception e) {
  222. LOGGER.log(Level.WARNING, "Failed to call API " + getRestUrl() +
  223. " for build " + run.getDisplayName(), e);
  224. }
  225. }
  226. }
  227. private void addBuildFailureCauses(BuildStats build) {
  228. List<PluginWrapper> plugins = Jenkins.getInstance().getPluginManager().getPlugins();
  229. for (PluginWrapper plugin : plugins) {
  230. if (plugin.getDisplayName().contains("Build Failure Analyzer")) {
  231. JSONObject response = RestClientUtil.getJson(build.getCiUrl() + build.getBuildUrl() + BUILD_FAILURE_URL_TO_APPEND);
  232. if (response != null && response.getJSONArray("actions") != null) {
  233. JSONArray actions = response.getJSONArray("actions");
  234. for (int i = 0; i < actions.length(); i++) {
  235. JSONObject failureResponse = actions.getJSONObject(i);
  236. if (!failureResponse.keySet().isEmpty()) {
  237. List<Map> failureCauses = new ArrayList<>();
  238. for (int j = 0; j < failureResponse.getJSONArray("foundFailureCauses").length(); j++) {
  239. JSONArray foundFailureCauses = failureResponse.getJSONArray("foundFailureCauses");
  240. Map jsonObject = JSONUtil.convertBuildFailureToMap(foundFailureCauses.getJSONObject(j));
  241. failureCauses.add(jsonObject);
  242. }
  243. build.setBuildFailureCauses(failureCauses);
  244. }
  245. }
  246. break;
  247. }
  248. }
  249. }
  250. }
  251. @Override
  252. public Environment setUpEnvironment(AbstractBuild build,
  253. Launcher launcher,
  254. BuildListener listener) throws IOException, InterruptedException {
  255. if (PropertyLoader.getScmCheckoutInfo()) {
  256. ScmCheckoutInfo scmCheckoutInfo = new ScmCheckoutInfo();
  257. scmCheckoutInfo.setStartTime(Calendar.getInstance().getTime());
  258. scmCheckoutInfo.setBuildUrl(build.getUrl());
  259. scmCheckoutInfo.setEndTime(new Date(0));
  260. RestClientUtil.postToService(getScmCheckoutUrl(), scmCheckoutInfo);
  261. }
  262. return super.setUpEnvironment(build, launcher, listener);
  263. }
  264. private String getScmCheckoutUrl() {
  265. return PropertyLoader.getScmCheckoutEndPoint();
  266. }
  267. }