AWS Elastic Beanstalk使用Python(django)进行日志记录

j7dteeu8  于 2023-08-08  发布在  Go
关注(0)|答案(9)|浏览(125)

如何在AWS Elastic Beanstalk中管理应用程序日志?您将应用程序日志写入哪个文件?
我在开发环境中使用以下日志记录配置,但在AWS中部署时,这不起作用。

DEBUG_LOG_DIR = BASE_DIR + "/django_debug.log"
LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    # How to format the output
    'formatters': {
        'standard': {
            'format' : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
            'datefmt' : "%d/%b/%Y %H:%M:%S"
        },
    },
    # Log handlers (where to go)
    'handlers': {
        'null': {
            'level':'DEBUG',
            'class':'django.utils.log.NullHandler',
        },
        'log_file': {
            'level':'DEBUG',
            'class':'logging.handlers.RotatingFileHandler',
            'filename': DEBUG_LOG_DIR,
            'maxBytes': 50000,
            'backupCount': 2,
            'formatter': 'standard',
        },
        'console':{
            'level':'INFO',
            'class':'logging.StreamHandler',
            'formatter': 'standard'
        },
        'mail_admins': {
            'level': 'ERROR',
            'class': 'django.utils.log.AdminEmailHandler',
        },
    },
    # Loggers (where does the log come from)
    'loggers': {
        'repackager': {
            'handlers': ['console', 'log_file'],
            'level': 'DEBUG',
            'propagate': True,
        },
        'django': {
            'handlers':['console'],
            'propagate': True,
            'level':'WARN',
        },
        'django.db.backends': {
            'handlers': ['console', 'log_file'],
            'level': 'WARN',
            'propagate': False,
        },
        '': {
            'handlers': ['console', 'log_file'],
            'level': 'DEBUG',
        },
    }
}

字符串

mec1mxoz

mec1mxoz1#

我在Elastic Beanstalk上遇到了类似的问题,所以我创建了一个配置文件(e.g. applogs.config)在应用程序的.ebextensions文件夹中。如果app-logs文件夹不存在,则会创建该文件夹,并设置文件权限和所有者,以便应用可以在其中写入日志。

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_owner:
    command: chown wsgi:wsgi /var/log/app-logs

字符串
最后,在Django设置中:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': '/var/log/app-logs/django.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}


有条件地,如果您希望您的日志可以通过web从beanstalk日志访问,请将其添加到.ebextensions中的文件中

files:
  "/opt/elasticbeanstalk/tasks/taillogs.d/django.conf":
    mode: "000755"
    owner: root
    group: root
    content: |
      /var/log/app-logs/django.log

wz3gfoph

wz3gfoph2#

好吧,我想到了一个办法。
首先,我通过ssh连接到ec2机器,然后我在/var/log中创建了一个名为app_logs的文件夹:

mkdir /var/log/app_logs

字符串
之后,我做了以下工作:

cd /var/log/
chmod g+s app_logs/
setfacl -d -m g::rw app_logs/
chown wsgi:wsgi app_logs/


这样可以确保在此文件夹中创建的所有文件都将wsgi作为所有者,并且对于文件所属的组来说都是可写的。我不得不这样做,因为我注意到django应用程序创建的日志文件有root作为所有者和所有者组,但是应用程序通过wsgi用户运行。
最后我把DEBUG_LOG_DIR改为/var/log/app_logs/django_debug. log

ilmyapht

ilmyapht3#

有一种简单的方法不需要任何beanstalk配置。
在你的django设置中,在LOGGING下设置一个指向文件**'/opt/python/log/{log_file_name}'**的处理程序。然后可以通过beanstalk环境菜单中的“Logs”访问日志。

LOGGING = {
    ...,
    'handlers': {
        'logfile': {
            'level': 'DEBUG',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': '/opt/python/log/{log_file_name}',
        },
    },
    'loggers': {
        'debugger': {
            'level': 'DEBUG',
            'handlers': ['logfile'],
        'propagate': False,
    },
}

字符串
此位置在此处的文档中说明:
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features.logging.html#health-logs-instancelocation

guykilcj

guykilcj4#

--编辑--
这个答案最初是为Amazon Linux AMI编写的,它现在已经达到了end-of-life
为了让事情清晰和分开,我写了一个new answer for Amazon Linux 2
--原创答案--

摘要

在我看来,最简单的解决方案是登录到/opt/python/log文件夹,正如bewestphal和@thierry-j(在steve-dunlop's answer下)所建议的那样。
这也是官方AWS EB Python * 示例应用程序 * 的功能:参见python-v1.zip
当您向EB请求日志时,日志文件将自动包含在内。
这个解决方案是开箱即用的,无需对.ebextensions进行任何修改,只要你不.ebextensions中调用django-admin.py(或其他django代码)。
但是,大多数应用
确实**需要在.ebextensions中调用django-admin.py,例如:为了migrate。这将导致创建日志文件 * 过早 *,包含root所有者和root组。这会导致权限错误,因为应用程序以wsgi:wsgi运行。
这个问题可以通过在container_commands的末尾 * 添加一个新命令来修复,以删除“过早”的日志文件,例如:

container_commands:
  ...
  9999_remove_root_log_file:
    command: rm /opt/python/log/django.log
    ignoreErrors: true

字符串
详情见下文。

后台

在一个标准的预配置Amazon Linux/Python平台上,使用Apache和mod_wsgi(参见AWS platform docs),Django应用程序的WSGIDaemonProcess以用户wsgi和组wsgi的身份运行(参见EC2示例上的/etc/httpd/conf.d/wsgi.conf)。
此外,/opt/python/log文件夹的 default 文件夹权限(在我的标准EC2示例上)是:drwxrwxr-x 3 root wsgi 4096 Mar 5 14:08 .
也就是说,wsgi组拥有所有权限(rwx),所以Django应用程序(wsgi组)可以在那里创建日志文件。
正如官方AWS EB Python示例应用程序(python-v1.zip)所演示的那样,这是现成的。
但是,如果您在.ebextensions中执行了任何导致logging文件处理程序初始化的操作(比如调用django-admin.py),它就会中断。

权限问题

以下是在.ebextensions中使用django-admin.py会破坏日志文件权限的方法:
.ebextensions中,Elastic Beanstalk container_commandsroot用户的身份执行(请参阅aws docs)。
如果您在任何container_commands中调用django-admin.py,例如使用collectstaticmigrate,这将导致日志文件处理程序被初始化。如果指定的日志文件尚不存在,则此时将创建该日志文件,并具有root所有者和root组。
这意味着Django应用程序作为wsgi组的一部分运行,将没有权限写入日志文件(属于root组)。
这会导致权限错误,例如:PermissionError: [Errno 13] Permission denied: '/opt/python/log/django.log'

如何复制

下面的代码片段说明了权限问题并说明如何修复它。
要重现问题,请将这些container_commands添加到干净的项目中(例如在AWS EB Django tutorial之后),配置Django settings.py以登录到/opt/python/log/django.log,部署到AWS EB,然后检查eb-activity.log以查看容器命令的输出。

...

container_commands:
  0100_show_current_user:
    # show that we are running as root user
    command: whoami
  0200_try_to_remove_log_file:
    # we need a clean slate for this example (make sure no log file owned by wsgi is present)
    command: rm /opt/python/log/django.log
    ignoreErrors: true
  0300_break_log_file_permissions:
    # this causes a new log file to be created, owned by root:root (instead of wsgi:wsgi)
    command: django-admin.py
  0400_show_log_file_permissions:
    # prove that a log file was created by root, and show folder permissions
    command: ls -la /opt/python/log
  0500_fix_by_removing_log_file_after_all_django_admin_calls:
    # remove the log file created by django-admin.py, to ensure that a new log file will  
    # be created when the server starts, owned by wsgi:wsgi
    command: rm /opt/python/log/django.log
    ignoreErrors: true

干燥溶液

所以,* 没有必要显式地混淆文件/文件夹权限 *。
如果你没有在.ebextensions中调用django代码,那么登录到/opt/python/log就可以了,开箱即用。
如果你在.ebextensions中调用django代码,例如:django-admin.py collectstatic,只需删除container_commands部分末尾的日志文件 * 即可。
注意:如果要记录文件以在部署之间持久存在,请仅在这些文件归root所有时才删除这些文件。
下面是一个DRY示例:
.ebextensions配置中:

option_settings:
  # create EB environment property for the log file path
  aws:elasticbeanstalk:application:environment:
    LOG_FILE_PATH: /opt/python/log/django.log
...

container_commands:
  ...
  # django code called here, e.g. "django-admin.py collectstatic"
  ...
  9999_remove_any_existing_django_log_files:
    command: rm $LOG_FILE_PATH      
    ignoreErrors: true


settings.py

...
# get log path from environment variable, with fallback for local development
log_file_path = os.getenv('LOG_FILE_PATH', 'local.log')
# use this as 'filename' for the file handler, as described in the other answers
...

kupeojn6

kupeojn65#

此答案仅适用于Amazon Linux 2。对于那些没有迁移yet的人,请看我的old answer for Amazon Linux AMI

后台

official AWS Python sample-application forAmazon linux 2使用/tmp文件夹进行日志记录。
但是,从Elastic Beanstalk请求日志时,不会自动包含添加到/tmp的自定义日志文件。要包含自定义日志文件,我们需要在EC2示例的/opt/elasticbeanstalk/tasks子文件夹中创建日志任务。参见文档中的说明。
示例应用程序(source)使用.ebextensions实现了这一点。然而,AWS Linux 2 migration docs建议我们应该使用.platform钩子:
我们建议使用平台钩子在您的环境示例上运行自定义代码。您仍然可以在.ebextensions配置文件中使用命令和容器命令,但它们不那么容易使用。例如,在YAML文件中编写命令脚本可能很麻烦,并且难以测试。
这还有一个额外的优点,即平台钩子的输出被收集在一个单独的日志文件中,即。/var/log/eb-hooks.log,这使得调试更容易一些。

Amazon Linux 2**上Django基本应用的DRY日志设置

日志级别和日志路径被定义在 * 一个 * 地方,作为Elastic Beanstalk环境属性,例如在.ebextensions/options.config中:

option_settings:
  aws:elasticbeanstalk:application:environment:
    LOG_LEVEL: INFO
    DJANGO_LOG_FILE_PATH: /tmp/django-app.log
    ...

字符串
DJANGO_LOG_FILE_PATH环境属性现在可以在平台钩子中用于创建日志记录任务:

.platform/hooks/postdeploy/020_create_logging_tasks.sh

#!/bin/bash
TASKS_DIR=/opt/elasticbeanstalk/tasks
# include all app log files in bundle logs (replaces ".log" by "*")
echo "${DJANGO_LOG_FILE_PATH//.log/*}" > "$TASKS_DIR/bundlelogs.d/01-app-log.conf"
# include current app log file in tail logs
echo $DJANGO_LOG_FILE_PATH > "$TASKS_DIR/taillogs.d/01-app-log.conf"


注意,平台钩子需要执行权限,例如chmod +x 020_create_logging_tasks.sh。在windows上,您可以使用git,如here所述。
为了防止权限问题,我们使用另一个平台钩子来确保日志文件始终归webapp所有。注意这个钩子在logging-tasks钩子之前运行:

.platform/hooks/postdeploy/010_create_log_file.sh

#!/bin/bash

if test -f "$DJANGO_LOG_FILE_PATH";
then
  echo "$DJANGO_LOG_FILE_PATH exists"
else
  # create log file
  touch $DJANGO_LOG_FILE_PATH
fi

# set log file owner (we are currently "root", but the app runs as "webapp")
chown webapp:webapp $DJANGO_LOG_FILE_PATH


我们还在Django设置中使用了LOG_LEVELDJANGO_LOG_FILE_PATH环境属性:

settings.py

...
# basic logging with file rotation ()
log_level = os.getenv('LOG_LEVEL', 'INFO')
handlers = dict(file={'class': 'logging.handlers.TimedRotatingFileHandler',
                      'filename': os.getenv('DJANGO_LOG_FILE_PATH'),
                      'when': 'midnight',
                      'interval': 1,
                      'backupCount': 1,
                      'encoding': 'utf-8'})
loggers = dict(django=dict(level=log_level, handlers=['file']),
               myapp=dict(level=log_level, handlers=['file']))
LOGGING = dict(version=1,
               disable_existing_loggers=False,
               handlers=handlers,
               loggers=loggers)
...


一些注解:

  • 我们通常也指定自定义formatters,但为了清楚起见,我省略了这些。
  • 现在可以在/var/app/current中的EC2示例上找到应用程序本身。更多详细信息,请参阅扩展EB Linux平台。
  • 该应用程序现在以webapp的形式运行,并具有组webapp
  • eb ssh是你的朋友。参见docs
  • 我们还使用平台钩子来运行Django的migratecollectstatic命令,如here所述。

编辑:
正如@hax0在评论中指出的,如果 * 您尝试在EC2示例上使用SSH运行manage.py命令,* 部署后 *,可能会出现文件权限问题。
例如,使用eb ssh时,您以ec2-user身份登录,但日志文件归webapp用户所有,默认情况下,只有所有者有写权限(644)。因此,当以ec2-user的形式运行python manage.py时,您将收到一个错误,说明它无法配置日志文件处理程序,因为权限被拒绝。
一个快速而肮脏的解决方法是 * 临时 * 更改文件权限,例如:使用

sudo chmod 646 /tmp/django-app.log


另一种解决方法是以webapp用户的身份运行manage.py,例如:

sudo su - webapp <<'EOF'
source $(find /var/app/venv/*/bin/activate)
export $(/opt/elasticbeanstalk/bin/get-config --output YAML environment | 
         sed -r 's/: /=/' | xargs)
python3 /var/app/current/manage.py showmigrations
EOF

bjg7j2ky

bjg7j2ky6#

作为一个linux权限方面的初学者,我花了一些时间才让它工作起来。总结以上给出的答案,以下最终对我起了作用:
logging.config

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_default_owner:
    command: setfacl -d -m g::rw /var/log/app-logs
  03_change_owner:
    command: chown wsgi:wsgi /var/log/app-logs

字符串
settings.py

LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
    'file': {
        'level': 'DEBUG',
        'class': 'logging.FileHandler',
        'filename': '/var/log/app-logs/django.log',
    },
},
'loggers': {
    'django': {
        'handlers': ['file'],
        'level': 'DEBUG',
        'propagate': True,
    },
},
}


这样我就可以使用'eb logs'将日志作为一个单独的部分或者在Beanstalk环境中的“logs”部分来查看日志。

laximzn5

laximzn57#

如果你使用gunicorn,那么你可以使用这个标志:

gunicorn --access-logfile=-

字符串

t3psigkw

t3psigkw8#

以下是我在64位Amazon Linux 2023/4.0.2上的解决方案

commands:
  00_create_dir:
    command: mkdir -p /var/log/app-logs
  01_change_permissions:
    command: chmod g+s /var/log/app-logs
  02_change_owner:
    command: chown webapp:webapp /var/log/app-logs

字符串
以及Django中的日志文件设置,

'handlers': {
    'console': {
        'level': 'INFO',
        'class': 'logging.StreamHandler',
    },
    'logfile': {
        'level': 'INFO',
        'class': 'logging.handlers.RotatingFileHandler',
        'filename': "/var/log/app-logs/django.log",
        'formatter': 'standard',
    },
},
'loggers': {
    '': {
        'handlers': ['console', 'logfile'],
        'level': 'INFO',
    },
}


确保日志文件具有正确的所有权和组配置,所有者和组应该是webapp:wehapp,如下所示

[ec2-user@ip-171-11-1-8 app-logs]$ ll django.log
-rw-r--r--. 1 webapp webapp 1120 Jul 29 01:08 django.log

sbtkgmzw

sbtkgmzw9#

默认情况下,在elasticbeanstalk中,您可以在这里看到django错误日志。

/var/log/httpd/error_log

字符串

相关问题