elastic-apm 3.7.0 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- }