Git Product home page Git Product logo

jenkins-datadog-plugin's Introduction

IMPORTANT

This repository is now archived.
Official repository is now located at https://github.com/jenkinsci/datadog-plugin.
This repository will not be deleted in order to keep track of historical changes, issues and pull requests.

  • Note that the changelog file references issues from this repository.

Build Status

Jenkins Datadog Plugin

A Jenkins plugin used to forward metrics, events, and service checks to an account at Datadog, automatically.

There is a Jenkins CI Plugin page for this plugin, but it refers to our DataDog/jenkins-datadog-plugin documentation.

Features

Currently, the plugin is tracking the following data.

Events

Default Events Type

  • Build Started
    • Triggered on RunListener#onStarted
    • Default tags: job, node, branch
    • Associated rate metric: jenkins.job.started
  • Build Aborted
    • Triggered on RunListener#onDeleted
    • Default tags: job, node, branch
    • Associated rate metric: jenkins.job.aborted
  • Build Completed
    • Triggered on RunListener#onCompleted
    • Default tags: job, node, branch, result (Git Branch, SVN revision or CVS branch)
    • Associated rate metric: jenkins.job.completed

Source Control Management Events Type

  • SCM Checkout
    • Triggered on SCMListener#onCheckout
    • Default tags: job, node, branch
    • Associated rate metric: jenkins.scm.checkout

Systems Events Type

  • Computer Online
    • Triggered on ComputerListener#onOnline
    • Associated rate metric: jenkins.computer.online
  • Computer Offline
    • Triggered on ComputerListener#onOffline
    • Associated rate metric: jenkins.computer.online
  • Computer TemporarilyOnline
    • Triggered on ComputerListener#onTemporarilyOnline
    • Associated rate metric: jenkins.computer.temporarily_online
  • Computer TemporarilyOffline
    • Triggered on ComputerListener#onTemporarilyOffline
    • Associated rate metric: jenkins.computer.temporarily_offline
  • Computer LaunchFailure
    • Triggered on ComputerListener#onLaunchFailure
    • Associated rate metric: jenkins.computer.launch_failure
  • Item Created
    • Triggered on ItemListener#onCreated
    • Associated rate metric: jenkins.item.created
  • Item Deleted
    • Triggered on ItemListener#onDeleted
    • Associated rate metric: jenkins.item.deleted
  • Item Updated
    • Triggered on ItemListener#onUpdated
    • Default tags:
    • Associated rate metric: jenkins.item.updated
  • Item Copied
    • Triggered on ItemListener#onCopied
    • Associated rate metric: jenkins.item.copied
  • ItemListener LocationChanged
    • Triggered on ItemListener#onLocationChanged
    • Associated rate metric: jenkins.item.location_changed
  • Config Changed
    • Triggered on SaveableListener#onChange
    • Associated rate metric: jenkins.config.changed

Security Events Type

  • User Authenticated
    • Triggered on SecurityListener#authenticated
    • Default tags:
    • Associated rate metric: jenkins.user.authenticated
  • User failed To Authenticate
    • Triggered on SecurityListener#failedToAuthenticate
    • Associated rate metric: jenkins.user.access_denied
  • User loggedOut
    • Triggered on SecurityListener#loggedOut
    • Associated rate metric: jenkins.user.logout

Metrics

Metric Name Description Default Tags
jenkins.computer.launch_failure Rate of computer launch failures.
jenkins.computer.offline Rate of computer going offline.
jenkins.computer.online Rate of computer going online.
jenkins.computer.temporarily_offline Rate of computer going temporarily offline.
jenkins.computer.temporarily_online Rate of computer going temporarily online.
jenkins.config.changed Rate of configs being changed.
jenkins.executor.count Executor count. node_hostname, node_name, node_label
jenkins.executor.free Number of unused executor. node_hostname, node_name, node_label
jenkins.executor.in_use Number of idle executor. node_hostname, node_name, node_label
jenkins.item.copied Rate of items being copied.
jenkins.item.created Rate of items being created.
jenkins.item.deleted Rate of items being deleted.
jenkins.item.location_changed Rate of items being moved.
jenkins.item.updated Rate of items being updated.
jenkins.job.aborted Rate of aborted jobs. branch, job, node
jenkins.job.completed Rate of completed jobs. branch, job, node, result
jenkins.job.cycletime Build Cycle Time. branch, job, node, result
jenkins.job.duration Build duration (in seconds). branch, job, node, result
jenkins.job.feedbacktime Feedback time from code commit to job failure. branch, job, node, result
jenkins.job.leadtime Build Lead Time. branch, job, node, result
jenkins.job.mtbf MTBF, time between last successful job and current failed job. branch, job, node, result
jenkins.job.mttr MTTR: time between last failed job and current successful job. branch, job, node, result
jenkins.job.started Rate of started jobs. branch, job, node
jenkins.job.waiting Time spent waiting for job to run (in milliseconds). branch, job, node
jenkins.node.count Total number of node.
jenkins.node.offline Offline nodes count.
jenkins.node.online Online nodes count.
jenkins.plugin.count Plugins count.
jenkins.project.count Project count.
jenkins.queue.size Queue Size.
jenkins.queue.buildable Number of Buildable item in Queue.
jenkins.queue.pending Number of Pending item in Queue.
jenkins.queue.stuck Number of Stuck item in Queue.
jenkins.queue.blocked Number of Blocked item in Queue.
jenkins.scm.checkout Rate of SCM checkouts. branch, job, node
jenkins.user.access_denied Rate of users failing to authenticate.
jenkins.user.authenticated Rate of users authenticating.
jenkins.user.logout Rate of users logging out.

Service checks

  • Build status jenkins.job.status
    • Default tags: : job, node, branch, result (Git Branch, SVN revision or CVS branch)
      • NOTE: Git Branch available when using the Git Plugin

Customization

From the global configuration page, at Manage Jenkins -> Configure System.

  • Blacklisted Jobs
    • A comma-separated list of regex to match job names that should not be monitored. (eg: susans-job,johns-.*,prod_folder/prod_release).
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_BLACKLIST.
  • Whitelisted Jobs
    • A comma-separated list of regex to match job names that should be monitored. (eg: susans-job,johns-.*,prod_folder/prod_release).
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_WHITELIST.
  • Global Tag File
    • Path to the workspace file containing a comma separated list of tags (not compatible with Pipeline jobs).
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_GLOBAL_TAG_FILE.
  • Global Tags
    • A comma-separated list of tags to apply to all metrics, events, service checks.
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_GLOBAL_TAGS.
  • Global Job Tags
    • A regex to match a job, and a list of tags to apply to that job, all separated by a comma.
      • tags can reference match groups in the regex using the $ symbol
      • eg: (.*?)_job_(*?)_release, owner:$1, release_env:$2, optional:Tag3
      • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_GLOBAL_JOB_TAGS.
  • Send Security audit events
    • Enabled by default, it submits Security Events Type of events and metrics.
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_EMIT_SECURITY_EVENTS.
  • Send System events
    • Enabled by default, it submits System Events Type of events and metrics
    • This property can be set using the following environment variable: DATADOG_JENKINS_PLUGIN_EMIT_SYSTEM_EVENTS.

From a job specific configuration page

  • Custom tags
    • From a File in the job workspace (not compatible with Pipeline jobs). If set, it will override the Global Job Tags configuration.
    • As text Properties directly from the configuration page.
  • Send Source Control Management events
    • Enabled by default, it submits Source Control Management Events Type of events and metrics.

Installation

This plugin requires Jenkins 1.580.1 or newer.

This plugin can be installed from the Update Center (found at Manage Jenkins -> Manage Plugins) in your Jenkins installation. Select the Available tab, search for Datadog and look for Datadog Plugin. Once you find it, check the checkbox next to it, and install via your preference by using one of the two install buttons at the bottom of the screen. Check to see that the plugin has been successfully installed by searching for Datadog Plugin on the Installed tab. If the plugin has been successfully installed, then continue on to the configuration step, described below.

Note: If you do not see the version of Datadog Plugin that you are expecting, make sure you have run Check Now from the Manage Jenkins -> Manage Plugins screen.

Configuration

Configure with the plugin user interface

To configure your newly installed Datadog Plugin, navigate to the Manage Jenkins -> Configure System page on your Jenkins installation. Once there, scroll down to find the Datadog Plugin section.

You can use two ways to configure your plugin to submit data to Datadog.

  • By using a Datadog API Key.
    • Click the "Use Datadog API URL and Key to report to Datadog" radio button (selected by default)
    • Find your API Key from the API Keys page on your Datadog account, and copy/paste it into the API Key textbox on the Jenkins configuration screen.
    • You can test that your API Key works by pressing the Test Key button, on the Jenkins configuration screen, directly below the API Key textbox.
  • By using a DogStatsD server.
    • Click the "Use a DogStatsD Server to report to Datadog" radio button.
    • Specify both your DogStatD server hostname and port

Once your configuration changes are finished, save them, and you're good to go!

Configure with a Groovy script

Configure your Datadog plugin using a Groovy script like this one

import jenkins.model.*
import org.datadog.jenkins.plugins.datadog.DatadogGlobalConfiguration

def j = Jenkins.getInstance()
def d = j.getDescriptor("org.datadog.jenkins.plugins.datadog.DatadogGlobalConfiguration")

// If you want to use Datadog API URL and Key to report to Datadog
d.setReportWith('HTTP')
d.setTargetApiURL('https://your-jenkins.com:8080')
d.setTargetApiKey('XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')

// If you want to use a DogStatsD Server to report to Datadog
// d.setReportWith('DSD')
// d.setTargetHost('localhost')
// d.setTargetPort(8125)

// Other configs
d.setBlacklist('job1,job2')
// Save config
d.save()

Configuring the plugin this way might be useful if you're running your Jenkins Master in a Docker container using the Official Jenkins Docker Image or any derivative that supports plugins.txt and Groovy init scripts.

Configure with an environment variables

Configure your Datadog plugin using environment variables by specifying the three variables below:.

  • DATADOG_JENKINS_PLUGIN_REPORT_WITH which specifies which report mechanism you want to use. When set to DSD it will use a DogStatsD Server to report to Datadog. Otherwise set it to the default HTTP value.

If you set DATADOG_JENKINS_PLUGIN_REPORT_WITH with the DSD value, you must specify the following environment variables:

  • DATADOG_JENKINS_PLUGIN_TARGET_HOST which specifies the DogStatsD Server host to report to. Default value is localhost.
  • DATADOG_JENKINS_PLUGIN_TARGET_PORT which specifies the DogStatsD Server port to report to. Default value is 8125.

If you set DATADOG_JENKINS_PLUGIN_REPORT_WITH with the HTTP value or don't specify it, you must specify the following environment variables:

  • DATADOG_JENKINS_PLUGIN_TARGET_API_URL which specifies the Datadog API Endpoint to report to. Default value is https://api.datadoghq.com/api/.
  • DATADOG_JENKINS_PLUGIN_TARGET_API_KEY which specifies your Datadog API key in order to report to your Datadog account.

Logging

Logging is done by utilizing the java.util.Logger, which follows the best logging practices for Jenkins. In order to obtain logs, follow the directions listed here. When adding a Logger, all Datadog plugin functions start with org.datadog.jenkins.plugins.datadog. and the function name you're after should autopopulate. As of this writing, the only function available was org.datadog.jenkins.plugins.datadog.listeners.DatadogBuildListener.

Release Process

Overview

Our DataDog/jenkins-datadog-plugin repository handles the most up-to-date changes we've made to the Datadog Plugin, as well as issue tickets revolving around that work. Releases are merged to the Jenkins-CI git repo for our plugin, and represents the source used for plugin releases found in the Update Center in your Jenkins installation.

Every commit to our DataDog/jenkins-datadog-plugin repository triggers a Jenkins build on our internal Jenkins installation.

A list of our releases is here.

How to Release

To release a new plugin version, change the project version in the pom.xml from x.x.x-SNAPSHOT to the updated version number you'd like to see. Add an entry for the new release number to CHANGELOG.md, and ensure that all the changes are listed accurately. Then run the jenkins-datadog-plugin-release job in our Jenkins installation. If the job completes successfully, then the newly updated plugin should be available from the Jenkins Update Center within ~4 hours (plus mirror propogation time).

Issue Tracking

We use Github's built in issue tracking system for all issues tickets relating to this plugin, found here. However, given how Jenkins Plugins are hosted, there may be issues that are posted to JIRA as well. You can check here for those issue postings.

Here are unresolved issues on JIRA mentioning Datadog.

Changes

See the CHANGELOG.md

How to contribute code

First of all and most importantly, thank you for sharing.

If you want to submit code, please fork this repository and submit pull requests against the master branch. For more information, checkout the contributing guidelines for our agent. We'll attempt to follow these here, as well, where it makes sense.

Check out the development document for tips on spinning up a quick development environment locally.

Manual Testing

In order to keep track of some testing procedures for ensuring proper functionality of the Datadog Plugin on Jenkins, there is a testing document.

jenkins-datadog-plugin's People

Contributors

alanranciato avatar bbeck avatar cmatteri avatar doy-stripe avatar gzussa avatar jameshsiaoacquia avatar jniesen avatar johnlzeller avatar lattwood avatar madsnielsen avatar mbaitelman avatar nikola-da avatar nmuesch avatar ofek avatar olivielpeau avatar pgarbe avatar remh avatar rgoomar avatar sjenriquez avatar truthbk avatar ulich avatar witokondoria avatar zippolyte avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jenkins-datadog-plugin's Issues

Metrics reporting is broken for Pipeline Jobs

Hello,

It seems that for jenkins2.x piepline jobs and multibranch piepline jobs (including github organisation) only job started event is reported. The job.juration and job.completed metrics are not reported at all.

Is there a possible fix to these issues as they both have the effect of rendering jenkins integration quite irrelevant, since there's no metric to report?

Thanks in advance.

Add project name as a tag

As discussed in #38 it would be useful to have a the project tag name to be able to group jobs belonging to the same jenkins project and therefore create more meaningful alerts.

I'll try to work on a patch

Allow ability to constrain jobs that are tracked

Allow the ability to somehow constrain the set of jobs we track. This could be a whitelist, or a blacklist. My gut says that default should be all, and we should allow a blacklist of jobs not to be tracked.

Use DataDog Application Key instead of just the API Key

Currently it is not possible to isolate data from Jenkins to a Jenkins application key in DataDog, creating a lot of noise for other applications being monitored in DataDog. It would be useful to configure and use the application key to isolate this traffic.

Empty whitelist does not permit all jobs

Plugin 0.6.1
Jenkins 2.60.3

Upon upgrading to 0.6.1 we found all metrics apart from jenkins.queue.size missing from DataDog. To enable metrics again we had to specify all job names in the whitelist. This should not be the case according to the docs.

Thanks

Merge dd-agent's tags into the emitted metrics

I'll start by describing what I want to accomplish first, then suggested fix.

We have two Jenkins clusters, one for QA and one for Prod, and want to separate alerts out based on this environment. The /etc/dd-agent/datadog.conf has this, and is managed through our automation.

The Jenkins plugin, however, does not try to integrate those configured tags. Events emitted by the Jenkins plugin have a fixed set of tags. The old Jenkins integration that parsed build.xml went through the local collector and didn't have this limitation.

Is it feasible to pull the tags from the local agent (if available) and merge those in? Either by checking for the file on disk, parsing and extracting tags: or an action against the agent API?

We're happy to contribute patches to resolve this issue with some guidance.

Thanks!

Enable reduce log level of datadog plugin

Currently, Datadog logs a lot of information before and after the job starts, prefixed with DatadogBuildListener.java:.

Would be nice to be able to reduce or suppress that logging using an option in the plugin.

Pull API key from credential store

This is a 'nice to have' feature, but I would like to be able to use the Credentials Plugin to pull my datadog API key from.

In Manage Jenkins -> Configure System -> Datadog -> API Key I would like to see either a form field, or a drop down to use a stored credential.

jenkins.job.duration is no longer emitted

We upgraded from 0.4.1 to 0.5.2, and we no longer seem to be getting jenkins.job.duration metrics at all. I looked through the changes, but can't seem to see anything that would have obviously caused this. Is there anything I can do to look into this?

Jenkins 2.89.4 - 0.6.2 plugin - WARNING: RunListener failed

I am getting runlistener failed events by the masses and I'm using spot instances.

Mar 05, 2018 5:29:41 PM hudson.model.listeners.RunListener report
WARNING: RunListener failed
java.lang.NullPointerException
at org.datadog.jenkins.plugins.datadog.DatadogBuildListener.onStarted(DatadogBuildListener.java:113)
at hudson.model.listeners.RunListener.fireStarted(RunListener.java:240)
at hudson.maven.MavenBuild$ProxyImpl2.start(MavenBuild.java:609)
at sun.reflect.GeneratedMethodAccessor161.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at hudson.model.Executor$2.call(Executor.java:911)
at hudson.util.InterceptingProxy$1.invoke(InterceptingProxy.java:23)
at com.sun.proxy.$Proxy97.start(Unknown Source)
at sun.reflect.GeneratedMethodAccessor161.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at hudson.remoting.RemoteInvocationHandler$RPCRequest.perform(RemoteInvocationHandler.java:922)
at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:896)
at hudson.remoting.RemoteInvocationHandler$RPCRequest.call(RemoteInvocationHandler.java:853)
at hudson.remoting.UserRequest.perform(UserRequest.java:207)
at hudson.remoting.UserRequest.perform(UserRequest.java:53)
at hudson.remoting.Request$2.run(Request.java:358)
at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:72)
at org.jenkinsci.remoting.CallableDecorator.call(CallableDecorator.java:19)
at hudson.remoting.CallableDecoratorList$1.call(CallableDecoratorList.java:21)
at jenkins.util.ContextResettingExecutorService$2.call(ContextResettingExecutorService.java:46)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

I'm using the latest datadog plugin and no luck. What other information can I provide to help fix this? This pretty much dominates my logs at this point.

thanks

Handle jobs within folders properly (such as Multibranch Workflow)

One of the features that's really starting to be used often is the Workflow plugin, a part of that functionality is "Multibranch" (explained here) which creates a "Folder" with jobs in it for each branch which contains a Jenkinsfile (example of such a job here).

When the plugin reports job statistics it is only reporting the job name, which means that all "Workflow Multibranch" or any other jobs within Folders which share the same name will be largely indistinguishable inside of the Datadog UI.

master-event

This is particularly problematic if one wants to set up a monitor based on a specific job failing :(

Add master statistics

Mike would like statistics from the master Manage Jenkins -> Monitoring of Jenkins master

Config panel populating API key incorrectly

Currently, the config panel is populating a previously entered API key incorrectly. This is because it's showing the redacted hash of the users API key, rather than the redacted API key. By-products of this include if a user presses 'Test Key' after they have already saved a key, it will fail, because the hash itself, is not a valid API key. This could present problems if one were to save the hash, which would be incorrect. This isn't a security problem, just incorrect.

Last release broke "passing/failing Jenkins jobs" in Jenkins dashboard

Hi,

It seems the "results" tag is not anymore passed with jenkins.job.status because of a recent commit.
As a result we can't anymore count easily the number of failed and successful jobs and the two related widgets default dashboard jenkins don't work anymore.

Is it possible to add back the result tag or to have the appropriate metric to extract this information ?

Thanks in advance.

Yann

Add ability to customize build tags from groovy pipelines

I need to change a tag value based on what triggered the build (i.e. what's the build cause). After a lot of tinkering, I'm doing something like this:

def cause = 'something' // actually comes from currentBuild.rawBuild.getCause...
properties([
  [
    $class: 'DatadogJobProperty',
    tagProperties: "cause=${cause}"
  ]
])

And this sort of works, but isn't really reliable. It causes issues when multiple jobs run concurrently. The current DatadogJobProperty value is used whenever a build finishes. That means that if job A starts with cause "A" and job B starts with cause "B" before A finishes running, then both jobs will use the last DatadogJobProperty which has "B" configured as the cause.

I also tried the following, but this fails to set the value altogether. The tag ends up as cause=_cause.

env.CAUSE = 'something' // actually comes from currentBuild.rawBuild.getCause...
properties([
  [
    $class: 'DatadogJobProperty',
    tagProperties: 'cause=${CAUSE}'
  ]
])

tags for releases?

Any chance we could get tags for the release changeset ids for the last couple of releases? Would make it easier for those who have to git clone && git checkout releases.

thx!

plugin binds a UDP socket for every build and never releases it

This behaviour will continue until Jenkins runs out of file descriptors, rendering it completely inoperable. Jenkins will then fill the disk at a very rapid rate with logs explaining it's out of file descriptors.

Here's the output of netstat and tcpdump confirming this.

tcpdump

21:07:22.531862 IP (tos 0x0, ttl 64, id 58450, offset 0, flags [DF], proto UDP (17), length 90)
    127.0.0.1.39127 > 127.0.0.1.8125: [bad udp cksum 0xfe59 -> 0xb716!] UDP, length 62
        0x0000:  0000 0304 0006 0000 0000 0000 6f6e 0800  ............on..
        0x0010:  4500 005a e452 4000 4011 583e 7f00 0001  E..Z.R@[email protected]>....
        0x0020:  7f00 0001 98d7 1fbd 0046 fe59 6a65 6e6b  .........F.Yjenk
        0x0030:  696e 732e 6a6f 622e 636f 6d70 6c65 7465  ins.job.complete
        0x0040:  643a 317c 637c 2362 7261 6e63 683a 6f72  d:1|c|#branch:or
        0x0050:  6967 696e 2f64 6576 656c 6f70 6d65 6e74  igin/development
        0x0060:  2c6a 6f62 3a55 492d 5141                 ,job:UI-QA
21:07:27.421957 IP (tos 0x0, ttl 64, id 59563, offset 0, flags [DF], proto UDP (17), length 110)
    127.0.0.1.34209 > 127.0.0.1.8125: [bad udp cksum 0xfe6d -> 0xfecf!] UDP, length 82
        0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
        0x0010:  4500 006e e8ab 4000 4011 53d1 7f00 0001  E..n..@[email protected].....
        0x0020:  7f00 0001 85a1 1fbd 005a fe6d 6a65 6e6b  .........Z.mjenk
        0x0030:  696e 732e 6a6f 622e 636f 6d70 6c65 7465  ins.job.complete
        0x0040:  643a 317c 637c 2362 7261 6e63 683a 7061  d:1|c|#branch:pa
        0x0050:  6769 6e61 7465 2d74 6865 2d6f 7267 616e  ginate-the-organ
        0x0060:  697a 6174 696f 6e73 2d6c 6973 742c 6a6f  izations-list,jo
        0x0070:  623a 496e 7472 616e 6574 2050 5273       b:Intranet.PRs
21:07:45.624593 IP (tos 0x0, ttl 64, id 62489, offset 0, flags [DF], proto UDP (17), length 113)
    127.0.0.1.33975 > 127.0.0.1.8125: [bad udp cksum 0xfe70 -> 0x6cfc!] UDP, length 85
        0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
        0x0010:  4500 0071 f419 4000 4011 4860 7f00 0001  E..q..@[email protected]`....
        0x0020:  7f00 0001 84b7 1fbd 005d fe70 6a65 6e6b  .........].pjenk
        0x0030:  696e 732e 6a6f 622e 636f 6d70 6c65 7465  ins.job.complete
        0x0040:  643a 317c 637c 2362 7261 6e63 683a 6f72  d:1|c|#branch:or
        0x0050:  6967 696e 2f70 6167 696e 6174 652d 6f72  igin/paginate-or
        0x0060:  6761 6e69 7a61 7469 6f6e 732d 6c69 7374  ganizations-list
        0x0070:  2c6a 6f62 3a49 6e74 7261 6e65 7420 5052  ,job:Intranet.PR
        0x0080:  73                                       s
21:08:01.167220 IP (tos 0x0, ttl 64, id 64502, offset 0, flags [DF], proto UDP (17), length 117)
    127.0.0.1.35373 > 127.0.0.1.8125: [bad udp cksum 0xfe74 -> 0x8de8!] UDP, length 89
        0x0000:  0000 0304 0006 0000 0000 0000 0000 0800  ................
        0x0010:  4500 0075 fbf6 4000 4011 407f 7f00 0001  E..u..@.@.@.....
        0x0020:  7f00 0001 8a2d 1fbd 0061 fe74 6a65 6e6b  .....-...a.tjenk
        0x0030:  696e 732e 6a6f 622e 636f 6d70 6c65 7465  ins.job.complete
        0x0040:  643a 317c 637c 2362 7261 6e63 683a 6f72  d:1|c|#branch:or
        0x0050:  6967 696e 2f70 6167 696e 6174 652d 7468  igin/paginate-th
        0x0060:  652d 6f72 6761 6e69 7a61 7469 6f6e 732d  e-organizations-
        0x0070:  6c69 7374 2c6a 6f62 3a49 6e74 7261 6e65  list,job:Intrane
        0x0080:  7420 5052 73                             t.PRs

netstat

The values in the Recv-Q column are due to me using netcat to prod the ports

root@ip-10-0-103-29:/var/lib/jenkins# netstat -nape | grep java | grep udp6
udp6       0      0 :::35373                :::*                                106        2770877827  20518/java
udp6    3840      0 :::60431                :::*                                106        2770521115  20518/java
udp6       0      0 :::5353                 :::*                                106        2770515125  20518/java
udp6       0      0 :::39127                :::*                                106        2770877557  20518/java
udp6       0      0 :::33848                :::*                                106        2770515122  20518/java
udp6     768      0 :::58444                :::*                                106        2770831899  20518/java
udp6       0      0 :::33975                :::*                                106        2770877724  20518/java
udp6       0      0 :::34209                :::*                                106        2770877594  20518/java
udp6    1536      0 :::34463                :::*                                106        2770624072  20518/java
udp6       0      0 :::34679                :::*                                106        2770559677  20518/java
unix  2      [ ]         STREAM     CONNECTED     2770016066 20518/java
unix  2      [ ]         STREAM     CONNECTED     2770506247 20518/java

As you can see, the source ports in tcpdump match up with bound ports in the netstat output. I don't expect Jenkins to require non-blocking statsd sends, perhaps that's the easiest way to fix this?

Having stage statistics

Currently it is possible to know if a job failed, but it would be interesting to know in what stage of the pipeline the job failed.

Example of use case:
Jenkins job is devided into the following stages:

  • lint
  • build
  • test backend
  • test frontend
  • functional tests

Knowing that a job fails during build or during functional tests requires very different actions to fix.

Multiple DataDog Accounts per Jenkins

We're using a shared Jenkins Server/Cluster and like to have the ability to integrate with different DataDog Accounts on a per job basis. Can this plugin also be configured on a per job basis?

When used with GitHub org folder plugin; all jobs labeled master

When used in combination with GitHub Organization Folder Plugin, a lot of jobs are tagged as #job:master in datadog. This is due to the folder structure set up by this plugin (GitHubOrganizationName>ProjectName>BranchName).

This makes it hard to distinguish and collect metrics on specific projects in a github organization.

I'm thinking that a feasible approach would be adding another tag to jobs that specify parent folder or something similar. So that it won't interfere with regular nested folders.

Add option to add hostname

The agent currently has the option to allow adding a hostname indatadog.conf. Let's add this option to the configuration screen for the plugin as well.

Plugin does not seem to respect proxy settings

We run our Jenkins v1.596 server in a lab that lives behind proxies. From the CLI, replacing real values with dummy values here, I can successfully run

export http_proxy=http://myproxy.foo.com:80/
export https_proxy=http://myproxy.foo.com:80/
wget https://app.datadoghq.com/api/v1/validate?api_key=1234key

The wget completes in just a second and returns the following body content: {"valid": true}

But when I run a Jenkins job, the plugin just hangs and then times out (after several minutes) with output like this, and we never see events in our DataDog dashboard

DatadogBuildListener.java: Started build!
DatadogBuildListener.java: Using hostname set in 'Manage Plugins'. Hostname: myhostname.foo.com
DatadogBuildListener.java: Sending event

Similarly, in the Manage Jenkins > Configure System page, we have the same proxies set in the Global properties section. In the Datadog Plugin, when I enter my key and click "Test", it spins for a while and then gives me "ERROR".

I also tried adding the following arguments to the CLI where I launch Jenkins: -Dhttp.proxyHost=myproxy.foo.com -Dhtttps.proxyHost=myproxy.foo.com -Dhttps.proxyPort=80

Same (bad) behavior from the plugin.

From a general Java perspective, these links may be useful: http://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html and http://stackoverflow.com/questions/2430142/java-app-behind-proxy-to-use-http-proxy-variable-in-linux. But I've never written a Jenkins plugin before, so I'm not sure whether there's anything special the plugin needs to do to pick up the proxy settings.

Change package name

Currently we are shipping with the package name datadog-build-reporter, however this should be datadog. This is because the hosted repository on jenkinsci is called datadog-plugin, where the -plugin is a typical appending that jenkinsci does for all plugins. Hence, this change helps to keep things consistent.

datadog plugin impacting job performance

As soon as we are installing this plugin into our Jenkins, any job takes around 2 minutes to start and after it gets start also performance remains slow through out the job flow. Job which usually takes 5 minutes to complete is taking more than double of that time.

java NPE exception

This appears to be a new issue that seems to have shown up after the upgrade of the datadog plugin to version .5

A lot of our jenkins job now crashes right at a beginning, with a NPE exception....

java.io.IOException: java.lang.NullPointerException
16:53:52 at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:614)
16:53:52 at jenkins.scm.SCMCheckoutStrategy.checkout(SCMCheckoutStrategy.java:86)
16:53:52 at hudson.model.AbstractBuild$AbstractBuildExecution.run(AbstractBuild.java:529)
16:53:52 at hudson.model.Run.execute(Run.java:1738)
16:53:52 at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43)
16:53:52 at hudson.model.ResourceController.execute(ResourceController.java:98)
16:53:52 at hudson.model.Executor.run(Executor.java:410)
16:53:52 Caused by: java.lang.NullPointerException
16:53:52 at org.datadog.jenkins.plugins.datadog.DatadogSCMListener.onCheckout(DatadogSCMListener.java:47)
16:53:52 at hudson.model.AbstractBuild$AbstractBuildExecution.defaultCheckout(AbstractBuild.java:612)

Unfortunately, this is causing a lot of our jobs to be unusable.....

Add service check when a job is running

Hi! We think it would also be useful to report a service check when the job is currently running, so we can monitor that too in our dashboard. Main problem is, what status should it emit? AFAIK there only 4 possible statuses and I'm not sure if a "Running Job" would better qualify as a WARNING or UNKNOWN, I'm not 100% happy with any of them, opinions?

Allow adding custom tags per job

The simplest solution would be to add a configuration option to each jobs config page where an admin could enter in a set of tags to tag the job with. However a static list of tags, while useful, is not sufficient for us.

We us parameterized jobs extensively. For example the same job builds all of our dropwizard projects in different configuration such as snapshot builds, release, builds, builds targeting platform X, targeting platform Y, etc. At the very least we would need to be able to specify that certain build parameters, or even certain environment variables, need to be set as the values of certain tags. For example set the #release tag to the value of the $DO_RELEASE env variable, and the #project tag be set to something based on which git repository we built from.

One possibility that would provide for maximum flexibility would be to be able to read in a set of tag values from a specified file in the workspace. This way we could use any sort of post build script to programmatically setup our tags.

Emit counter for completed jobs

We would like to graph failed jobs, grouped by job, on our Jenkins dashboards. It doesn't look like it's possible to add the count of each event on a dashboard, and looking at other plugins using a count metric is the typical method for doing this.

With a jenkins.job.completed counter, we can use sum and filter accordingly and then add the graph as expected.

We use the service checks for monitors, which are working fine, but we can't add that graph to a dashboard.

Allow the ability to constrain the jobs that are tracked

Use case: I only want to report on branches that can harm my production environment (ie. merges/deploys to branch "master") I'd like to whitelist those and have all others ignored.

The current blacklist doesn't help as each team/feature branch has different naming and it doesn't scale.

Blacklist feature added here:
#6

Add a tag for Node (slave) name

Based on line 175 it would seem this is already in place but we are not seeing any node tag and this would be very useful for us in alerting when a particular slave is having problems.

Capture total number of jobs

Total number of defined jobs in a jenkins instance is easy to acquire but also essential for monitoring long term performance of Jenkins.

There are huge performance impacts between an instance with 10, 100, 500, or 3000 jobs defined.

Support prefix for White/Blacklist

Hi there,

Can you consider to support to specify job name prefixes for white/black lists? Aka. exclude jobs in a "sandbox/" folder? Thanks.

Wei

Append the default parameter "Add tags from file in workspace" in general plugin configuration

To be clear I'll explain the issue first.

Let's assume that we have a Github organization/Bitbucket organization folder where all Jenkins jobs are created automatically for every new repository with Jenkinsfile or repo branches. This setup is pretty popular for now. But how can we tag the builds for Datadog? For now there is no clear option for this. Every job has Datadog tagging parameters, but they couldn't be modified because the organization folder jobs are immutable. Also the tags couldn't be appended at any folder level.

Also here is the issue out of such setup. Even if we manually create Jenkins job, we have to always make sure that the "Add tags from file in workspace" option is filled and we can't inherit any default settings. Which sometimes seems pretty useful due to organisation standards (e.g. have a tags.dd file in every repo/project with tags declaration). And, if you want to migrate to Datadog - it means that you have to setup this parameter manually on all existing jobs (that's probably wrong, but all my attempts to do this through XML reconfig&reload and Groovy scripts were failed).

If we could append the option in "Manage Jenkins โ†’ Configure System โ†’ Datadog Plugin" the option to declare the default file in workspace and inherit this parameter for every job. This feature would make the tagging setup much easier.

Please, let me know if something isn't clear at this issue.

Test Key in Jenkins fails with this stack trace

java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at java.security.cert.PKIXParameters.setTrustAnchors(PKIXParameters.java:200)
at java.security.cert.PKIXParameters.(PKIXParameters.java:120)
at java.security.cert.PKIXBuilderParameters.(PKIXBuilderParameters.java:104)
at sun.security.validator.PKIXValidator.(PKIXValidator.java:88)
Caused: java.lang.RuntimeException: Unexpected error
at sun.security.validator.PKIXValidator.(PKIXValidator.java:90)
at sun.security.validator.Validator.getInstance(Validator.java:179)
at sun.security.ssl.X509TrustManagerImpl.getValidator(X509TrustManagerImpl.java:312)
at sun.security.ssl.X509TrustManagerImpl.checkTrustedInit(X509TrustManagerImpl.java:171)
at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:184)
at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1496)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:961)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
Caused: javax.net.ssl.SSLException
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1906)
at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1889)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1410)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
at org.datadog.jenkins.plugins.datadog.DatadogBuildListener$DescriptorImpl.doTestConnection(DatadogBuildListener.java:440)
Caused: javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1926)
at sun.net.www.protocol.http.HttpURLConnection$10.run(HttpURLConnection.java:1921)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.protocol.http.HttpURLConnection.getChainedException(HttpURLConnection.java:1920)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1490)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
at org.datadog.jenkins.plugins.datadog.DatadogBuildListener$DescriptorImpl.doTestConnection(DatadogBuildListener.java:456)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
at org.kohsuke.stapler.MetaClass$1.doDispatch(MetaClass.java:129)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
at org.kohsuke.stapler.MetaClass$5.doDispatch(MetaClass.java:248)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:649)
at org.kohsuke.stapler.Stapler.service(Stapler.java:238)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:841)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1650)
at hudson.util.PluginServletFilter$1.doFilter(PluginServletFilter.java:135)
at hudson.util.PluginServletFilter.doFilter(PluginServletFilter.java:138)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at hudson.security.csrf.CrumbFilter.doFilter(CrumbFilter.java:85)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:84)
at hudson.security.UnwrapSecurityExceptionFilter.doFilter(UnwrapSecurityExceptionFilter.java:51)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at jenkins.security.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:117)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.providers.anonymous.AnonymousProcessingFilter.doFilter(AnonymousProcessingFilter.java:125)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.rememberme.RememberMeProcessingFilter.doFilter(RememberMeProcessingFilter.java:142)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.ui.AbstractProcessingFilter.doFilter(AbstractProcessingFilter.java:271)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at jenkins.security.BasicHeaderProcessor.doFilter(BasicHeaderProcessor.java:93)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at org.acegisecurity.context.HttpSessionContextIntegrationFilter.doFilter(HttpSessionContextIntegrationFilter.java:249)
at hudson.security.HttpSessionContextIntegrationFilter2.doFilter(HttpSessionContextIntegrationFilter2.java:67)
at hudson.security.ChainedServletFilter$1.doFilter(ChainedServletFilter.java:87)
at hudson.security.ChainedServletFilter.doFilter(ChainedServletFilter.java:90)
at hudson.security.HudsonFilter.doFilter(HudsonFilter.java:171)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at org.kohsuke.stapler.compression.CompressionFilter.doFilter(CompressionFilter.java:49)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at hudson.util.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:82)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at org.kohsuke.stapler.DiagnosticThreadNameFilter.doFilter(DiagnosticThreadNameFilter.java:30)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1637)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:533)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1595)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:188)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:168)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1564)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:166)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:564)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:317)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:251)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:110)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at winstone.BoundedExecutorService$1.run(BoundedExecutorService.java:77)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)

java.lang.NullPointerException with DD 0.5.1 on Jenkins 2.9

I am using the datadog plugin version 0.5.1 with jenkins version 2.9, and in the jenkins log I see the following. Although my API key seems to check out fine using the system control panel, no events make it to DataDog. Any suggestions?

WARNING: RunListener failed java.lang.NullPointerException at org.datadog.jenkins.plugins.datadog.DatadogUtilities.parseTagList(DatadogUtilities.java:105) at org.datadog.jenkins.plugins.datadog.DatadogBuildListener.onStarted(DatadogBuildListener.java:103) at hudson.model.listeners.RunListener.fireStarted(RunListener.java:240) at hudson.model.Run.execute(Run.java:1716) at hudson.model.FreeStyleBuild.run(FreeStyleBuild.java:43) at hudson.model.ResourceController.execute(ResourceController.java:98) at hudson.model.Executor.run(Executor.java:410)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.