如果您在 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
然后在.ebextensions下的.config文件中配置awslogs如下:
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下为你的docker设置了一个卷
"Logging": "/var/log",
"Volumes": [
{
"HostDirectory": "/var/log",
"ContainerDirectory": "/opt/log"
}
],
之后,您可以在CloudWatch 下查看您的错误消息。
现在,如果您使用ElasticBeanstalk(我上面的示例隐含暗示)与Docker 部署而不是AWS ECS,则std_input 的日志默认重定向到CloudWatch 内的/var/log/eb-docker/containers/eb-current-app/stdouterr.log。
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 %>
在rel/config.exs 中,您可以这样设置发布:
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",
]
然后您可以通过首先在包含 docker 容器的 EC2 实例中 ssh-ing 直接连接到在 docker 中运行的生产节点,然后运行以下命令:
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,后果自负地为您要检查的模块动态注入修改后的代码。一个简单的方法是在容器内创建一个文件并调用Node.spawn_link target_node, fn Code.eval_file(file_name, path) end
如果您的生产节点已经在运行并且您不知道 cookie,您可以进入正在运行的容器中并执行 ps aux > t.log 并执行 cat t.log 以确定已应用和使用的随机 cookie相应地。
Docker 阻碍了epmd 与其他节点的通信。因此,最好的办法是使用Packer 创建您自己的AWS AMI 映像,然后进行裸机部署。
亚马逊最近向AWS ECS、AWS VPC Networking Mode 发布了一项新功能,这可能有助于容器间epmd 通信,从而直接连接到您的节点。我还没试过,我可能错了。
如果您在 AWS 以外的提供商上运行,那么必须弄清楚如何使用 SSM agent 或其他服务轻松访问您的远程日志。