這不是特別關於我目前的問題,但更像一般。有時我遇到的問題只發生在生產配置中,我想在那裏調試它。 Elixir的最佳方法是什麼?生產運行時沒有圖形環境(docker)。如何在生產中調試Elixir應用程序?
在開發中,我可以使用IEX.pry,但由於混合在生產中不可用,這似乎不是一種選擇。
對於Erlang https://stackoverflow.com/a/21413344/1561489提到了dbg和redbug,但即使它們可以使用,我也需要將它們應用到Elixir代碼上。
這不是特別關於我目前的問題,但更像一般。有時我遇到的問題只發生在生產配置中,我想在那裏調試它。 Elixir的最佳方法是什麼?生產運行時沒有圖形環境(docker)。如何在生產中調試Elixir應用程序?
在開發中,我可以使用IEX.pry,但由於混合在生產中不可用,這似乎不是一種選擇。
對於Erlang https://stackoverflow.com/a/21413344/1561489提到了dbg和redbug,但即使它們可以使用,我也需要將它們應用到Elixir代碼上。
首先,使用iex -S mix
在您的開發機器上啓動一個運行iex的本地節點。如果您不希望在本地運行的應用程序導致斷點被激活,則需要禁用該應用程序從本地啓動。要做到這一點,您只需在mix.exs
中註釋application
函數或運行iex -S mix run --no-start
即可。
接下來,您需要使用Node.connect(:"[email protected]")
從dev節點上的iex連接到docker上運行的遠程節點。爲此,您必須確保遠程計算機上的epmd和節點端口均可從本地節點訪問。
最後,一旦您的節點連接,從本地iex運行:debugger.start()
,它將打開調試器與GUI。現在在本地iex中運行:int.ni(<Module you want to debug>)
,它將使該模塊對調試器可見,您可以繼續並添加斷點並開始調試。
你可以找到一個教程,步驟和截圖here。
我會推薦使用某種異常處理工具,到目前爲止我在Sentry上有很棒的體驗。
如果您在AWS上運行生產,那麼您首先應該利用CloudWatch
來獲得您的優勢。 在你elixir
代碼,配置您的記錄是這樣的:
config :logger,
handle_otp_reports: true,
handle_sasl_reports: true,
metadata: [:application, :module, :function, :file, :line]
config :logger,
backends: [
{LoggerFileBackend, :shared_error}
]
config :logger, :shared_error,
path: "#{logging_dir}/verbose-error.log",
level: :error
您Dockerfile內部,配置正是erl_crash.dump
的環境變量被寫入,如: ERL_CRASH_DUMP=/opt/log/erl_crash.dump
然後裏面.config
配置awslogs
文件在.ebextensions
如下:
files:
"/etc/awslogs/config/stdout.conf":
mode: "000755"
owner: root
group: root
content: |
[erl_crash.dump]
log_group_name=/aws/elasticbeanstalk/your_app/erl_crash.dump
log_stream_name={instance_id}
file=/var/log/erl_crash.dump
[verbose-error.log]
log_group_name=/aws/elasticbeanstalk/your_app/verbose-error.log
log_stream_name={instance_id}
file=/var/log/verbose-error.log
並確保喲u盤捲到您的碼頭工人Dockerrun.aws.json
"Logging": "/var/log",
"Volumes": [
{
"HostDirectory": "/var/log",
"ContainerDirectory": "/opt/log"
}
],
下之後,你就可以CloudWatch
下檢查你的錯誤消息。 現在,如果你正在使用ElasticBeanstalk
(這我上面的例子含蓄地暗示)與Docker
部署,而不是AWS ECS
,那麼std_input
的日誌默認重定向到/var/log/eb-docker/containers/eb-current-app/stdouterr.log
內CloudWatch
。
erl_crash.dump
的主要目的是至少知道您的應用程序何時崩潰,從而取下容器。AWS EB
通常會重新啓動容器,從而使您不知道重新啓動。這種理解也可以從其他docker相關日誌中獲得,並且您可以配置警報以偵聽它們,並在docker必須重新啓動時相應地通知。但將erl_crash.dump
記錄到CloudWatch的另一個優點是,如果需要,可以隨時將其稍後導出到S3,下載該文件並將其導入:observer
以分析出錯的原因。
如果在查閱日誌後,仍需要與生產應用程序進行更密切的交互,那麼您需要將remsh
用於節點。如果你使用distillery
,你會配置cookie
和生產應用程序的node name
你發佈這樣的:
內rel/confix.exs
,設置cookie的:
environment :prod do
set include_erts: false
set include_src: false
set cookie: :"my_cookie"
end
和rel/templates/vm.args.eex
下你設置變量:
-name <%= node_name %>
-setcookie <%= release.profile.cookie %>
and inside rel/config.exs
,you set like this:
release :my_app do
set version: "0.1.0"
set overlays: [
{:template, "rel/templates/vm.args.eex", "releases/<%= release_version %>/vm.args"}
]
set overlay_vars: [
node_name: "[email protected]",
]
然後你就可以直接連接到您的生產節點首先SSH-ING的EC2實例,裏面的泊塢窗容器內內碼頭工人運行,且運行以下命令:
CONTAINER_ID=$(sudo docker ps --format '{{.ID}}')
sudo docker exec -it $CONTAINER_ID bash -c "iex --name [email protected] --cookie my_cookie"
一旦進入,你可以然後嘗試在你自己的危險周圍或if need be
,動態注入你想要檢查的模塊的修改後的代碼。一個簡單的方法是在容器中創建一個文件並調用Node.spawn_link target_node, fn Code.eval_file(file_name, path) end
如果您的生產節點已經在運行並且您不知道該cookie,則可以進入正在運行的容器並執行一個ps aux > t.log
並做一個cat t.log
找出什麼隨機cookie已被應用和相應使用。
碼頭作爲阻礙epmd
能夠與其他節點通信的障礙。因此,最好的方法是使用Packer
創建自己的AWS AMI
圖像,然後進行裸機部署。
亞馬遜最近發佈了AWS ECS
,AWS VPC Networking Mode的新功能,這可能會促進容器間的通信,因此可以直接連接到您的節點。我還沒有嘗試過,我可能是錯的。
如果您在AWS以外的提供商上運行,那麼確定如何使用某些SSM agent
或某些其他服務輕鬆訪問遠程日誌是必須的。
以上是一般性概述,迂腐細節可能會丟失,並留給讀者作爲練習:) –
使用特定的日誌,您可以始終替換日誌的默認後端 - 控制檯 - 以獲取適合您需求的內容。 – PatNowak
在你想調試,重新部署和監視日誌的地方添加'Logger.error'。我也想聽到更好的方法。 –
您還可以嘗試確定生產系統和調試系統之間的確切區別,並將其消除。據我所知,在BEAM代碼方面沒有像「調試」構建這樣的東西,所以兩種環境下的代碼應該是相同的。 –