这不是特别关于我目前的问题,但更像一般。有时我遇到的问题只发生在生产配置中,我想在那里调试它。 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代码方面没有像“调试”构建这样的东西,所以两种环境下的代码应该是相同的。 –