这不是特别关于我目前的问题,但更像是一般情况。有时我遇到的问题只发生在生产配置中,我想在那里进行调试。 Elixir最好的方法是什么?生产在没有图形环境(docker)的情况下运行。
在开发中我可以使用IEX.pry,但由于mix在生产中不可用,这似乎不是一种选择。
对于Erlang https://stackoverflow.com/a/21413344/1561489提到dbg和redbug,但即使可以使用它们,我也需要帮助将它们应用于Elixir代码。
答案 0 :(得分:3)
首先,使用iex -S mix
启动在dev计算机上运行iex的本地节点。如果您不希望本地运行的应用程序导致断点被激活,则需要禁止该应用程序在本地启动。为此,您只需在application
中注释mix.exs
功能或运行iex -S mix run --no-start
。
接下来,您需要使用Node.connect(:"remote@hostname")
从dev节点上的iex连接到docker上运行的远程节点。为此,您必须确保远程计算机上的epmd和节点端口都可以从本地节点访问。
最后,一旦你的节点连接起来,从本地iex运行:debugger.start()
,用GUI打开调试器。现在在本地iex中运行:int.ni(<Module you want to debug>)
,它将使模块对调试器可见,您可以继续添加断点并开始调试。
您可以找到包含步骤和屏幕截图here的教程。
答案 1 :(得分:2)
如果您在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
然后在awslogs
下的.config
文件中配置.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
并确保在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
内{1}}。
CloudWatch
的主要目的是至少知道您的应用程序何时崩溃,从而将容器关闭。 erl_crash.dump
通常会重新启动容器,从而让您无法重启。这种理解也可以从其他与docker相关的日志中获得,您可以配置警报以监听它们,并在您的docker必须重新启动时得到相应的通知。但是,将AWS EB
记录到CloudWatch的另一个好处是,如果需要,您可以随后将其导出到S3,下载文件并将其导入erl_crash.dump
内以分析出错的地方。
如果在查阅日志后仍然需要与生产应用程序进行更亲密的交互,那么您需要将:observer
用于您的节点。如果您使用remsh
,则可以使用以下版本配置生产应用程序的distillery
和cookie
:
在node name
内,设置Cookie:
rel/confix.exs
并在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 %>
内,你设置了这样的版本:
rel/config.exs
然后,您可以通过首先在包含docker容器的EC2实例内进行ssh-ing直接连接到docker内部运行的生产节点,然后运行以下命令:
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: "p@127.0.0.1",
]
进入内部后,您可以尝试四处寻找或CONTAINER_ID=$(sudo docker ps --format '{{.ID}}')
sudo docker exec -it $CONTAINER_ID bash -c "iex --name q@127.0.0.1 --cookie my_cookie"
,在您自己的危险中,动态注入您想要检查的模块的修改代码。一种简单的方法是在容器内创建一个文件并调用if need be
如果你的生产节点已经在运行并且你不知道cookie,你可以进入正在运行的容器并执行Node.spawn_link target_node, fn Code.eval_file(file_name, path) end
并执行ps aux > t.log
以找出随机cookie有哪些已经应用并相应使用。
Docker阻碍了cat t.log
能够与其他节点通信的方式。因此,最好使用epmd
创建自己的AWS AMI
图像,而不是进行裸机部署。
亚马逊最近向Packer
AWS VPC Networking Mode发布了一项新功能,这可能会促进容器间AWS ECS
通信,从而直接连接到您的节点。我还没有尝试过,我可能错了。
如果您在AWS以外的提供商上运行,那么必须确定如何使用某些epmd
或其他服务轻松访问远程日志。
答案 2 :(得分:0)
我建议使用某种异常处理工具,到目前为止,我在Sentry上有很棒的体验。