elastic-apm 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,75 +17,31 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
+ require 'elastic_apm/transport/filters/hash_sanitizer'
21
+
20
22
  module ElasticAPM
21
23
  module Transport
22
24
  module Filters
23
25
  # @api private
24
26
  class SecretsFilter
25
- FILTERED = '[FILTERED]'
26
-
27
- KEY_FILTERS = [
28
- /passw(or)?d/i,
29
- /auth/i,
30
- /^pw$/,
31
- /secret/i,
32
- /token/i,
33
- /api[-._]?key/i,
34
- /session[-._]?id/i,
35
- /(set[-_])?cookie/i
36
- ].freeze
37
-
38
- VALUE_FILTERS = [
39
- # (probably) credit card number
40
- /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/
41
- ].freeze
42
-
43
27
  def initialize(config)
44
28
  @config = config
45
- @key_filters =
46
- KEY_FILTERS +
47
- config.custom_key_filters +
48
- config.sanitize_field_names
29
+ @sanitizer = HashSanitizer.new
30
+ @sanitizer.key_filters += config.custom_key_filters +
31
+ config.sanitize_field_names
49
32
  end
50
33
 
51
34
  def call(payload)
52
- strip_from! payload.dig(:transaction, :context, :request, :headers)
53
- strip_from! payload.dig(:transaction, :context, :request, :env)
54
- strip_from! payload.dig(:transaction, :context, :request, :cookies)
55
- strip_from! payload.dig(:transaction, :context, :response, :headers)
56
- strip_from! payload.dig(:error, :context, :request, :headers)
57
- strip_from! payload.dig(:error, :context, :response, :headers)
58
- strip_from! payload.dig(:transaction, :context, :request, :body)
35
+ @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :headers)
36
+ @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :env)
37
+ @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :cookies)
38
+ @sanitizer.strip_from! payload.dig(:transaction, :context, :response, :headers)
39
+ @sanitizer.strip_from! payload.dig(:error, :context, :request, :headers)
40
+ @sanitizer.strip_from! payload.dig(:error, :context, :response, :headers)
41
+ @sanitizer.strip_from! payload.dig(:transaction, :context, :request, :body)
59
42
 
60
43
  payload
61
44
  end
62
-
63
- def strip_from!(obj)
64
- return unless obj&.is_a?(Hash)
65
-
66
- obj.each do |k, v|
67
- if filter_key?(k)
68
- next obj[k] = FILTERED
69
- end
70
-
71
- case v
72
- when Hash
73
- strip_from!(v)
74
- when String
75
- if filter_value?(v)
76
- obj[k] = FILTERED
77
- end
78
- end
79
- end
80
- end
81
-
82
- def filter_key?(key)
83
- @key_filters.any? { |regex| regex.match(key) }
84
- end
85
-
86
- def filter_value?(value)
87
- VALUE_FILTERS.any? { |regex| regex.match(value) }
88
- end
89
45
  end
90
46
  end
91
47
  end
@@ -36,27 +36,34 @@ module ElasticAPM
36
36
  private
37
37
 
38
38
  def build_service(service)
39
- {
40
- name: keyword_field(service.name),
41
- environment: keyword_field(service.environment),
42
- version: keyword_field(service.version),
43
- agent: {
44
- name: keyword_field(service.agent.name),
45
- version: keyword_field(service.agent.version)
46
- },
47
- framework: {
48
- name: keyword_field(service.framework.name),
49
- version: keyword_field(service.framework.version)
50
- },
51
- language: {
52
- name: keyword_field(service.language.name),
53
- version: keyword_field(service.language.version)
54
- },
55
- runtime: {
56
- name: keyword_field(service.runtime.name),
57
- version: keyword_field(service.runtime.version)
39
+ base =
40
+ {
41
+ name: keyword_field(service.name),
42
+ environment: keyword_field(service.environment),
43
+ version: keyword_field(service.version),
44
+ agent: {
45
+ name: keyword_field(service.agent.name),
46
+ version: keyword_field(service.agent.version)
47
+ },
48
+ framework: {
49
+ name: keyword_field(service.framework.name),
50
+ version: keyword_field(service.framework.version)
51
+ },
52
+ language: {
53
+ name: keyword_field(service.language.name),
54
+ version: keyword_field(service.language.version)
55
+ },
56
+ runtime: {
57
+ name: keyword_field(service.runtime.name),
58
+ version: keyword_field(service.runtime.version)
59
+ }
58
60
  }
59
- }
61
+
62
+ if node_name = service.node_name
63
+ base[:node] = { name: keyword_field(node_name) }
64
+ end
65
+
66
+ base
60
67
  end
61
68
 
62
69
  def build_process(process)
@@ -18,5 +18,5 @@
18
18
  # frozen_string_literal: true
19
19
 
20
20
  module ElasticAPM
21
- VERSION = '3.7.0'
21
+ VERSION = '3.8.0'
22
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic-apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.7.0
4
+ version: 3.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Malmberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-15 00:00:00.000000000 Z
11
+ date: 2020-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -59,7 +59,6 @@ files:
59
59
  - ".ci/docker/jruby/README.md"
60
60
  - ".ci/docker/jruby/run.sh"
61
61
  - ".ci/docker/jruby/test.sh"
62
- - ".ci/downstreamTests.groovy"
63
62
  - ".ci/jobs/apm-agent-ruby-downstream.yml"
64
63
  - ".ci/jobs/apm-agent-ruby-linting-mbp.yml"
65
64
  - ".ci/jobs/apm-agent-ruby-mbp.yml"
@@ -220,6 +219,7 @@ files:
220
219
  - lib/elastic_apm/transport/connection/http.rb
221
220
  - lib/elastic_apm/transport/connection/proxy_pipe.rb
222
221
  - lib/elastic_apm/transport/filters.rb
222
+ - lib/elastic_apm/transport/filters/hash_sanitizer.rb
223
223
  - lib/elastic_apm/transport/filters/secrets_filter.rb
224
224
  - lib/elastic_apm/transport/headers.rb
225
225
  - lib/elastic_apm/transport/serializers.rb
@@ -1,192 +0,0 @@
1
- #!/usr/bin/env groovy
2
- @Library('apm@current') _
3
-
4
- import co.elastic.matrix.*
5
- import groovy.transform.Field
6
-
7
- /**
8
- This is the parallel tasks generator,
9
- it is need as field to store the results of the tests.
10
- */
11
- @Field def rubyTasksGen
12
-
13
- pipeline {
14
- agent { label 'linux && immutable' }
15
- environment {
16
- REPO="git@github.com:elastic/apm-agent-ruby.git"
17
- BASE_DIR="src/github.com/elastic/apm-agent-ruby"
18
- PIPELINE_LOG_LEVEL='INFO'
19
- NOTIFY_TO = credentials('notify-to')
20
- JOB_GCS_BUCKET = credentials('gcs-bucket')
21
- JOB_GIT_CREDENTIALS = "f6c7695a-671e-4f4f-a331-acdce44ff9ba"
22
- DOCKER_REGISTRY = 'docker.elastic.co'
23
- DOCKER_SECRET = 'secret/apm-team/ci/docker-registry/prod'
24
- CODECOV_SECRET = 'secret/apm-team/ci/apm-agent-ruby-codecov'
25
- }
26
- options {
27
- timeout(time: 2, unit: 'HOURS')
28
- buildDiscarder(logRotator(numToKeepStr: '300', artifactNumToKeepStr: '20', daysToKeepStr: '30'))
29
- timestamps()
30
- ansiColor('xterm')
31
- disableResume()
32
- durabilityHint('PERFORMANCE_OPTIMIZED')
33
- rateLimitBuilds(throttle: [count: 60, durationName: 'hour', userBoost: true])
34
- quietPeriod(10)
35
- }
36
- parameters {
37
- string(name: 'RUBY_VERSION', defaultValue: "ruby:2.6", description: "Ruby version to test")
38
- string(name: 'BRANCH_SPECIFIER', defaultValue: "master", description: "Git branch/tag to use")
39
- string(name: 'MERGE_TARGET', defaultValue: "master", description: "Git branch/tag where to merge this code")
40
- }
41
- stages {
42
- /**
43
- Checkout the code and stash it, to use it on other stages.
44
- */
45
- stage('Checkout') {
46
- options { skipDefaultCheckout() }
47
- when {
48
- beforeAgent true
49
- not {
50
- tag pattern: 'v\\d+.*', comparator: "REGEXP"
51
- }
52
- }
53
- steps {
54
- deleteDir()
55
- gitCheckout(basedir: "${BASE_DIR}",
56
- branch: "${params.BRANCH_SPECIFIER}",
57
- repo: "${REPO}",
58
- credentialsId: "${JOB_GIT_CREDENTIALS}",
59
- mergeTarget: "${params.MERGE_TARGET}")
60
- stash allowEmpty: true, name: 'source', useDefaultExcludes: false
61
- }
62
- }
63
- stage('Checkout tag') {
64
- options { skipDefaultCheckout() }
65
- when {
66
- beforeAgent true
67
- tag pattern: 'v\\d+.*', comparator: "REGEXP"
68
- }
69
- steps {
70
- deleteDir()
71
- gitCheckout(basedir: "${BASE_DIR}")
72
- stash allowEmpty: true, name: 'source', useDefaultExcludes: false
73
- }
74
- }
75
- stage('Test') {
76
- options { skipDefaultCheckout() }
77
- steps {
78
- runTests('.ci/.jenkins_framework.yml')
79
- }
80
- }
81
- stage('Master Test') {
82
- options { skipDefaultCheckout() }
83
- steps {
84
- catchError(buildResult: 'SUCCESS', stageResult: 'UNSTABLE', message: "The tests for the master framework have failed. Let's warn instead.") {
85
- runTests('.ci/.jenkins_master_framework.yml')
86
- }
87
- }
88
- }
89
- }
90
- post {
91
- cleanup {
92
- script{
93
- if(rubyTasksGen?.results){
94
- writeJSON(file: 'results.json', json: toJSON(rubyTasksGen.results), pretty: 2)
95
- def mapResults = ["Ruby": rubyTasksGen.results]
96
- def processor = new ResultsProcessor()
97
- processor.processResults(mapResults)
98
- archiveArtifacts allowEmptyArchive: true, artifacts: 'results.json,results.html', defaultExcludes: false
99
- catchError(buildResult: 'SUCCESS') {
100
- def datafile = readFile(file: "results.json")
101
- def json = getVaultSecret(secret: 'secret/apm-team/ci/jenkins-stats-cloud')
102
- sendDataToElasticsearch(es: json.data.url, data: datafile, restCall: '/jenkins-builds-ruby-test-results/_doc/')
103
- }
104
- }
105
- }
106
- notifyBuildResult(prComment: false)
107
- }
108
- }
109
- }
110
-
111
- /**
112
- Parallel task generator for the integration tests.
113
- */
114
- class RubyParallelTaskGenerator extends DefaultParallelTaskGenerator {
115
-
116
- public RubyParallelTaskGenerator(Map params){
117
- super(params)
118
- }
119
-
120
- /**
121
- build a clousure that launch and agent and execute the corresponding test script,
122
- then store the results.
123
- */
124
- public Closure generateStep(x, y){
125
- return {
126
- steps.sleep steps.randomNumber(min:10, max: 30)
127
- steps.node('linux && immutable'){
128
- // Label is transformed to avoid using the internal docker registry in the x coordinate
129
- // TODO: def label = "${tag}:${x?.drop(x?.lastIndexOf('/')+1)}#${y}"
130
- def label = "${tag}:${x}#${y}"
131
- try {
132
- steps.runScript(label: label, ruby: x, framework: y)
133
- saveResult(x, y, 1)
134
- } catch(e){
135
- saveResult(x, y, 0)
136
- steps.error("${label} tests failed : ${e.toString()}\n")
137
- } finally {
138
- steps.junit(allowEmptyResults: true,
139
- keepLongStdio: true,
140
- testResults: "**/spec/junit-reports/**/ruby-agent-junit.xml")
141
- }
142
- }
143
- }
144
- }
145
- }
146
- /**
147
- Run tests for a Ruby version and framework version.
148
- */
149
- def runScript(Map params = [:]){
150
- def label = params.label
151
- def ruby = params.ruby
152
- def framework = params.framework
153
- log(level: 'INFO', text: "${label}")
154
- env.HOME = "${env.WORKSPACE}"
155
- env.PATH = "${env.PATH}:${env.WORKSPACE}/bin"
156
- deleteDir()
157
- unstash 'source'
158
- dir("${BASE_DIR}"){
159
- retry(2){
160
- sleep randomNumber(min:10, max: 30)
161
- dockerLogin(secret: "${DOCKER_SECRET}", registry: "${DOCKER_REGISTRY}")
162
- sh("./spec/scripts/spec.sh ${ruby} ${framework}")
163
- script{
164
- archiveArtifacts(artifacts: "coverage/matrix_results/", defaultExcludes: false)
165
- }
166
- }
167
- }
168
- }
169
-
170
- /**
171
- Run all the tests for the given ruby version and file with the frameworks to test
172
- */
173
- def runTests(frameworkFile) {
174
- deleteDir()
175
- unstash "source"
176
- dir("${BASE_DIR}"){
177
- script {
178
- rubyTasksGen = new RubyParallelTaskGenerator(
179
- xVersions: [ "${params.RUBY_VERSION}" ],
180
- xKey: 'RUBY_VERSION',
181
- yKey: 'FRAMEWORK',
182
- yFile: frameworkFile,
183
- exclusionFile: '.ci/.jenkins_exclude.yml',
184
- tag: 'Ruby',
185
- name: 'Ruby',
186
- steps: this
187
- )
188
- def mapParallelTasks = rubyTasksGen.generateParallelTests()
189
- parallel(mapParallelTasks)
190
- }
191
- }
192
- }