2017-10-11 45 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

以上是一般性概述,迂腐细节可能会丢失,并留给读者作为练习:) –

相关问题