sentry-ruby 5.9.0 → 5.16.1
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.
- checksums.yaml +4 -4
- data/Gemfile +2 -10
- data/README.md +9 -9
- data/lib/sentry/background_worker.rb +8 -1
- data/lib/sentry/backpressure_monitor.rb +75 -0
- data/lib/sentry/breadcrumb.rb +8 -2
- data/lib/sentry/check_in_event.rb +60 -0
- data/lib/sentry/client.rb +48 -10
- data/lib/sentry/configuration.rb +89 -17
- data/lib/sentry/cron/configuration.rb +23 -0
- data/lib/sentry/cron/monitor_check_ins.rb +75 -0
- data/lib/sentry/cron/monitor_config.rb +53 -0
- data/lib/sentry/cron/monitor_schedule.rb +42 -0
- data/lib/sentry/envelope.rb +1 -1
- data/lib/sentry/event.rb +6 -28
- data/lib/sentry/hub.rb +74 -2
- data/lib/sentry/integrable.rb +6 -0
- data/lib/sentry/interfaces/single_exception.rb +5 -3
- data/lib/sentry/net/http.rb +26 -20
- data/lib/sentry/profiler.rb +18 -7
- data/lib/sentry/propagation_context.rb +134 -0
- data/lib/sentry/puma.rb +11 -4
- data/lib/sentry/rack/capture_exceptions.rb +1 -4
- data/lib/sentry/rake.rb +0 -13
- data/lib/sentry/redis.rb +9 -3
- data/lib/sentry/release_detector.rb +1 -1
- data/lib/sentry/scope.rb +29 -13
- data/lib/sentry/span.rb +39 -2
- data/lib/sentry/test_helper.rb +18 -12
- data/lib/sentry/transaction.rb +18 -19
- data/lib/sentry/transaction_event.rb +0 -3
- data/lib/sentry/transport/configuration.rb +74 -1
- data/lib/sentry/transport/http_transport.rb +68 -37
- data/lib/sentry/transport/spotlight_transport.rb +50 -0
- data/lib/sentry/transport.rb +21 -17
- data/lib/sentry/utils/argument_checking_helper.rb +9 -3
- data/lib/sentry/version.rb +1 -1
- data/lib/sentry-ruby.rb +83 -25
- metadata +10 -3
- data/CODE_OF_CONDUCT.md +0 -74
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "net/http"
|
4
|
+
require "zlib"
|
5
|
+
|
6
|
+
module Sentry
|
7
|
+
# Designed to just report events to Spotlight in development.
|
8
|
+
class SpotlightTransport < HTTPTransport
|
9
|
+
DEFAULT_SIDECAR_URL = "http://localhost:8969/stream"
|
10
|
+
MAX_FAILED_REQUESTS = 3
|
11
|
+
|
12
|
+
def initialize(configuration)
|
13
|
+
super
|
14
|
+
@sidecar_url = configuration.spotlight.is_a?(String) ? configuration.spotlight : DEFAULT_SIDECAR_URL
|
15
|
+
@failed = 0
|
16
|
+
@logged = false
|
17
|
+
|
18
|
+
log_debug("[Spotlight] initialized for url #{@sidecar_url}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def endpoint
|
22
|
+
"/stream"
|
23
|
+
end
|
24
|
+
|
25
|
+
def send_data(data)
|
26
|
+
if @failed >= MAX_FAILED_REQUESTS
|
27
|
+
unless @logged
|
28
|
+
log_debug("[Spotlight] disabling because of too many request failures")
|
29
|
+
@logged = true
|
30
|
+
end
|
31
|
+
|
32
|
+
return
|
33
|
+
end
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_error
|
39
|
+
@failed += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
# Similar to HTTPTransport connection, but does not support Proxy and SSL
|
43
|
+
def conn
|
44
|
+
sidecar = URI(@sidecar_url)
|
45
|
+
connection = ::Net::HTTP.new(sidecar.hostname, sidecar.port, nil)
|
46
|
+
connection.use_ssl = false
|
47
|
+
connection
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/sentry/transport.rb
CHANGED
@@ -18,7 +18,9 @@ module Sentry
|
|
18
18
|
:network_error,
|
19
19
|
:sample_rate,
|
20
20
|
:before_send,
|
21
|
-
:event_processor
|
21
|
+
:event_processor,
|
22
|
+
:insufficient_data,
|
23
|
+
:backpressure
|
22
24
|
]
|
23
25
|
|
24
26
|
include LoggingHelper
|
@@ -73,7 +75,7 @@ module Sentry
|
|
73
75
|
result, oversized = item.serialize
|
74
76
|
|
75
77
|
if oversized
|
76
|
-
|
78
|
+
log_debug("Envelope item [#{item.type}] is still oversized after size reduction: {#{item.size_breakdown}}")
|
77
79
|
|
78
80
|
next
|
79
81
|
end
|
@@ -118,16 +120,8 @@ module Sentry
|
|
118
120
|
!!delay && delay > Time.now
|
119
121
|
end
|
120
122
|
|
121
|
-
def
|
122
|
-
|
123
|
-
fields = {
|
124
|
-
'sentry_version' => PROTOCOL_VERSION,
|
125
|
-
'sentry_client' => USER_AGENT,
|
126
|
-
'sentry_timestamp' => now,
|
127
|
-
'sentry_key' => @dsn.public_key
|
128
|
-
}
|
129
|
-
fields['sentry_secret'] = @dsn.secret_key if @dsn.secret_key
|
130
|
-
'Sentry ' + fields.map { |key, value| "#{key}=#{value}" }.join(', ')
|
123
|
+
def any_rate_limited?
|
124
|
+
@rate_limits.values.any? { |t| t && t > Time.now }
|
131
125
|
end
|
132
126
|
|
133
127
|
def envelope_from_event(event)
|
@@ -143,7 +137,7 @@ module Sentry
|
|
143
137
|
sent_at: Sentry.utc_now.iso8601
|
144
138
|
}
|
145
139
|
|
146
|
-
if event.is_a?(
|
140
|
+
if event.is_a?(Event) && event.dynamic_sampling_context
|
147
141
|
envelope_headers[:trace] = event.dynamic_sampling_context
|
148
142
|
end
|
149
143
|
|
@@ -174,18 +168,27 @@ module Sentry
|
|
174
168
|
@discarded_events[[reason, item_type]] += 1
|
175
169
|
end
|
176
170
|
|
171
|
+
def flush
|
172
|
+
client_report_headers, client_report_payload = fetch_pending_client_report(force: true)
|
173
|
+
return unless client_report_headers
|
174
|
+
|
175
|
+
envelope = Envelope.new
|
176
|
+
envelope.add_item(client_report_headers, client_report_payload)
|
177
|
+
send_envelope(envelope)
|
178
|
+
end
|
179
|
+
|
177
180
|
private
|
178
181
|
|
179
|
-
def fetch_pending_client_report
|
182
|
+
def fetch_pending_client_report(force: false)
|
180
183
|
return nil unless @send_client_reports
|
181
|
-
return nil if @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
184
|
+
return nil if !force && @last_client_report_sent > Time.now - CLIENT_REPORT_INTERVAL
|
182
185
|
return nil if @discarded_events.empty?
|
183
186
|
|
184
187
|
discarded_events_hash = @discarded_events.map do |key, val|
|
185
188
|
reason, type = key
|
186
189
|
|
187
190
|
# 'event' has to be mapped to 'error'
|
188
|
-
category = type == '
|
191
|
+
category = type == 'event' ? 'error' : type
|
189
192
|
|
190
193
|
{ reason: reason, category: category, quantity: val }
|
191
194
|
end
|
@@ -205,7 +208,7 @@ module Sentry
|
|
205
208
|
def reject_rate_limited_items(envelope)
|
206
209
|
envelope.items.reject! do |item|
|
207
210
|
if is_rate_limited?(item.type)
|
208
|
-
|
211
|
+
log_debug("[Transport] Envelope item [#{item.type}] not sent: rate limiting")
|
209
212
|
record_lost_event(:ratelimit_backoff, item.type)
|
210
213
|
|
211
214
|
true
|
@@ -219,3 +222,4 @@ end
|
|
219
222
|
|
220
223
|
require "sentry/transport/dummy_transport"
|
221
224
|
require "sentry/transport/http_transport"
|
225
|
+
require "sentry/transport/spotlight_transport"
|
@@ -4,9 +4,15 @@ module Sentry
|
|
4
4
|
module ArgumentCheckingHelper
|
5
5
|
private
|
6
6
|
|
7
|
-
def check_argument_type!(argument,
|
8
|
-
unless argument.is_a?(
|
9
|
-
raise ArgumentError, "expect the argument to be a #{
|
7
|
+
def check_argument_type!(argument, *expected_types)
|
8
|
+
unless expected_types.any? { |t| argument.is_a?(t) }
|
9
|
+
raise ArgumentError, "expect the argument to be a #{expected_types.join(' or ')}, got #{argument.class} (#{argument.inspect})"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def check_argument_includes!(argument, values)
|
14
|
+
unless values.include?(argument)
|
15
|
+
raise ArgumentError, "expect the argument to be one of #{values.map(&:inspect).join(' or ')}, got #{argument.inspect}"
|
10
16
|
end
|
11
17
|
end
|
12
18
|
end
|
data/lib/sentry/version.rb
CHANGED
data/lib/sentry-ruby.rb
CHANGED
@@ -15,11 +15,14 @@ require "sentry/logger"
|
|
15
15
|
require "sentry/event"
|
16
16
|
require "sentry/error_event"
|
17
17
|
require "sentry/transaction_event"
|
18
|
+
require "sentry/check_in_event"
|
18
19
|
require "sentry/span"
|
19
20
|
require "sentry/transaction"
|
20
21
|
require "sentry/hub"
|
21
22
|
require "sentry/background_worker"
|
22
23
|
require "sentry/session_flusher"
|
24
|
+
require "sentry/backpressure_monitor"
|
25
|
+
require "sentry/cron/monitor_check_ins"
|
23
26
|
|
24
27
|
[
|
25
28
|
"sentry/rake",
|
@@ -63,25 +66,29 @@ module Sentry
|
|
63
66
|
end
|
64
67
|
|
65
68
|
# @!attribute [rw] background_worker
|
66
|
-
# @return [BackgroundWorker
|
69
|
+
# @return [BackgroundWorker]
|
67
70
|
attr_accessor :background_worker
|
68
71
|
|
69
72
|
# @!attribute [r] session_flusher
|
70
73
|
# @return [SessionFlusher, nil]
|
71
74
|
attr_reader :session_flusher
|
72
75
|
|
76
|
+
# @!attribute [r] backpressure_monitor
|
77
|
+
# @return [BackpressureMonitor, nil]
|
78
|
+
attr_reader :backpressure_monitor
|
79
|
+
|
73
80
|
##### Patch Registration #####
|
74
81
|
|
75
82
|
# @!visibility private
|
76
|
-
def register_patch(patch = nil, target = nil, &block)
|
83
|
+
def register_patch(key, patch = nil, target = nil, &block)
|
77
84
|
if patch && block
|
78
85
|
raise ArgumentError.new("Please provide either a patch and its target OR a block, but not both")
|
79
86
|
end
|
80
87
|
|
81
88
|
if block
|
82
|
-
registered_patches
|
89
|
+
registered_patches[key] = block
|
83
90
|
else
|
84
|
-
registered_patches
|
91
|
+
registered_patches[key] = proc do
|
85
92
|
target.send(:prepend, patch) unless target.ancestors.include?(patch)
|
86
93
|
end
|
87
94
|
end
|
@@ -89,14 +96,14 @@ module Sentry
|
|
89
96
|
|
90
97
|
# @!visibility private
|
91
98
|
def apply_patches(config)
|
92
|
-
registered_patches.each do |patch|
|
93
|
-
patch.call(config)
|
99
|
+
registered_patches.each do |key, patch|
|
100
|
+
patch.call(config) if config.enabled_patches.include?(key)
|
94
101
|
end
|
95
102
|
end
|
96
103
|
|
97
104
|
# @!visibility private
|
98
105
|
def registered_patches
|
99
|
-
@registered_patches ||=
|
106
|
+
@registered_patches ||= {}
|
100
107
|
end
|
101
108
|
|
102
109
|
##### Integrations #####
|
@@ -215,17 +222,9 @@ module Sentry
|
|
215
222
|
Thread.current.thread_variable_set(THREAD_LOCAL, hub)
|
216
223
|
@main_hub = hub
|
217
224
|
@background_worker = Sentry::BackgroundWorker.new(config)
|
218
|
-
|
219
|
-
@
|
220
|
-
|
221
|
-
else
|
222
|
-
nil
|
223
|
-
end
|
224
|
-
|
225
|
-
if config.include_local_variables
|
226
|
-
exception_locals_tp.enable
|
227
|
-
end
|
228
|
-
|
225
|
+
@session_flusher = config.auto_session_tracking ? Sentry::SessionFlusher.new(config, client) : nil
|
226
|
+
@backpressure_monitor = config.enable_backpressure_handling ? Sentry::BackpressureMonitor.new(config, client) : nil
|
227
|
+
exception_locals_tp.enable if config.include_local_variables
|
229
228
|
at_exit { close }
|
230
229
|
end
|
231
230
|
|
@@ -234,20 +233,27 @@ module Sentry
|
|
234
233
|
#
|
235
234
|
# @return [void]
|
236
235
|
def close
|
237
|
-
if @background_worker
|
238
|
-
@background_worker.shutdown
|
239
|
-
@background_worker = nil
|
240
|
-
end
|
241
|
-
|
242
236
|
if @session_flusher
|
237
|
+
@session_flusher.flush
|
243
238
|
@session_flusher.kill
|
244
239
|
@session_flusher = nil
|
245
240
|
end
|
246
241
|
|
247
|
-
if
|
248
|
-
|
242
|
+
if @backpressure_monitor
|
243
|
+
@backpressure_monitor.kill
|
244
|
+
@backpressure_monitor = nil
|
249
245
|
end
|
250
246
|
|
247
|
+
if client = get_current_client
|
248
|
+
client.transport.flush
|
249
|
+
|
250
|
+
if client.configuration.include_local_variables
|
251
|
+
exception_locals_tp.disable
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
@background_worker.shutdown
|
256
|
+
|
251
257
|
@main_hub = nil
|
252
258
|
Thread.current.thread_variable_set(THREAD_LOCAL, nil)
|
253
259
|
end
|
@@ -430,6 +436,22 @@ module Sentry
|
|
430
436
|
get_current_hub.capture_event(event)
|
431
437
|
end
|
432
438
|
|
439
|
+
# Captures a check-in and sends it to Sentry via the currently active hub.
|
440
|
+
#
|
441
|
+
# @param slug [String] identifier of this monitor
|
442
|
+
# @param status [Symbol] status of this check-in, one of {CheckInEvent::VALID_STATUSES}
|
443
|
+
#
|
444
|
+
# @param [Hash] options extra check-in options
|
445
|
+
# @option options [String] check_in_id for updating the status of an existing monitor
|
446
|
+
# @option options [Integer] duration seconds elapsed since this monitor started
|
447
|
+
# @option options [Cron::MonitorConfig] monitor_config configuration for this monitor
|
448
|
+
#
|
449
|
+
# @return [String, nil] The {CheckInEvent#check_in_id} to use for later updates on the same slug
|
450
|
+
def capture_check_in(slug, status, **options)
|
451
|
+
return unless initialized?
|
452
|
+
get_current_hub.capture_check_in(slug, status, **options)
|
453
|
+
end
|
454
|
+
|
433
455
|
# Takes or initializes a new Sentry::Transaction and makes a sampling decision for it.
|
434
456
|
#
|
435
457
|
# @return [Transaction, nil]
|
@@ -489,6 +511,42 @@ module Sentry
|
|
489
511
|
Scope.add_global_event_processor(&block)
|
490
512
|
end
|
491
513
|
|
514
|
+
# Returns the traceparent (sentry-trace) header for distributed tracing.
|
515
|
+
# Can be either from the currently active span or the propagation context.
|
516
|
+
#
|
517
|
+
# @return [String, nil]
|
518
|
+
def get_traceparent
|
519
|
+
return nil unless initialized?
|
520
|
+
get_current_hub.get_traceparent
|
521
|
+
end
|
522
|
+
|
523
|
+
# Returns the baggage header for distributed tracing.
|
524
|
+
# Can be either from the currently active span or the propagation context.
|
525
|
+
#
|
526
|
+
# @return [String, nil]
|
527
|
+
def get_baggage
|
528
|
+
return nil unless initialized?
|
529
|
+
get_current_hub.get_baggage
|
530
|
+
end
|
531
|
+
|
532
|
+
# Returns the a Hash containing sentry-trace and baggage.
|
533
|
+
# Can be either from the currently active span or the propagation context.
|
534
|
+
#
|
535
|
+
# @return [Hash, nil]
|
536
|
+
def get_trace_propagation_headers
|
537
|
+
return nil unless initialized?
|
538
|
+
get_current_hub.get_trace_propagation_headers
|
539
|
+
end
|
540
|
+
|
541
|
+
# Continue an incoming trace from a rack env like hash.
|
542
|
+
#
|
543
|
+
# @param env [Hash]
|
544
|
+
# @return [Transaction, nil]
|
545
|
+
def continue_trace(env, **options)
|
546
|
+
return nil unless initialized?
|
547
|
+
get_current_hub.continue_trace(env, **options)
|
548
|
+
end
|
549
|
+
|
492
550
|
##### Helpers #####
|
493
551
|
|
494
552
|
# @!visibility private
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentry-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sentry Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -42,7 +42,6 @@ files:
|
|
42
42
|
- ".rspec"
|
43
43
|
- ".yardopts"
|
44
44
|
- CHANGELOG.md
|
45
|
-
- CODE_OF_CONDUCT.md
|
46
45
|
- Gemfile
|
47
46
|
- LICENSE.txt
|
48
47
|
- Makefile
|
@@ -52,15 +51,21 @@ files:
|
|
52
51
|
- bin/setup
|
53
52
|
- lib/sentry-ruby.rb
|
54
53
|
- lib/sentry/background_worker.rb
|
54
|
+
- lib/sentry/backpressure_monitor.rb
|
55
55
|
- lib/sentry/backtrace.rb
|
56
56
|
- lib/sentry/baggage.rb
|
57
57
|
- lib/sentry/breadcrumb.rb
|
58
58
|
- lib/sentry/breadcrumb/sentry_logger.rb
|
59
59
|
- lib/sentry/breadcrumb_buffer.rb
|
60
|
+
- lib/sentry/check_in_event.rb
|
60
61
|
- lib/sentry/client.rb
|
61
62
|
- lib/sentry/configuration.rb
|
62
63
|
- lib/sentry/core_ext/object/deep_dup.rb
|
63
64
|
- lib/sentry/core_ext/object/duplicable.rb
|
65
|
+
- lib/sentry/cron/configuration.rb
|
66
|
+
- lib/sentry/cron/monitor_check_ins.rb
|
67
|
+
- lib/sentry/cron/monitor_config.rb
|
68
|
+
- lib/sentry/cron/monitor_schedule.rb
|
64
69
|
- lib/sentry/dsn.rb
|
65
70
|
- lib/sentry/envelope.rb
|
66
71
|
- lib/sentry/error_event.rb
|
@@ -79,6 +84,7 @@ files:
|
|
79
84
|
- lib/sentry/logger.rb
|
80
85
|
- lib/sentry/net/http.rb
|
81
86
|
- lib/sentry/profiler.rb
|
87
|
+
- lib/sentry/propagation_context.rb
|
82
88
|
- lib/sentry/puma.rb
|
83
89
|
- lib/sentry/rack.rb
|
84
90
|
- lib/sentry/rack/capture_exceptions.rb
|
@@ -96,6 +102,7 @@ files:
|
|
96
102
|
- lib/sentry/transport/configuration.rb
|
97
103
|
- lib/sentry/transport/dummy_transport.rb
|
98
104
|
- lib/sentry/transport/http_transport.rb
|
105
|
+
- lib/sentry/transport/spotlight_transport.rb
|
99
106
|
- lib/sentry/utils/argument_checking_helper.rb
|
100
107
|
- lib/sentry/utils/custom_inspection.rb
|
101
108
|
- lib/sentry/utils/encoding_helper.rb
|
data/CODE_OF_CONDUCT.md
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
2
|
-
|
3
|
-
## Our Pledge
|
4
|
-
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
-
orientation.
|
11
|
-
|
12
|
-
## Our Standards
|
13
|
-
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
15
|
-
include:
|
16
|
-
|
17
|
-
* Using welcoming and inclusive language
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
19
|
-
* Gracefully accepting constructive criticism
|
20
|
-
* Focusing on what is best for the community
|
21
|
-
* Showing empathy towards other community members
|
22
|
-
|
23
|
-
Examples of unacceptable behavior by participants include:
|
24
|
-
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
-
advances
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
-
* Public or private harassment
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
30
|
-
address, without explicit permission
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
-
professional setting
|
33
|
-
|
34
|
-
## Our Responsibilities
|
35
|
-
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
38
|
-
response to any instances of unacceptable behavior.
|
39
|
-
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
-
threatening, offensive, or harmful.
|
45
|
-
|
46
|
-
## Scope
|
47
|
-
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
-
when an individual is representing the project or its community. Examples of
|
50
|
-
representing a project or community include using an official project e-mail
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
53
|
-
further defined and clarified by project maintainers.
|
54
|
-
|
55
|
-
## Enforcement
|
56
|
-
|
57
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at stan001212@gmail.com. All
|
59
|
-
complaints will be reviewed and investigated and will result in a response that
|
60
|
-
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
-
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
-
Further details of specific enforcement policies may be posted separately.
|
63
|
-
|
64
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
-
faith may face temporary or permanent repercussions as determined by other
|
66
|
-
members of the project's leadership.
|
67
|
-
|
68
|
-
## Attribution
|
69
|
-
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
-
available at [https://contributor-covenant.org/version/1/4][version]
|
72
|
-
|
73
|
-
[homepage]: https://contributor-covenant.org
|
74
|
-
[version]: https://contributor-covenant.org/version/1/4/
|