newrelic_rpm 6.13.1 → 6.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +55 -0
- data/lib/new_relic/agent/audit_logger.rb +10 -0
- data/lib/new_relic/agent/configuration/default_source.rb +15 -1
- data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +2 -2
- data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +4 -5
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +16 -37
- data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +3 -11
- data/lib/new_relic/agent/instrumentation/net.rb +66 -59
- data/lib/new_relic/agent/instrumentation/net_prepend.rb +72 -0
- data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rack.rb +8 -18
- data/lib/new_relic/agent/instrumentation/redis.rb +1 -1
- data/lib/new_relic/agent/method_tracer.rb +6 -16
- data/lib/new_relic/agent/new_relic_service.rb +1 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
- data/lib/new_relic/agent/stats_engine/gc_profiler.rb +1 -1
- data/lib/new_relic/agent/transaction/distributed_tracer.rb +12 -6
- data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -0
- data/lib/new_relic/constants.rb +4 -0
- data/lib/new_relic/environment_report.rb +7 -1
- data/lib/new_relic/supportability_helper.rb +1 -0
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +1 -1
- metadata +3 -27
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -31
- data/.github/ISSUE_TEMPLATE/config.yml +0 -5
- data/.github/ISSUE_TEMPLATE/feature_request.md +0 -24
- data/.github/actions/annotate/README.md +0 -79
- data/.github/actions/annotate/action.yml +0 -6
- data/.github/actions/annotate/dist/index.js +0 -433
- data/.github/actions/annotate/index.js +0 -25
- data/.github/actions/annotate/package-lock.json +0 -172
- data/.github/actions/annotate/package.json +0 -30
- data/.github/actions/annotate/pre-commit +0 -5
- data/.github/actions/build-ruby/README.md +0 -79
- data/.github/actions/build-ruby/action.yml +0 -15
- data/.github/actions/build-ruby/dist/index.js +0 -52683
- data/.github/actions/build-ruby/index.js +0 -514
- data/.github/actions/build-ruby/package-lock.json +0 -581
- data/.github/actions/build-ruby/package.json +0 -32
- data/.github/actions/build-ruby/pre-commit +0 -5
- data/.github/pull_request_template.md +0 -16
- data/.github/workflows/ci.yml +0 -212
- data/.github/workflows/pr_review_checklist.yml +0 -22
- data/.github/workflows/release.yml +0 -78
- data/.github/workflows/scripts/rubygems-authenticate.py +0 -13
- data/.github/workflows/scripts/rubygems-publish.rb +0 -32
- data/.github/workflows/snyk.yml +0 -27
- data/.github/workflows/stale.yml +0 -21
@@ -75,7 +75,7 @@ module NewRelic
|
|
75
75
|
# we don't expect this to be called more than once, but we're being
|
76
76
|
# defensive.
|
77
77
|
return if defined?(exception_object)
|
78
|
-
return unless defined?(::ActiveSupport)
|
78
|
+
return unless defined?(::ActiveSupport::VERSION)
|
79
79
|
if ::ActiveSupport::VERSION::STRING < "5.0.0"
|
80
80
|
# Earlier versions of Rails did not add the exception itself to the
|
81
81
|
# payload asssessible via :exception_object, so we create a stand-in
|
@@ -99,27 +99,17 @@ module NewRelic
|
|
99
99
|
else
|
100
100
|
run_without_newrelic(app, *args, **kwargs)
|
101
101
|
end
|
102
|
-
end
|
102
|
+
end
|
103
103
|
end
|
104
104
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
end
|
105
|
+
def use_with_newrelic(middleware_class, *args, &blk)
|
106
|
+
return if middleware_class.nil?
|
107
|
+
if ::NewRelic::Agent::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
|
108
|
+
wrapped_middleware_class = ::NewRelic::Agent::Instrumentation::MiddlewareProxy.for_class(middleware_class)
|
109
|
+
use_without_newrelic(wrapped_middleware_class, *args, &blk)
|
110
|
+
else
|
111
|
+
use_without_newrelic(middleware_class, *args, &blk)
|
113
112
|
end
|
114
|
-
else
|
115
|
-
def use_with_newrelic(middleware_class, *args, **kwargs, &blk)
|
116
|
-
if ::NewRelic::Agent::Instrumentation::RackHelpers.middleware_instrumentation_enabled?
|
117
|
-
wrapped_middleware_class = ::NewRelic::Agent::Instrumentation::MiddlewareProxy.for_class(middleware_class)
|
118
|
-
use_without_newrelic(wrapped_middleware_class, *args, **kwargs, &blk)
|
119
|
-
else
|
120
|
-
use_without_newrelic(middleware_class, *args, **kwargs, &blk)
|
121
|
-
end
|
122
|
-
end
|
123
113
|
end
|
124
114
|
|
125
115
|
# We patch this method for a reason that actually has nothing to do with
|
@@ -173,30 +173,20 @@ module NewRelic
|
|
173
173
|
# instrumentation into effectively one method call overhead
|
174
174
|
# when the agent is disabled
|
175
175
|
def assemble_code_header(method_name, metric_name_code, options)
|
176
|
-
header = "return #{_untraced_method_name(method_name, metric_name_code)}(
|
176
|
+
header = "return #{_untraced_method_name(method_name, metric_name_code)}(#{ARGS_FOR_RUBY_VERSION}) unless NewRelic::Agent.tl_is_execution_traced?\n"
|
177
177
|
header += options[:code_header].to_s
|
178
178
|
header
|
179
179
|
end
|
180
180
|
|
181
|
-
# Positional and Keyword arguments are separated beginning with Ruby 2.7
|
182
|
-
def arguments_for_ruby_version
|
183
|
-
if RUBY_VERSION < "2.7.0"
|
184
|
-
"(*args, &block)"
|
185
|
-
else
|
186
|
-
"(*args, **kwargs, &block)"
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
181
|
# returns an eval-able string that contains the traced
|
191
182
|
# method code used if the agent is not creating a scope for
|
192
183
|
# use in scoped metrics.
|
193
184
|
def method_without_push_scope(method_name, metric_name_code, options)
|
194
|
-
|
195
|
-
"def #{_traced_method_name(method_name, metric_name_code)}#{arguments}
|
185
|
+
"def #{_traced_method_name(method_name, metric_name_code)}(#{ARGS_FOR_RUBY_VERSION})
|
196
186
|
#{assemble_code_header(method_name, metric_name_code, options)}
|
197
187
|
t0 = Time.now
|
198
188
|
begin
|
199
|
-
#{_untraced_method_name(method_name, metric_name_code)}#{
|
189
|
+
#{_untraced_method_name(method_name, metric_name_code)}(#{ARGS_FOR_RUBY_VERSION})\n
|
200
190
|
ensure
|
201
191
|
duration = (Time.now - t0).to_f
|
202
192
|
NewRelic::Agent.record_metric(\"#{metric_name_code}\", duration)
|
@@ -208,12 +198,11 @@ module NewRelic
|
|
208
198
|
# returns an eval-able string that contains the tracing code
|
209
199
|
# for a fully traced metric including scoping
|
210
200
|
def method_with_push_scope(method_name, metric_name_code, options)
|
211
|
-
|
212
|
-
"def #{_traced_method_name(method_name, metric_name_code)}#{arguments}
|
201
|
+
"def #{_traced_method_name(method_name, metric_name_code)}(#{ARGS_FOR_RUBY_VERSION})
|
213
202
|
#{options[:code_header]}
|
214
203
|
result = ::NewRelic::Agent::MethodTracerHelpers.trace_execution_scoped(\"#{metric_name_code}\",
|
215
204
|
:metric => #{options[:metric]}) do
|
216
|
-
#{_untraced_method_name(method_name, metric_name_code)}#{
|
205
|
+
#{_untraced_method_name(method_name, metric_name_code)}(#{ARGS_FOR_RUBY_VERSION})
|
217
206
|
end
|
218
207
|
#{options[:code_footer]}
|
219
208
|
result
|
@@ -337,6 +326,7 @@ module NewRelic
|
|
337
326
|
class_eval traced_method, __FILE__, __LINE__
|
338
327
|
alias_method _untraced_method_name(method_name, metric_name_code), method_name
|
339
328
|
alias_method method_name, _traced_method_name(method_name, metric_name_code)
|
329
|
+
ruby2_keywords(_traced_method_name(method_name, metric_name_code)) if respond_to?(:ruby2_keywords, true)
|
340
330
|
send visibility, method_name
|
341
331
|
send visibility, _traced_method_name(method_name, metric_name_code)
|
342
332
|
::NewRelic::Agent.logger.debug("Traced method: class = #{derived_class_name},"+
|
@@ -526,6 +526,7 @@ module NewRelic
|
|
526
526
|
else
|
527
527
|
request = Net::HTTP::Post.new(opts[:uri], headers)
|
528
528
|
end
|
529
|
+
@audit_logger.log_request_headers(opts[:uri], headers)
|
529
530
|
request['user-agent'] = user_agent
|
530
531
|
request.content_type = "application/octet-stream"
|
531
532
|
request.body = opts[:data]
|
@@ -29,7 +29,7 @@ module NewRelic
|
|
29
29
|
end
|
30
30
|
elsif platform =~ /darwin9/ # 10.5
|
31
31
|
@sampler = ShellPS.new("ps -o rsz")
|
32
|
-
elsif platform =~ /
|
32
|
+
elsif platform =~ /darwin(1|2)\d+/ # >= 10.6
|
33
33
|
@sampler = ShellPS.new("ps -o rss")
|
34
34
|
elsif platform =~ /freebsd/
|
35
35
|
@sampler = ShellPS.new("ps -o rss")
|
@@ -99,7 +99,7 @@ module NewRelic
|
|
99
99
|
|
100
100
|
# When using GC::Profiler, it's important to periodically call
|
101
101
|
# GC::Profiler.clear in order to avoid unbounded growth in the number
|
102
|
-
# of GC
|
102
|
+
# of GC records that are stored. However, we actually do this
|
103
103
|
# internally within MonotonicGCProfiler on calls to #total_time_s,
|
104
104
|
# so the reset here is a no-op.
|
105
105
|
def reset; end
|
@@ -68,13 +68,19 @@ module NewRelic
|
|
68
68
|
payload
|
69
69
|
end
|
70
70
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
def log_request_headers headers, direction = "OUTGOING"
|
72
|
+
NewRelic::Agent.logger.debug "#{direction} REQUEST HEADERS: #{headers}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def insert_headers headers
|
76
|
+
insert_trace_context_header headers
|
77
|
+
insert_distributed_trace_header headers
|
78
|
+
insert_cross_app_header headers
|
79
|
+
log_request_headers headers
|
75
80
|
end
|
76
81
|
|
77
82
|
def consume_message_headers headers, tracer_state, transport_type
|
83
|
+
log_request_headers headers, "INCOMING"
|
78
84
|
consume_message_distributed_tracing_headers headers, transport_type
|
79
85
|
consume_message_cross_app_tracing_headers headers, tracer_state
|
80
86
|
consume_message_synthetics_headers headers
|
@@ -90,11 +96,11 @@ module NewRelic
|
|
90
96
|
end
|
91
97
|
end
|
92
98
|
|
93
|
-
def insert_distributed_trace_header
|
99
|
+
def insert_distributed_trace_header headers
|
94
100
|
return unless Agent.config[:'distributed_tracing.enabled']
|
95
101
|
return if Agent.config[:'exclude_newrelic_header']
|
96
102
|
payload = create_distributed_trace_payload
|
97
|
-
|
103
|
+
headers[NewRelic::NEWRELIC_KEY] = payload.http_safe if payload
|
98
104
|
end
|
99
105
|
|
100
106
|
def insert_cat_headers headers
|
@@ -93,6 +93,7 @@ module NewRelic
|
|
93
93
|
if headers && transaction && action == :produce && record_metrics?
|
94
94
|
transaction.distributed_tracer.insert_distributed_trace_header headers
|
95
95
|
transaction.distributed_tracer.insert_cat_headers headers
|
96
|
+
transaction.distributed_tracer.log_request_headers headers
|
96
97
|
end
|
97
98
|
rescue => e
|
98
99
|
NewRelic::Agent.logger.error "Error during message header processing", e
|
data/lib/new_relic/constants.rb
CHANGED
@@ -28,6 +28,10 @@ module NewRelic
|
|
28
28
|
TRACEPARENT_KEY = "traceparent"
|
29
29
|
TRACESTATE_KEY = "tracestate"
|
30
30
|
|
31
|
+
# Right now, old and new Rubies are the same. Intention is to use "(...)" for
|
32
|
+
# Ruby 2.7+ for argument delegation, but doing so is a breaking API change.
|
33
|
+
ARGS_FOR_RUBY_VERSION = RUBY_VERSION < "2.7.0" ? "*args, &block" : "*args, &block"
|
34
|
+
|
31
35
|
HTTP_TRACEPARENT_KEY = "HTTP_#{TRACEPARENT_KEY.upcase}"
|
32
36
|
HTTP_TRACESTATE_KEY = "HTTP_#{TRACESTATE_KEY.upcase}"
|
33
37
|
HTTP_NEWRELIC_KEY = "HTTP_#{NEWRELIC_KEY.upcase}"
|
@@ -71,7 +71,13 @@ module NewRelic
|
|
71
71
|
report_on('OS' ) { ::NewRelic::Agent::SystemInfo.ruby_os_identifier }
|
72
72
|
report_on('Database adapter' ) do
|
73
73
|
begin
|
74
|
-
ActiveRecord::Base.
|
74
|
+
if ::ActiveRecord::Base.respond_to?(:connection_db_config)
|
75
|
+
ActiveRecord::Base.configurations.configs_for(env_name: NewRelic::Control.instance.env, name: "primary")
|
76
|
+
.connection_db_config.configuration_hash['adapter']
|
77
|
+
else
|
78
|
+
ActiveRecord::Base.configurations.configs_for(env_name: NewRelic::Control.instance.env, spec_name: "primary").config['adapter']
|
79
|
+
end
|
80
|
+
|
75
81
|
rescue NoMethodError
|
76
82
|
ActiveRecord::Base.configurations[NewRelic::Control.instance.env]['adapter']
|
77
83
|
end
|
data/lib/new_relic/version.rb
CHANGED
data/newrelic_rpm.gemspec
CHANGED
@@ -39,7 +39,7 @@ EOS
|
|
39
39
|
"homepage_uri" => "https://newrelic.com/ruby",
|
40
40
|
}
|
41
41
|
|
42
|
-
file_list = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|infinite_tracing)/(?!agent_helper.rb)}) }
|
42
|
+
file_list = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|infinite_tracing|\.github)/(?!agent_helper.rb)}) }
|
43
43
|
build_file_path = 'lib/new_relic/build.rb'
|
44
44
|
file_list << build_file_path if File.exist?(build_file_path)
|
45
45
|
s.files = file_list
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_rpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rachel Klein
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2020-
|
13
|
+
date: 2020-11-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rake
|
@@ -201,31 +201,6 @@ extra_rdoc_files:
|
|
201
201
|
- CONTRIBUTING.md
|
202
202
|
- newrelic.yml
|
203
203
|
files:
|
204
|
-
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
205
|
-
- ".github/ISSUE_TEMPLATE/config.yml"
|
206
|
-
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
207
|
-
- ".github/actions/annotate/README.md"
|
208
|
-
- ".github/actions/annotate/action.yml"
|
209
|
-
- ".github/actions/annotate/dist/index.js"
|
210
|
-
- ".github/actions/annotate/index.js"
|
211
|
-
- ".github/actions/annotate/package-lock.json"
|
212
|
-
- ".github/actions/annotate/package.json"
|
213
|
-
- ".github/actions/annotate/pre-commit"
|
214
|
-
- ".github/actions/build-ruby/README.md"
|
215
|
-
- ".github/actions/build-ruby/action.yml"
|
216
|
-
- ".github/actions/build-ruby/dist/index.js"
|
217
|
-
- ".github/actions/build-ruby/index.js"
|
218
|
-
- ".github/actions/build-ruby/package-lock.json"
|
219
|
-
- ".github/actions/build-ruby/package.json"
|
220
|
-
- ".github/actions/build-ruby/pre-commit"
|
221
|
-
- ".github/pull_request_template.md"
|
222
|
-
- ".github/workflows/ci.yml"
|
223
|
-
- ".github/workflows/pr_review_checklist.yml"
|
224
|
-
- ".github/workflows/release.yml"
|
225
|
-
- ".github/workflows/scripts/rubygems-authenticate.py"
|
226
|
-
- ".github/workflows/scripts/rubygems-publish.rb"
|
227
|
-
- ".github/workflows/snyk.yml"
|
228
|
-
- ".github/workflows/stale.yml"
|
229
204
|
- ".gitignore"
|
230
205
|
- ".project"
|
231
206
|
- ".yardopts"
|
@@ -355,6 +330,7 @@ files:
|
|
355
330
|
- lib/new_relic/agent/instrumentation/mongo.rb
|
356
331
|
- lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb
|
357
332
|
- lib/new_relic/agent/instrumentation/net.rb
|
333
|
+
- lib/new_relic/agent/instrumentation/net_prepend.rb
|
358
334
|
- lib/new_relic/agent/instrumentation/notifications_subscriber.rb
|
359
335
|
- lib/new_relic/agent/instrumentation/padrino.rb
|
360
336
|
- lib/new_relic/agent/instrumentation/passenger_instrumentation.rb
|
@@ -1,31 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: Bug report
|
3
|
-
about: Create a report to help us improve
|
4
|
-
title: ''
|
5
|
-
labels: ''
|
6
|
-
assignees: ''
|
7
|
-
|
8
|
-
---
|
9
|
-
|
10
|
-
^^ Provide a general summary of the issue in the title above. ^^
|
11
|
-
|
12
|
-
## Description
|
13
|
-
Describe the problem you're encountering.
|
14
|
-
TIP: Do NOT share sensitive information, whether personal, proprietary, or otherwise!
|
15
|
-
|
16
|
-
## Expected Behavior
|
17
|
-
Tell us what you expected to happen.
|
18
|
-
|
19
|
-
## [Troubleshooting](https://discuss.newrelic.com/t/troubleshooting-frameworks/108787) or [NR Diag](https://docs.newrelic.com/docs/using-new-relic/cross-product-functions/troubleshooting/new-relic-diagnostics) results
|
20
|
-
Provide any other relevant log data.
|
21
|
-
TIP: Scrub logs and diagnostic information for sensitive information
|
22
|
-
|
23
|
-
## Steps to Reproduce
|
24
|
-
Please be as specific as possible.
|
25
|
-
TIP: Link a sample application that demonstrates the issue.
|
26
|
-
|
27
|
-
## Your Environment
|
28
|
-
Include as many relevant details about your environment as possible including the running version of the Ruby agent, the Ruby version being used and any other relevant environment information
|
29
|
-
|
30
|
-
## Additional context
|
31
|
-
Add any other context about the problem here. For example, relevant community posts or support tickets.
|
@@ -1,24 +0,0 @@
|
|
1
|
-
---
|
2
|
-
name: Feature request
|
3
|
-
about: Suggest an idea for this project
|
4
|
-
title: ''
|
5
|
-
labels: ''
|
6
|
-
assignees: ''
|
7
|
-
|
8
|
-
---
|
9
|
-
|
10
|
-
### Is your feature request related to a problem? Please describe.
|
11
|
-
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
12
|
-
|
13
|
-
### Feature Description
|
14
|
-
A clear and concise description of the feature you want or need.
|
15
|
-
|
16
|
-
### Describe Alternatives
|
17
|
-
A clear and concise description of any alternative solutions or features you've considered. Are there examples you could link us to?
|
18
|
-
|
19
|
-
### Additional context
|
20
|
-
Add any other context here.
|
21
|
-
|
22
|
-
### Priority
|
23
|
-
Please help us better understand this feature request by choosing a priority from the following options:
|
24
|
-
[Nice to Have, Really Want, Must Have, Blocker]
|
@@ -1,79 +0,0 @@
|
|
1
|
-
|
2
|
-
# Install Node
|
3
|
-
|
4
|
-
Using Homebrew, install Node (npm will be installed with Node):
|
5
|
-
|
6
|
-
```
|
7
|
-
brew install node
|
8
|
-
```
|
9
|
-
|
10
|
-
# Install Yarn
|
11
|
-
|
12
|
-
Yarn provides dependency management, so install it:
|
13
|
-
|
14
|
-
```
|
15
|
-
brew install yarn
|
16
|
-
```
|
17
|
-
|
18
|
-
# Install NCC
|
19
|
-
|
20
|
-
NCC is used to compile the *.js into a dist/index.js
|
21
|
-
|
22
|
-
```
|
23
|
-
npm i -g @zeit/ncc
|
24
|
-
```
|
25
|
-
|
26
|
-
# Build the dist/index.js
|
27
|
-
|
28
|
-
```
|
29
|
-
yarn run package
|
30
|
-
```
|
31
|
-
|
32
|
-
# Installing new javascript packages
|
33
|
-
|
34
|
-
Adding new javascript packages is fairly straightforward. If you're adding a github @actions/xxx package,
|
35
|
-
simply refer to it by its short-hand name:
|
36
|
-
|
37
|
-
```
|
38
|
-
npm install @actions/core
|
39
|
-
```
|
40
|
-
|
41
|
-
# Optional pre-commit hook
|
42
|
-
|
43
|
-
A pre-commit hook is provided that can help keep dist/index.js in tune with local changes
|
44
|
-
|
45
|
-
|
46
|
-
# Using Node as a REPL
|
47
|
-
|
48
|
-
If you're developing or working on the index.js script, it can be handy to try out stuff
|
49
|
-
locally. To do that, use Node to start up a REPL shell by running it from the action's folder:
|
50
|
-
|
51
|
-
```
|
52
|
-
cd .github/workflow/actions/annotate
|
53
|
-
node
|
54
|
-
```
|
55
|
-
|
56
|
-
Example session:
|
57
|
-
|
58
|
-
```javascript
|
59
|
-
Welcome to Node.js v14.3.0.
|
60
|
-
Type ".help" for more information.
|
61
|
-
> const os = require('os')
|
62
|
-
undefined
|
63
|
-
> const fs = require('fs')
|
64
|
-
undefined
|
65
|
-
> const path = require('path')
|
66
|
-
undefined
|
67
|
-
>
|
68
|
-
> const core = require('@actions/core')
|
69
|
-
undefined
|
70
|
-
> core.startGroup("hello")
|
71
|
-
::group::hello
|
72
|
-
undefined
|
73
|
-
> console.debug("hello")
|
74
|
-
hello
|
75
|
-
undefined
|
76
|
-
> core.endGroup()
|
77
|
-
::endgroup::
|
78
|
-
undefined
|
79
|
-
```
|