2017-10-11 73 views
4

這不是特別關於我目前的問題,但更像一般。有時我遇到的問題只發生在生產配置中,我想在那裏調試它。 Elixir的最佳方法是什麼?生產運行時沒有圖形環境(docker)。如何在生產中調試Elixir應用程序?

在開發中,我可以使用IEX.pry,但由於混合在生產中不可用,這似乎不是一種選擇。

對於Erlang https://stackoverflow.com/a/21413344/1561489提到了dbg和redbug,但即使它們可以使用,我也需要將它們應用到Elixir代碼上。

+3

使用特定的日誌,您可以始終替換日誌的默認後端 - 控制檯 - 以獲取適合您需求的內容。 – PatNowak

+1

在你想調試,重新部署和監視日誌的地方添加'Logger.error'。我也想聽到更好的方法。 –

+0

您還可以嘗試確定生產系統和調試系統之間的確切區別,並將其消除。據我所知,在BEAM代碼方面沒有像「調試」構建這樣的東西,所以兩種環境下的代碼應該是相同的。 –

回答

3

首先,使用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

+0

謝謝,這是我正在尋找的答案! – raarts

+0

我想從IEx手冊中添加以下內容:「連接到遠程shell非常常見,我們也通過命令行提供了快捷方式:'$ iex --sname baz --remsh foo @ HOST'」 – raarts

0

我會推薦使用某種異常處理工具,到目前爲止我在Sentry上有很棒的體驗。

0

如果您在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.logCloudWatch

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或某些其他服務輕鬆訪問遠程日誌是必須的。

+0

以上是一般性概述,迂腐細節可能會丟失,並留給讀者作爲練習:) –

相關問題