• EnglishEspañol日本語한국어Português
  • 로그인지금 시작하기

사용자의 편의를 위해 제공되는 기계 번역입니다.

In the event of any inconsistency between the English version and the translated version, the English versionwill take priority. Please visit this page for more information.

문제 신고

SystemStackError: 스택 수준이 너무 깊습니다.

문제

애플리케이션에 newrelic_rpm gem을 추가하거나 버전 7.0.0 이상으로 업그레이드한 후 stack level too deep (SystemStackError) 오류가 표시됩니다.

해결책

대부분의 경우 Ruby 에이전트는 근본적인 문제가 아닙니다. 문제는 메서드 체인(alias_method)과 Module#prepend가 특정 상황에서만 함께 작동한다는 것입니다. 적절하게 함께 사용되지 않으면 종료되지 않는 재귀가 발생할 수 있습니다. Ruby 에이전트는 Module#prepend 및 메서드 체인 보석 계측을 모두 제공하여 고객에게 유연성을 제공합니다. 메서드 체인 및 Module#prepend 비호환성에 대한 자세한 내용은 New Relic Ruby 에이전트와 관련된 Module#prependalias_method 충돌 해결을 참조하세요.

1. 전체 스택 추적 가져오기

가장 먼저 해야 할 일은 보고 있는 오류에 대한 전체 스택 추적을 가져오는 것입니다. 전체 스택 추적이어야 하는 이유는 충돌하는 두 위치를 찾기 위해 재귀를 표시하는 섹션을 스택 추적에서 찾아야 하기 때문입니다. Rails 로그 및 Passenger 로그와 같은 항목은 스택 추적이 너무 길기 때문에 종종 자르기 때문에 잘리지 않은 전체 스택 추적을 가져올 수 있는 환경에서 오류를 재현해야 할 수도 있습니다. 이를 수행하는 한 가지 방법은 전체 스택 추적을 반환하는 stack level too deep 예외에서 Exception#backtrace를 호출하는 것입니다.

2. 스택 추적에서 충돌하는 코드 찾기

전체 스택 추적이 있으면 하나의 gem과 newrelic_rpm gem 사이에서 반복되는 섹션을 찾습니다. 이것은 아마도 충돌을 일으키는 보석일 것입니다. 다음은 Module#prepend 및 메서드 연결과 충돌하는 위치를 보여주는 스택 추적의 예시 섹션입니다.

/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:11:in `block in request'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rack.rb:25:in `capture_timing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:10:in `request'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/chain.rb:16:in `block in request_with_newrelic_trace'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:26:in `block (2 levels) in request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/tracer.rb:371:in `capture_segment_error'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:25:in `block in request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent.rb:501:in `disable_all_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:24:in `request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/chain.rb:16:in `request_with_newrelic_trace'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:11:in `block in request'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rack.rb:25:in `capture_timing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:10:in `request'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/chain.rb:16:in `block in request_with_newrelic_trace'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:26:in `block (2 levels) in request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/tracer.rb:371:in `capture_segment_error'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:25:in `block in request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent.rb:501:in `disable_all_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb:24:in `request_with_tracing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/chain.rb:16:in `request_with_newrelic_trace'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:11:in `block in request'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rack.rb:25:in `capture_timing'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:10:in `request'

줄 번호를 포함하여 충돌을 일으키는 파일을 볼 수 있습니다. 이를 통해 이 오류의 일부인 gem 계측을 알 수 있습니다. 위의 예를 사용하여 재귀를 일으키는 두 위치는 다음과 같습니다.

/Users/user/.rvm/gems/ruby-2.6.5/gems/newrelic_rpm-7.0.0/lib/new_relic/agent/instrumentation/net_http/chain.rb:16:in `request_with_newrelic_trace'
/Users/user/.rvm/gems/ruby-2.6.5/gems/airbrake-11.0.1/lib/airbrake/rails/net_http.rb:11:in `block in request'

이 두 위치에서 코드를 풀업하면 하나는 prepend를 사용하고 다른 하나는 메서드 체이닝을 사용하는 것을 볼 수 있습니다. 이 특정 예에서 에이전트는 메서드 체인을 사용하고 Airbrake는 Module#prepend를 사용합니다. 에이전트는 메서드 체인과 Module#prepend를 모두 제공하므로 충돌하는 gem과 호환되는 전략을 사용하도록 에이전트를 구성할 수 있습니다.

3. 구성 파일 업데이트

스택 추적의 에이전트 행을 자세히 살펴보면 경로 이름에서 구성해야 하는 gem 계측을 볼 수 있습니다.

new_relic/agent/instrumentation/net_http/chain.rb:16

gem 이름은 파일 경로에서 new_relic/agent/instrumentation/ 다음에 옵니다. 이 예의 경우 이것이 Net::HTTP 계측임을 알 수 있으므로 구성 파일에서 net_http 을 사용하여 이 계측을 제어할 수 있습니다. 파일 이름을 보면 이것이 메서드 체인 계측을 사용하고 있음을 알 수 있습니다. 메소드 체인의 파일 이름은 /chain.rb 이고 Module#prepend 의 경우 /prepend.rb 입니다.

충돌의 일부였던 gem 계측을 사용하여 구성 옵션을 newrelic.yml 에 추가합니다. 이 예에서는 메서드 체인 계측과의 충돌로 인해 오류가 발생했습니다. 이를 해결하기 위해 Module#prepend를 사용하도록 Net::HTTP 계측을 설정합니다.

instrumentation:
net_http: prepend

대신 스택 추적에서 prepend.rb 파일이 참조된 경우 이 구성 옵션을 chain 로 설정합니다.

에이전트의 사용 가능한 구성 옵션에 대한 자세한 내용은 구성 문서 의 계측 섹션을 참조하십시오.

4. 여전히 오류가 표시됩니까?

위의 지침을 따른 후에도 여전히 스택 수준이 너무 깊은 오류가 표시되는 경우 이것이 동일한 충돌 및 스택 추적인지 또는 이것이 방금 수정한 것과 다른 충돌인지 확인하고 확인하십시오.

이것이 다른 스택 추적과 다른 충돌인 경우 새 스택 추적으로 위의 단계를 반복하십시오. 그렇게 하면 새로 표면화된 갈등이 해결될 것입니다.

스택 추적이 첫 번째 추적과 동일한 경우 에이전트가 구성 파일을 로드할 수 있는지 확인하십시오. 에이전트가 구성 파일을 찾거나 로드하는 데 문제가 있는 경우 해당 문제를 해결하면 에이전트가 필요한 gem 계측을 사용할 수 있습니다. 자세한 내용은 구성 설명서 를 참조하십시오.

원인

애플리케이션의 한 위치(또는 애플리케이션에서 사용되는 gem)가 나중에 다른 위치(또는 gem)에서 alias_method를 사용하는 메서드에 Module#prepend를 사용하면 비종료 재귀가 생성되고 SystemStackError: stack level too deep error 가 발생합니다.

Ruby 에이전트의 7.0 릴리스에서는 이전에 메서드 체인만 사용했던 모든 gem 계측에 대해 Module#prepend 계측이 추가되었습니다. Module#prepend는 대부분의 경우 기본적으로 사용됩니다. 에이전트는 여전히 gem 계측에 메서드 체인을 사용할 수 있도록 허용합니다. 이 동작은 에이전트 구성 에 의해 제어됩니다.

에이전트가 gem 계측 구성에 기본값을 사용할 때 Module#prepend를 사용하여 일반적으로 알려진 충돌이 있는지 환경을 확인합니다. 이 충돌을 일으키는 gem이 감지되면 에이전트는 대신 메서드 체인 계측을 설치합니다.

그러나 가능한 충돌을 모두 알고 있는 것은 아닙니다. 모든 gem 또는 애플리케이션은 모든 메소드에 메소드 체이닝을 추가할 수 있습니다. 이것이 사용되는 계측 유형을 구성하는 옵션을 제공하는 이유입니다.

다음은 에이전트가 호환 가능한 gem 계측을 확인하고 설치하는 알려진 충돌의 몇 가지 예입니다.

Net::HTTP 계측

Airbrake < 10.0.2를 사용할 때 Net::HTTP 메서드에 메서드 체인을 사용합니다. Airbrake 10.0.2+는 Net::HTTP에서 Module#prepend를 사용하도록 업데이트되었으므로 에이전트는 해당 버전 이상이 감지되면 prepend 계측을 설치합니다.

Resque 계측

Airbrake < 11.0.3을 사용할 때 Reque 메서드에 메서드 체인을 사용합니다. Airbrake 11.0.3+는 Resque에서 Module#prepend를 사용하도록 업데이트되었으므로 에이전트는 해당 버전 이상이 감지되면 prepend 계측을 설치합니다.

레디스 계측

PrometheusExporter가 감지되면 해당 gem이 redis 메서드에서 메서드 체인을 사용하므로 메서드 체인을 사용합니다.

Copyright © 2024 New Relic Inc.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.