We're trying to migrate our Java applications from from the current Elastic Beanstalk JDK 8 platforms to the new ones running Corretto 11 on Amazon Linux 2. The app works well, but the way logs are handled changed. The output from the web process is now stored in /var/log/web.stdout.log
and every line is prefixed with the timestamp and process name, ie:
May 20 17:00:00 ip-10-48-41-129 web: {"timestamp":"2020-05-20T17:00:00.035Z","message":"...","logger":"...","thread":"MessageBroker-2","level":"INFO"}
How can we get rid of the prefix? These logs are streamed into CloudWatch and we're outputting them to stdout in JSON so that we can later query them with Logs Insights. But with the prefix, Insights doesn't "see" the JSON and just treats the whole line as a text blob.
I cannot find any documentation for that on AWS. Almost all of Elastic Beanstalk's documentation refers to the first version of Amazon Linux.
I found a solution that works well enough, so I'll post it here for posterity. If someone can suggest a better one, please do.
Elastic Beanstalk on Amazon Linux 2 relies on
rsyslog
for log processing and output. There's a file at/opt/elasticbeanstalk/config/private/rsyslog.conf
that during deployment gets copied over to/etc/rsyslog.d/web.conf
and it's the one that's directing all output from theweb
application to/var/log/web.stdout.log
.The file doesn't include any custom template. It relies on
rsyslog
's default template, which prefixes any%msg%
with a timestamp and$programname
(which isweb
in this case).I tried replacing this file via an
.ebextensions
config, but that didn't work, because Elastic Beanstalk seems to be overwriting this file after.ebextensions
run. So I added an additional platform hook that deletes the file, keeping the custom one I added.Here's the
.ebextensions/logs.config
file:and
.platform/hooks/predeploy/remove-default-rsyslog-conf.sh
(make sure youchmod +x
this one):I used Platform Hooks to accomplish this. The only catch is
/etc/rsyslog.d/web.conf
is replaced on both application and configuration deployments, so you need a hook for both.This approach avoids messing with Elastic Beanstalk's internal files in
/opt/elasticbeanstalk/config/private
(which have changed since the previous answers -rsyslog.conf
no longer exists). Also, platform hooks are now preferred over ebextensions.If you use CodeBuild, don't forget to include the
platformFiles
directory (or wherever you put your files) in your output artifact.NOTE: This code assumes the name of the process is
web
. If you defined a different process name in yourProcfile
, use that instead. However, I think the rsyslog config should always be at/etc/rsyslog.d/web.conf
despite the process name.Make sure all of your
.sh
files are executable usingchmod +x
..platform/hooks/predeploy/10_logs.sh
.platform/confighooks/predeploy/10_logs.sh
platformFiles/setupLogs.sh
platformFiles/rsyslogWebConf.conf
Conjecture
It looks like
/opt/elasticbeanstalk/config/private/rsyslog.conf
was replaced with/opt/elasticbeanstalk/config/private/rsyslog.conf.template
:Based on this, I speculate Elastic Beanstalk uses this template to generate a single
/etc/rsyslog.d/web.conf
file which contains a block for every defined process name. Because both an application and a configuration deployment can change the defined processes, it makes sense this file is recreated after both.I'm going to put my solution down here, although its a bit of a different problem than op - its around the same idea and hopefully answers some of the other commenters questions about nodejs.
This is for Amazon Linux 2 running Node.js 12.x
Problem: nodejs stdout logs are mixed in with nginx logs under "web" and are badly formatted.
Previously, in Amazon Linux 1 running Nodejs, these logs are separated into
/var/log/nodejs/nodejs.log
and/var/log/nginx/access.log
. Having them combined and prefixed with the ip address just makes them an an absolute mess.I followed the solutions put forwarded and modified them a bit.
I'm not sure if theey want you to be editing this file, as another commenter has pointed out, sincei is private. If you're not comfortable with this, I would recommend writing to your own log files rather than stdout. You have more control that way.
If you are using a lambda to move stuff into loggly (as per their documentation here https://documentation.solarwinds.com/en/success_center/loggly/content/admin/cloudwatch-logs.htm) you can simply modify the lambda to extract the JSON and drop off the leading string that is causing grief. Here is the lambda I am using, and it works great to clean stuff up and post my JSON logs.
Sidenote, I use NodeJS - Fastify which includes Pino under the hood for nice JSON logs. Some great insight on setting up the logs can be found here https://jaywolfe.dev/blog/setup-your-fastify-server-with-logging-the-right-way-no-more-express/