diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ba6901909abf8f..38c63aa95430d9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -84,7 +84,6 @@ /pkg/process/ @DataDog/processes /pkg/process/checks/pod*.go @DataDog/container-app /pkg/ebpf/ @DataDog/networks -/pkg/procmatch/ @DataDog/processes /pkg/quantile @DataDog/metrics-aggregation /releasenotes/ @DataDog/agent-all diff --git a/pkg/procmatch/default_catalog.go b/pkg/procmatch/default_catalog.go deleted file mode 100644 index fc13431d071706..00000000000000 --- a/pkg/procmatch/default_catalog.go +++ /dev/null @@ -1,383 +0,0 @@ -// Code generated by go generate; DO NOT EDIT. -package procmatch - -var DefaultCatalog IntegrationCatalog = IntegrationCatalog{ - IntegrationEntry{ - DisplayName: "ActiveMQ", - MetricPrefix: "activemq.", - Name: "activemq", - Signatures: []string{ - "activemq", - }, - }, - IntegrationEntry{ - DisplayName: "Apache", - MetricPrefix: "apache.", - Name: "Apache", - Signatures: []string{ - "httpd", - "apache", - "apache2", - }, - }, - IntegrationEntry{ - DisplayName: "Cassandra", - MetricPrefix: "cassandra.", - Name: "cassandra", - Signatures: []string{ - "java org.apache.cassandra.service.CassandraDaemon", - }, - }, - IntegrationEntry{ - DisplayName: "Ceph", - MetricPrefix: "ceph.", - Name: "ceph", - Signatures: []string{ - "ceph-mon", - "ceph-mgr", - "ceph-osd", - }, - }, - IntegrationEntry{ - DisplayName: "Consul", - MetricPrefix: "consul.", - Name: "consul", - Signatures: []string{ - "consul agent", - "consul_agent", - "consul-agent", - }, - }, - IntegrationEntry{ - DisplayName: "CouchDB", - MetricPrefix: "couch.", - Name: "couch", - Signatures: []string{ - "couchjs", - }, - }, - IntegrationEntry{ - DisplayName: "Couchbase", - MetricPrefix: "couchbase.", - Name: "couchbase", - Signatures: []string{ - "beam.smp couchbase", - }, - }, - IntegrationEntry{ - DisplayName: "Docker", - MetricPrefix: "docker.", - Name: "docker_daemon", - Signatures: []string{ - "dockerd", - "docker-containerd", - "docker run", - "docker daemon", - "docker-containerd-shim", - }, - }, - IntegrationEntry{ - DisplayName: "Elasticsearch", - MetricPrefix: "elasticsearch.", - Name: "elastic", - Signatures: []string{ - "java org.elasticsearch.bootstrap.Elasticsearch", - }, - }, - IntegrationEntry{ - DisplayName: "etcd", - MetricPrefix: "etcd.", - Name: "etcd", - Signatures: []string{ - "etcd", - }, - }, - IntegrationEntry{ - DisplayName: "fluentd", - MetricPrefix: "fluentd.", - Name: "fluentd", - Signatures: []string{ - "td-agent", - "fluentd", - "ruby td-agent", - }, - }, - IntegrationEntry{ - DisplayName: "Gearman", - MetricPrefix: "gearmand.", - Name: "gearmand", - Signatures: []string{ - "gearmand", - "gearman", - }, - }, - IntegrationEntry{ - DisplayName: "Gunicorn", - MetricPrefix: "gunicorn.", - Name: "gunicorn", - Signatures: []string{ - "gunicorn: master", - }, - }, - IntegrationEntry{ - DisplayName: "HAProxy", - MetricPrefix: "haproxy.", - Name: "haproxy", - Signatures: []string{ - "haproxy", - "haproxy-master", - "haproxy-controller", - }, - }, - IntegrationEntry{ - DisplayName: "Kafka", - MetricPrefix: "kafka.", - Name: "kafka", - Signatures: []string{ - "java kafka.kafka", - }, - }, - IntegrationEntry{ - DisplayName: "Kong", - MetricPrefix: "kong.", - Name: "kong", - Signatures: []string{ - "kong start", - }, - }, - IntegrationEntry{ - DisplayName: "Kyoto Tycoon", - MetricPrefix: "kyototycoon.", - Name: "kyototycoon", - Signatures: []string{ - "ktserver", - }, - }, - IntegrationEntry{ - DisplayName: "Lighttpd", - MetricPrefix: "lighttpd.", - Name: "lighttpd", - Signatures: []string{ - "lighttpd", - }, - }, - IntegrationEntry{ - DisplayName: "Marathon", - MetricPrefix: "marathon.", - Name: "marathon", - Signatures: []string{ - "start --master mesos marathon", - }, - }, - IntegrationEntry{ - DisplayName: "Memcached", - MetricPrefix: "memcache.", - Name: "mcache", - Signatures: []string{ - "memcached", - }, - }, - IntegrationEntry{ - DisplayName: "Mesos Master", - MetricPrefix: "mesos.", - Name: "mesos_master", - Signatures: []string{ - "mesos-master.sh --ip=127.0.0.1 --work_dir=/var/lib/mesos", - "mesos-agent.sh --master --work_dir=/var/lib/mesos", - }, - }, - IntegrationEntry{ - DisplayName: "MongoDB", - MetricPrefix: "mongodb.", - Name: "mongo", - Signatures: []string{ - "mongod", - }, - }, - IntegrationEntry{ - DisplayName: "MySQL", - MetricPrefix: "mysql.", - Name: "MySQL", - Signatures: []string{ - "mysqld", - }, - }, - IntegrationEntry{ - DisplayName: "Nagios", - MetricPrefix: "nagios.", - Name: "nagios", - Signatures: []string{ - "nagios", - }, - }, - IntegrationEntry{ - DisplayName: "Nginx", - MetricPrefix: "nginx.", - Name: "nginx", - Signatures: []string{ - "nginx: master process", - }, - }, - IntegrationEntry{ - DisplayName: "OpenStack", - MetricPrefix: "openstack.", - Name: "openstack", - Signatures: []string{ - "stack.sh", - }, - }, - IntegrationEntry{ - DisplayName: "PGBouncer", - MetricPrefix: "pgbouncer.", - Name: "pgbouncer", - Signatures: []string{ - "pgbouncer", - }, - }, - IntegrationEntry{ - DisplayName: "PHP-FPM", - MetricPrefix: "php_fpm.", - Name: "php_fpm", - Signatures: []string{ - "php-fpm", - "php7.0-fpm", - "php7.0-fpm start", - "service php-fpm", - "php7.0-fpm restart", - "restart php-fpm", - "systemctl restart php-fpm.service", - "php7.0-fpm.service", - }, - }, - IntegrationEntry{ - DisplayName: "Postfix", - MetricPrefix: "postfix.", - Name: "postfix", - Signatures: []string{ - "postfix start", - "sendmail -bd", - }, - }, - IntegrationEntry{ - DisplayName: "Postgres", - MetricPrefix: "postgresql.", - Name: "postgres", - Signatures: []string{ - "postgres -D", - "pg_ctl start -l logfile", - "postgres -c 'pg_ctl start -D -l", - }, - }, - IntegrationEntry{ - DisplayName: "PowerDNS Recursor", - MetricPrefix: "powerdns.", - Name: "powerdns_recursor", - Signatures: []string{ - "pdns_server", - "systemctl start pdns@", - }, - }, - IntegrationEntry{ - DisplayName: "RabbitMQ", - MetricPrefix: "rabbitmq.", - Name: "rabbitmq", - Signatures: []string{ - "rabbitmq", - }, - }, - IntegrationEntry{ - DisplayName: "Redis", - MetricPrefix: "redis.", - Name: "redisdb", - Signatures: []string{ - "redis-server", - }, - }, - IntegrationEntry{ - DisplayName: "RethinkDB", - MetricPrefix: "rethinkdb.", - Name: "rethinkdb", - Signatures: []string{ - "rethinkdb", - }, - }, - IntegrationEntry{ - DisplayName: "Riak CS", - MetricPrefix: "riakcs.", - Name: "riakcs", - Signatures: []string{ - "riak-cs start", - }, - }, - IntegrationEntry{ - DisplayName: "Solr", - MetricPrefix: "solr.", - Name: "solr", - Signatures: []string{ - "solr start", - }, - }, - IntegrationEntry{ - DisplayName: "SSH", - MetricPrefix: "ssh.", - Name: "ssh_check", - Signatures: []string{ - "ssh", - "sftp", - "sshd", - "sshd:", - }, - }, - IntegrationEntry{ - DisplayName: "Supervisord", - MetricPrefix: "supervisord.", - Name: "supervisord", - Signatures: []string{ - "python supervisord", - "supervisord", - }, - }, - IntegrationEntry{ - DisplayName: "Teamcity", - MetricPrefix: "teamcity.", - Name: "teamcity", - Signatures: []string{ - "teamcity-server.sh", - "teamcity-server", - }, - }, - IntegrationEntry{ - DisplayName: "TokuMX", - MetricPrefix: "tokumx.", - Name: "tokumx", - Signatures: []string{ - "mongod --config /etc/tokumx.conf", - }, - }, - IntegrationEntry{ - DisplayName: "Tomcat", - MetricPrefix: "tomcat.", - Name: "tomcat", - Signatures: []string{ - "java tomcat", - }, - }, - IntegrationEntry{ - DisplayName: "Varnish", - MetricPrefix: "varnish.", - Name: "varnish", - Signatures: []string{ - "service varnish start", - "varnishd", - }, - }, - IntegrationEntry{ - DisplayName: "ZooKeeper", - MetricPrefix: "zookeeper.", - Name: "zk", - Signatures: []string{ - "zkServer.sh start", - "java zoo.cfg", - }, - }, -} diff --git a/pkg/procmatch/gen/generate_catalog.go b/pkg/procmatch/gen/generate_catalog.go deleted file mode 100644 index 2192f26c7ae12a..00000000000000 --- a/pkg/procmatch/gen/generate_catalog.go +++ /dev/null @@ -1,87 +0,0 @@ -// +build ignore - -package main - -import ( - "bytes" - "encoding/json" - "fmt" - "html/template" - "io/ioutil" - "os" - "path" -) - -type Manifest struct { - DisplayName *string `json:"display_name"` - MetricPrefix *string `json:"metric_prefix"` - Name *string `json:"name"` - Signatures []string `json:"process_signatures"` -} - -const codeTemplate = `// Code generated by go generate; DO NOT EDIT. -package procmatch - -var DefaultCatalog IntegrationCatalog = IntegrationCatalog{{"{"}}{{ range $_, $manifest := . }} - IntegrationEntry{ - DisplayName: "{{$manifest.DisplayName}}", - MetricPrefix: "{{$manifest.MetricPrefix}}", - Name: "{{$manifest.Name}}", - Signatures: []string{{"{"}}{{ range $_, $sig := $manifest.Signatures }} - "{{$sig}}",{{end}} - }, - },{{ end }} -} -` - -func readManifest(raw []byte) (Manifest, bool) { - m := Manifest{} - _ = json.Unmarshal(raw, &m) - return m, m.Signatures != nil && m.Name != nil && m.MetricPrefix != nil -} - -func failIf(err error, format string, args ...interface{}) { - if err != nil { - fmt.Fprintf(os.Stderr, format, args...) - os.Exit(1) - } -} - -func main() { - rootDir := os.Getenv("INTEGRATIONS_CORE_DIR") - - if len(rootDir) == 0 { - fmt.Fprintln(os.Stderr, "Please set INTEGRATIONS_CORE_DIR env variable") - os.Exit(1) - } - - dirs, err := ioutil.ReadDir(rootDir) - failIf(err, "An error occurred listing directories in %s: %s", rootDir, err) - - manifests := []Manifest{} - - for _, dir := range dirs { - if dir.IsDir() { - // Ignore errors - manifest, _ := ioutil.ReadFile(path.Join(rootDir, dir.Name(), "manifest.json")) - decoded, ok := readManifest(manifest) - if ok { - manifests = append(manifests, decoded) - } - } - } - - tmpl := template.New("catalog") - tmpl, err = tmpl.Parse(codeTemplate) - failIf(err, "Couldn't parse code template: %s", err) - - var buf bytes.Buffer - - err = tmpl.Execute(&buf, manifests) - failIf(err, "Couldn't execute template: %s", err) - - err = ioutil.WriteFile("./default_catalog.go", buf.Bytes(), 0644) - failIf(err, "Couldn't write file to disk: %s", err) - - fmt.Printf("%v entries generated !\n", len(manifests)) -} diff --git a/pkg/procmatch/graph.go b/pkg/procmatch/graph.go deleted file mode 100644 index cde1dcff8af5d9..00000000000000 --- a/pkg/procmatch/graph.go +++ /dev/null @@ -1,160 +0,0 @@ -package procmatch - -import ( - "fmt" - "strings" - "unicode" -) - -// signatureGraph holds the catalog as a graph to be able to quickly find an integration for a given command line (split by word) -// - Nodes either represent an integration, or an intermediary state that may lead to another, more specific integration -// - Edges represent the string components of the signature, which ultimately map to an integration -// e.g. -// (root) ---"java"---> (integration: java) ---"elasticsearch"-> (integration: elastic search) -// \--"kafka.Kafka"---> (integration: kafka) -// \--"jar"-----------> (integration: nil) ---"MapReduce.jar"---> (integration: map reduce) -// \--"zookeeper.jar"---> (integration: zookeeper) -type signatureGraph struct { - root *node -} - -// Node represents a node on the signatureGraph -type node struct { - // The integration field indicates if this node actually represents a valid integration. - // While walking through the graph, if we reach a node whose integration != "", it means that we found - // a potential integration to the cmdline - integration Integration - - // We use a map to link a node to its children so at which time that we try to move on the graph - // we can do it in a O(1) operation - children map[string]*node -} - -// buildsignatureGraph takes a slice of signatures and constructs a signatureGraph for them -func buildSignatureGraph(signatures []signature) (*signatureGraph, error) { - graph := &signatureGraph{ - root: &node{ - integration: Integration{}, - children: make(map[string]*node), - }, - } - - // Recursively construct the graph from the root - if err := expandNode(graph.root, signatures); err != nil { - return nil, err - } - return graph, nil -} - -// expandNode analyzes the signatures of a node and groups the signatures with same first word. -// Then it creates a new child node for each group and recursively applies the same process for each child -func expandNode(n *node, sigs []signature) error { - if len(sigs) == 0 { // It's a leaf node so nothing left to be done - return nil - } - - signaturesForNode := make(map[*node][]signature) - - // Searches for signatures with same first word, creates a new node for them and remove them from the sigs list - for len(sigs) > 0 { - sig := sigs[0] - word := sig.words[0] - - newNode := &node{ - integration: Integration{}, - children: make(map[string]*node), - } - n.children[word] = newNode - - // If the signature has more words to be processed, the remaining part of it must be in the child's signatures. - // Otherwise, this signature has been all processed and the child'll contain its integration - if len(sig.words) > 1 { - sig.words = sig.words[1:] - signaturesForNode[newNode] = append(signaturesForNode[newNode], sig) - } else { - newNode.integration = sig.integration - } - - // Stores the position of the signatures with the same first word to remove them from the sigs list - toRemove := make([]int, 0) - - // Searches for signatures with same path - for i := range sigs { - s := sigs[i] - - // This signature has the same path at the current one - if s.words[0] == word { - toRemove = append(toRemove, i) - - if len(s.words) == 1 && newNode.integration.Name != "" && s.integration.Name != newNode.integration.Name { - return fmt.Errorf("Two different signatures are leading to the same node with different integration."+ - "Current :%s with %s + %s, other %s with %s\n", sig.integration.Name, word, sig.words, s.integration.Name, s.words) - } - - // Verify if this signature has been completely processed - if len(s.words) > 1 { - s.words = s.words[1:] - signaturesForNode[newNode] = append(signaturesForNode[newNode], s) - } else { - newNode.integration = s.integration - } - } - } - - // Create a new filtered sigs list - sigs = removeByIndex(sigs, toRemove) - } - - // Apply the same process recursively on each child - for _, child := range n.children { - err := expandNode(child, signaturesForNode[child]) - if err != nil { - return err - } - } - return nil -} - -func removeByIndex(sigs []signature, indices []int) []signature { - filtered := []signature{} - for i := range sigs { - if len(indices) > 0 && i == indices[0] { - indices = indices[1:] - continue - } - filtered = append(filtered, sigs[i]) - } - return filtered -} - -// splitCmdline splits a cmdline by " " or "/" -func splitCmdline(r rune) bool { - return r == '/' || unicode.IsSpace(r) -} - -func (g *signatureGraph) searchIntegration(cmdline string) Integration { - integration := Integration{} - walk(g.root, strings.FieldsFunc(strings.ToLower(cmdline), splitCmdline), &integration) - return integration -} - -// walk takes the words from a cmdline and use them to move trough the graph -func walk(node *node, cmdline []string, integration *Integration) { - // If we reach a node with an integration, it's potentially the cmdline integration - if node.integration.Name != "" { - *integration = node.integration - } - - if len(node.children) == 0 || len(cmdline) == 0 { - return - } - - // Each one of the words of a cmdline is used to walk through the graph - for i := range cmdline { - // If this word links the current node to a child, we move to the child - if nextNode, ok := node.children[cmdline[i]]; ok { - walk(nextNode, cmdline[i+1:], integration) - break - } - } -} diff --git a/pkg/procmatch/graph_matcher.go b/pkg/procmatch/graph_matcher.go deleted file mode 100644 index 7971c6d91e8568..00000000000000 --- a/pkg/procmatch/graph_matcher.go +++ /dev/null @@ -1,23 +0,0 @@ -package procmatch - -import "fmt" - -type graphMatcher struct { - graph *signatureGraph -} - -func (m graphMatcher) Match(cmdline string) Integration { - return m.graph.searchIntegration(cmdline) -} - -// NewMatcher builds a graph matcher from an integration catalog -func NewMatcher(catalog IntegrationCatalog) (Matcher, error) { - signatures := buildSignatures(catalog) - - graph, err := buildSignatureGraph(signatures) - if err != nil { - return nil, fmt.Errorf("error building the graph: %s", err) - } - - return graphMatcher{graph}, nil -} diff --git a/pkg/procmatch/graph_matcher_test.go b/pkg/procmatch/graph_matcher_test.go deleted file mode 100644 index 73334d2e819500..00000000000000 --- a/pkg/procmatch/graph_matcher_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package procmatch - -import "testing" - -var avoidOptimization Integration - -var ( - rawIntegs = []IntegrationEntry{ - {"ActiveMQ", "", "", []string{"activemq"}}, - {"Airbrake", "", "", []string{"rake airbrake:deploy"}}, - {"Apache", "", "", []string{"httpd", "apache"}}, - {"BitBucket", "", "", []string{"start-bitbucket.sh ", "service atlbitbucket start"}}, - {"Bugsnag", "", "", []string{"bugsnag-agent", "start bugsnag"}}, - {"Cassandra", "", "", []string{"java org.apache.cassandra.service.CassandraDaemon"}}, - {"Ceph", "", "", []string{"ceph-*"}}, - {"Consul", "", "", []string{"consul agent", "consul_agent", "consul-agent"}}, - {"Couchbase", "", "", []string{"beam.smp"}}, - {"CouchDB", "", "", []string{"couchjs"}}, - {"Docker", "", "", []string{"dockerd", "docker-containerd", "docker run", "docker daemon", " docker-containerd-shim"}}, - {"Elasticsearch", "", "", []string{"java org.elasticsearch.bootstrap.Elasticsearch"}}, - {"Etcd", "", "", []string{"etcd"}}, - {"fluentd", "", "", []string{"td-agent", "fluentd", "ruby td-agent"}}, - {"Gearman", "", "", []string{"gearmand", "gearman"}}, - {"Gunicorn", "", "", []string{"gunicorn: master "}}, - {"HAProxy", "", "", []string{"haproxy", "haproxy-master"}}, - {"Java", "", "", []string{"java"}}, - {"Kafka", "", "", []string{"java kafka.kafka"}}, - {"Kong", "", "", []string{"kong start"}}, - {"Kyototycoon", "", "", []string{"ktserver"}}, - {"Lighttpd", "", "", []string{"lighttpd"}}, - {"Marathon", "", "", []string{"start --master mesos marathon"}}, - {"Memcached", "", "", []string{"memcached"}}, - {"Mesos", "", "", []string{" mesos-agent.sh --master --work_dir=/var/lib/mesos"}}, - {"Mongodb", "", "", []string{"mongod"}}, - {"Mysql", "", "", []string{"mysqld"}}, - {"Nagios", "", "", []string{"service snmpd restart", "systemctl restart snmpd.service"}}, - {"Nginx", "", "", []string{"nginx: master process"}}, - {"OpenStack", "", "", []string{"stack.sh"}}, - {"Pgbouncer", "", "", []string{"pgbouncer"}}, - {"PHP", "", "", []string{"php"}}, - {"PHP-FPM", "", "", []string{"php7.0-fpm", "php7.0-fpm start", "service php-fpm", "php7.0-fpm restart", "restart php-fpm", "systemctl restart php-fpm.service", "php7.0-fpm.service"}}, - {"Postfix", "", "", []string{"postfix start", "sendmail -bd"}}, - {"Postgres", "", "", []string{"postgres -D", "pg_ctl start -l logfile", "postgres -c 'pg_ctl start -D -l"}}, - {"PowerDNS Recursor", "", "", []string{"pdns_server", "systemctl start pdns@"}}, - {"RabbitMQ", "", "", []string{"rabbitmq"}}, - {"Redis", "", "", []string{"redis-server"}}, - {"Supervisord", "", "", []string{"python supervisord", "supervisord"}}, - {"Tomcat", "", "", []string{"java tomcat"}}, - } -) - -func BenchmarkGraph10(b *testing.B) { - m, err := NewMatcher(rawIntegs[:10]) - if err != nil { - return - } - benchmarkGraph(b, m) -} - -func BenchmarkGraph20(b *testing.B) { - m, err := NewMatcher(rawIntegs[:20]) - if err != nil { - return - } - benchmarkGraph(b, m) -} - -func BenchmarkGraph40(b *testing.B) { - m, err := NewMatcher(rawIntegs[:40]) - if err != nil { - return - } - benchmarkGraph(b, m) -} - -func BenchmarkGraphAll(b *testing.B) { - m, err := NewMatcher(rawIntegs) - if err != nil { - return - } - benchmarkGraph(b, m) -} - -func benchmarkGraph(b *testing.B, m Matcher) { - test := "myprogram -Xmx4000m -Xms4000m -XX:ReservedCodeCacheSize=256m -port 9999 kafka.Kafka" - - var r Integration - for n := 0; n < b.N; n++ { - r = m.Match(test) - } - avoidOptimization = r -} diff --git a/pkg/procmatch/procmatch.go b/pkg/procmatch/procmatch.go deleted file mode 100644 index aeba7bf80b861a..00000000000000 --- a/pkg/procmatch/procmatch.go +++ /dev/null @@ -1,36 +0,0 @@ -package procmatch - -//go:generate go run gen/generate_catalog.go - -// Matcher interface implements the Match method that takes a command line string and returns a potential integration for this command line string -type Matcher interface { - Match(cmdline string) Integration // Return the matched integration -} - -// Integration represents an integration -type Integration struct { - MetricPrefix string // Metric prefix of the integration - Name string // Name of the integration - DisplayName string // DisplayName of the integration -} - -// IntegrationEntry represents an integration entry in the catalog -type IntegrationEntry struct { - MetricPrefix string // Metric prefix of the integration - Name string // Name of the integration - DisplayName string // DisplayName of the integration - Signatures []string // Signatures of the integration's command line processes -} - -// IntegrationCatalog represents a list of Integrations -type IntegrationCatalog []IntegrationEntry - -type signature struct { - integration Integration - words []string -} - -// NewDefault returns the default matcher (graph one) built with the default catalog -func NewDefault() (Matcher, error) { - return NewMatcher(DefaultCatalog) -} diff --git a/pkg/procmatch/procmatch_test.go b/pkg/procmatch/procmatch_test.go deleted file mode 100644 index 4e5bc9f71b34a7..00000000000000 --- a/pkg/procmatch/procmatch_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package procmatch - -import ( - "testing" -) - -var testMatcher Matcher - -func init() { - testMatcher, _ = NewDefault() -} - -func assertIntegration(t *testing.T, e string, i string) { - if e != i { - t.Errorf("%s failed, wrong integration name, expected '%s' but got '%s'", t.Name(), e, i) - } -} - -func TestMatchIntegration(t *testing.T) { - cases := []struct { - cmdline string - integration string - }{ - {"java org.elasticsearch.bootstrap.Elasticsearch ‑Xms28000m ‑Xmx28000m ‑XX:+UseCompressedOops ‑Djna.tmpdir=/tmp/elasticsearch/jna ‑XX:+UseConcMarkSweepGC ‑XX:CMSInitiatingOccupancyFraction=75 ‑XX:+UseCMSInitiatingOccupancyOnly ‑XX:+DisableExplicitGC ‑XX:+AlwaysPreTouch ‑server ‑Xss1m ‑Djava.awt.headless=true ‑Dfile.encoding=UTF-8 ‑Djna.nosys=true ‑Djdk.io.permissionsUseCanonicalPath=true ‑Dio.netty.noUnsafe=true ‑Dio.netty.noKeySetOptimization=true ‑Dio.netty.recycler.maxCapacityPerThread=0 ‑Dlog4j.shutdownHookEnabled=false ‑Dlog4j2.disable.jmx=true ‑Dlog4j.skipJansi=true ‑Des.path.home=/usr/share/elasticsearch ‑Des.path.conf=/config ‑cp /usr/share/elasticsearch/lib/* ‑p /var/run/elasticsearch.pid ‑Epath.logs=/logs ‑Epath.data=/data ", - "elastic"}, - {"gunicorn: master [mcnulty]", - "gunicorn"}, - {"java kafka.Kafka /usr/local/kafka/config/server.properties ‑Xmx4G ‑Xms4G ‑server ‑XX:+UseCompressedOops ‑XX:PermSize=48m ‑XX:MaxPermSize=48m ‑XX:+UseG1GC ‑XX:MaxGCPauseMillis=20 ‑XX:InitiatingHeapOccupancyPercent=35 ‑Djava.awt.headless=true ‑Xloggc:/mnt/log/kafka/kafkaServer-gc.log ‑verbose:gc ‑XX:+PrintGCDetails ‑XX:+PrintGCDateStamps ‑XX:+PrintGCTimeStamps ‑Dcom.sun.management.jmxremote ‑Dcom.sun.management.jmxremote.authenticate=false ‑Dcom.sun.management.jmxremote.ssl=false ‑Dcom.sun.management.jmxremote.port=9999", - "kafka"}, - {"haproxy ‑p /run/haproxy.pid ‑db ‑f /usr/local/etc/haproxy/haproxy.cfg ‑Ds", - "haproxy"}, - {"mongod ‑-config /config/mongodb.conf", - "mongo"}, - {"java -Xmx4000m -Xms4000m -XX:ReservedCodeCacheSize=256m -port 9999 kafka.Kafka", - "kafka"}, - {"java -Xmx4000m -Xms4000m -XX:ReservedCodeCacheSize=256m -port 9999 kafka.Kafka", - "kafka"}, - {"/usr/local/bin/consul agent -config-dir /etc/consul.d", - "consul"}, - {"/usr/bin/python /usr/local/bin/supervisord -c /etc/supervisord.conf", - "supervisord"}, - {"/usr/sbin/pgbouncer -d /etc/pgbouncer/pgbouncer.ini", - "pgbouncer"}, - {"varnishd -j unix,user=vcache -F -a :6081 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m", - "varnish"}, - {"rethinkdb --daemon --config-file /etc/rethinkdb/instances.d/instance1.conf --runuser rethinkdb --rungroup rethinkdb --pid-file /var/run/rethinkdb/instance1/pid_file --directory /var/lib/rethinkdb/instance1/data", - "rethinkdb"}, - } - - for _, c := range cases { - matched := testMatcher.Match(c.cmdline) - assertIntegration(t, c.integration, matched.Name) - } -} - -func TestOverlappingSignatures(t *testing.T) { - cases := []struct { - cmdline string - integration string - }{ - {"java org.elasticsearch.bootstrap.Elasticsearch -p=mypath", - "elastic"}, - {"java org.elasticsearch.bootstrap.Elasticsearch", - "elastic"}, - {"java ***** kafka.kafka", - "kafka"}, - } - - for _, c := range cases { - matched := testMatcher.Match(c.cmdline) - assertIntegration(t, c.integration, matched.Name) - } -} - -// Test that the signatures defined in the default catalog are matches the integrations of the catalog -func TestDefaultCatalogOnGraph(t *testing.T) { - for _, integration := range DefaultCatalog { - for _, cmd := range integration.Signatures { - matched := testMatcher.Match(cmd) - assertIntegration(t, integration.Name, matched.Name) - } - } -} diff --git a/pkg/procmatch/readme.md b/pkg/procmatch/readme.md deleted file mode 100644 index aec78305745d07..00000000000000 --- a/pkg/procmatch/readme.md +++ /dev/null @@ -1,63 +0,0 @@ -# procmatch - -Procmatch is a library that provides a way to extract datadog-integrations from command lines by using a catalog. - -## Getting Started - -### Installing - -To install the package: `go get -u github.com/DataDog/datadog-agent/pkg/procmatch` - -Usage: - -```golang -package main - -import ( - "fmt" - - "github.com/DataDog/datadog-agent/pkg/procmatch" -) - -func main() { - matcher, err := procmatch.NewDefault() - if err != nil { - // Handle the error - } - - cmd := "java org.elasticsearch.bootstrap.elasticsearch" - fmt.Printf("Integration: %s\n", matcher.Match(cmd).Name) - // Outputs: - // Integration: elastic -} -``` - -The default catalog is available [here](/default_catalog.go) - -## Adding a new integration's signature - -To add a new integration signature, you will first have to add it inside its `manifest.json` file in the [datadog integration-core repo](https://github.com/DataDog/integrations-core) under the `process_signatures` field. - -After that create a PR on the datadog integration-core repo to commit your change. - -Then you can regenerate the default catalog to get the new signature here (see section below to regenerate the catalog) - -For testing purposes you can also modify the generated file `/default_catalog.go`. - -## Generate a new catalog - -The catalog is generated [here](/gen/generate_catalog.go), you will first need to clone the [datadog integration-core repo](https://github.com/DataDog/integrations-core). - -Then you can run `INTEGRATIONS_CORE_DIR= go generate ./...` or `INTEGRATIONS_CORE_DIR= go generate ./pkg/procmatch` if you're at the repo root. - -The generation script reads process signatures from the `manifest.json` files. - -## Adding tests for an integration - -To add a new test for a given integration you can add an entry inside the test cases in `TestMatchIntegration` under `graph_matcher_test.go`, it will try to match an integration on your provided command line by using the default catalog. - -## Running the tests - -To run the tests simply do: `go test ./...` - -There are also benchmarks included, to run them you can do: `go test -bench=.` diff --git a/pkg/procmatch/signature.go b/pkg/procmatch/signature.go deleted file mode 100644 index 776ab83401ff2e..00000000000000 --- a/pkg/procmatch/signature.go +++ /dev/null @@ -1,37 +0,0 @@ -package procmatch - -import ( - "sort" - "strings" -) - -// getSignatures retrieves the signatures structured -func (i IntegrationEntry) getSignatures() []signature { - sigs := []signature{} - - for _, rawSig := range i.Signatures { - sigs = append(sigs, signature{ - integration: Integration{DisplayName: i.DisplayName, MetricPrefix: i.MetricPrefix, Name: i.Name}, - words: strings.FieldsFunc(strings.ToLower(rawSig), splitCmdline), - }) - } - - return sigs -} - -// buildSignatures builds the signatures from the given integration catalog and returns them sorted by length of words -func buildSignatures(integs IntegrationCatalog) []signature { - signatures := []signature{} - - for _, integ := range integs { - signatures = append(signatures, integ.getSignatures()...) - } - - // We must match the more specific signatures first. So if a process cmdline matches more than - // one integration, we'll return the most specific one i.e. the one with more words - sort.SliceStable(signatures, func(i, j int) bool { - return len(signatures[i].words) > len(signatures[j].words) - }) - - return signatures -}