Browse Source

add logs.py to save some logs.Update readme

logs.py include log to file and if web app has some error happen send
email to admin
honmaple 8 years ago
parent
commit
b279fd2384

+ 17 - 0
README.org

@@ -28,6 +28,23 @@
    pip install -r requirements.txt
     #+END_SRC
 
+*** Config
+    #+BEGIN_SRC shell
+    mv config.example config
+    #+END_SRC
+    after finished configure
+
+    *For Production*
+    Please set DEBUG = False or change *maple/__init__.py*
+    #+BEGIN_SRC python
+    app.config.from_object('config.config')
+    #+END_SRC
+    to
+    #+BEGIN_SRC python
+    app.config.from_object('config.production')
+    #+END_SRC
+
+
 *** Comment before init db
 
     place of file: *maple/topic/forms.py*

+ 36 - 19
config.example/config.py

@@ -2,45 +2,62 @@
 # -*- coding=UTF-8 -*-
 # **************************************************************************
 # Copyright © 2016 jianglin
-# File Name: config.py
+# File Name: production.py
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 12:31:46 (CST)
-# Last Update:星期三 2016-6-15 18:24:59 (CST)
+# Last Update:星期二 2016-7-26 18:3:24 (CST)
 #          By: jianglin
 # Description:
 # **************************************************************************
 from datetime import timedelta
 
 DEBUG = True
-SECRET_KEY = ''
-SECURITY_PASSWORD_SALT = ''
+SECRET_KEY = 'secret key'
+SECURITY_PASSWORD_SALT = 'you will never guess'
 
+# remember me to save cookies
 PERMANENT_SESSION_LIFETIME = timedelta(days=3)
 REMEMBER_COOKIE_DURATION = timedelta(days=3)
+ONLINE_LAST_MINUTES = 5
 
+# You want show how many topics per page
 PER_PAGE = 12
 
-# 定制缓存 = 60
+# Use cache
+CACHE_TYPE = 'redis'
 CACHE_DEFAULT_TIMEOUT = 60
 CACHE_KEY_PREFIX = 'cache:'
 CACHE_REDIS_HOST = '127.0.0.1'
-CACHE_REDIS_PORT = ''
-CACHE_REDIS_PASSWORD = ''
+CACHE_REDIS_PORT = '6379'
+CACHE_REDIS_PASSWORD = 'redis password'
 CACHE_REDIS_DB = 1
 
-# REDIS_PASSWORD = 'redis'
-# REDIS_DB = 1
 
-ONLINE_LAST_MINUTES = 5
+# Mail such as qq
+MAIL_SERVER = 'smtp.qq.com'
+MAIL_PORT = 25
+MAIL_USE_TLS = True
+MAIL_USE_SSL = False
+MAIL_USERNAME = 'Your domain email'
+MAIL_PASSWORD = 'Your password'
+MAIL_DEFAULT_SENDER = 'Your domain email'
+
+# Log,if SEND_LOGS is True when web app has some error happen(500)
+# the email will be sent to RECEIVER
+SEND_LOGS = False
+RECEIVER = ["yourname@gmail.com"]
+INFO_LOG = "info.log"
+ERROR_LOG = "error.log"
+
+# Sql
+SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:password@localhost/db_name'
+# SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/test.db'
+# SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db'
+
 
-MAIL_SERVER = ''
-MAIL_PORT =
-MAIL_USE_TLS =
-MAIL_USE_SSL =
-MAIL_USERNAME = ''
-MAIL_PASSWORD = ''
-MAIL_DEFAULT_SENDER = ''
+# avatar upload folder
+AVATAR_FOLDER = 'avatars/'
 
-# SQLALCHEMY_TRACK_MODIFICATIONS = False
-SQLALCHEMY_DATABASE_URI = ''
+# Locale
+LANGUAGES = {'en': 'English', 'zh': 'Chinese'}

+ 37 - 20
config.example/production.py

@@ -2,45 +2,62 @@
 # -*- coding=UTF-8 -*-
 # **************************************************************************
 # Copyright © 2016 jianglin
-# File Name: config.py
+# File Name: production.py
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 12:31:46 (CST)
-# Last Update:星期二 2016-6-14 23:42:32 (CST)
+# Last Update:星期二 2016-7-26 18:9:4 (CST)
 #          By: jianglin
 # Description:
 # **************************************************************************
 from datetime import timedelta
 
-DEBUG = True
-SECRET_KEY = ''
-SECURITY_PASSWORD_SALT = ''
+DEBUG = False
+SECRET_KEY = 'secret key'
+SECURITY_PASSWORD_SALT = 'you will never guess'
 
+# remember me to save cookies
 PERMANENT_SESSION_LIFETIME = timedelta(days=3)
 REMEMBER_COOKIE_DURATION = timedelta(days=3)
+ONLINE_LAST_MINUTES = 5
 
+# You want show how many topics per page
 PER_PAGE = 12
 
-# 定制缓存 = 60
+# Use cache
+CACHE_TYPE = 'redis'
 CACHE_DEFAULT_TIMEOUT = 60
 CACHE_KEY_PREFIX = 'cache:'
 CACHE_REDIS_HOST = '127.0.0.1'
-CACHE_REDIS_PORT = ''
-CACHE_REDIS_PASSWORD = ''
+CACHE_REDIS_PORT = '6379'
+CACHE_REDIS_PASSWORD = 'redis password'
 CACHE_REDIS_DB = 1
 
-# REDIS_PASSWORD = 'redis'
-# REDIS_DB = 1
 
-ONLINE_LAST_MINUTES = 5
+# Mail such as qq
+MAIL_SERVER = 'smtp.qq.com'
+MAIL_PORT = 25
+MAIL_USE_TLS = True
+MAIL_USE_SSL = False
+MAIL_USERNAME = 'Your domain email'
+MAIL_PASSWORD = 'Your password'
+MAIL_DEFAULT_SENDER = 'Your domain email'
+
+# Log,if SEND_LOGS is True when web app has some error happen(500)
+# the email will be sent to RECEIVER
+SEND_LOGS = False
+RECEIVER = ["yourname@gmail.com"]
+INFO_LOG = "info.log"
+ERROR_LOG = "error.log"
+
+# Sql
+SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:password@localhost/db_name'
+# SQLALCHEMY_DATABASE_URI = 'sqlite:////tmp/test.db'
+# SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/db'
+
 
-MAIL_SERVER = ''
-MAIL_PORT =
-MAIL_USE_TLS =
-MAIL_USE_SSL =
-MAIL_USERNAME = ''
-MAIL_PASSWORD = ''
-MAIL_DEFAULT_SENDER = ''
+# avatar upload folder
+AVATAR_FOLDER = 'avatars/'
 
-# SQLALCHEMY_TRACK_MODIFICATIONS = False
-SQLALCHEMY_DATABASE_URI = ''
+# Locale
+LANGUAGES = {'en': 'English', 'zh': 'Chinese'}

+ 3 - 1
maple/__init__.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 12:35:52 (CST)
-# Last Update:星期一 2016-7-25 11:11:52 (CST)
+# Last Update:星期二 2016-7-26 15:13:12 (CST)
 #          By:jianglin
 # Description:
 # **************************************************************************
@@ -19,6 +19,7 @@ from maple.extensions import (register_form, register_babel,
 from maple.extensions import register_rbac
 from flask_login import current_user
 from flask_sqlalchemy import SQLAlchemy
+from .logs import register_logging
 import os
 
 
@@ -48,6 +49,7 @@ def register(app):
     register_jinja2(app)
     register_maple(app)
     register_routes(app)
+    register_logging(app)
 
 
 def register_routes(app):

+ 1 - 1
maple/admin/admin.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-31 21:42:11 (CST)
-# Last Update:星期日 2016-7-24 20:2:3 (CST)
+# Last Update:星期二 2016-7-26 17:15:22 (CST)
 #          By:
 # Description:
 # **************************************************************************

+ 2 - 2
maple/extensions.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 13:02:50 (CST)
-# Last Update:星期一 2016-7-25 20:18:50 (CST)
+# Last Update:星期二 2016-7-26 16:55:5 (CST)
 #          By:
 # Description:
 # **************************************************************************
@@ -107,7 +107,7 @@ def register_redis(app):
 
 
 def register_cache(app):
-    cache = Cache(config={'CACHE_TYPE': 'redis'})
+    cache = Cache()
     cache.init_app(app)
     return cache
 

+ 1 - 1
maple/forums/forms.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-06-03 19:27:58 (CST)
-# Last Update:星期四 2016-7-14 20:35:37 (CST)
+# Last Update:星期二 2016-7-26 10:38:39 (CST)
 #          By:
 # Description:
 # **************************************************************************

+ 2 - 2
maple/forums/urls.py

@@ -6,14 +6,14 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-07-15 18:48:57 (CST)
-# Last Update:星期日 2016-7-24 22:3:29 (CST)
+# Last Update:星期二 2016-7-26 10:38:19 (CST)
 #          By:
 # Description:
 # **************************************************************************
 from flask import Blueprint
 from flask_login import login_required
 from .views import (index, forums, notice, userlist, message, about, help,
-                    order,contact)
+                    order, contact)
 
 site = Blueprint('forums', __name__)
 

+ 1 - 1
maple/forums/views.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 13:18:19 (CST)
-# Last Update:星期一 2016-7-25 21:0:0 (CST)
+# Last Update:星期二 2016-7-26 16:50:16 (CST)
 #          By:
 # Description:
 # **************************************************************************

+ 65 - 0
maple/logs.py

@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+# -*- coding=UTF-8 -*-
+# **************************************************************************
+# Copyright © 2016 jianglin
+# File Name: logs.py
+# Author: jianglin
+# Email: xiyang0807@gmail.com
+# Created: 2016-07-26 15:10:14 (CST)
+# Last Update:星期二 2016-7-26 16:38:55 (CST)
+#          By:
+# Description:
+# **************************************************************************
+import os
+import logging
+from logging.handlers import SMTPHandler
+from logging import Formatter
+
+
+def register_logging(app):
+    config = app.config
+    logs_folder = os.path.abspath(os.path.join(
+        os.path.dirname(__file__), os.pardir, 'logs'))
+    formatter = Formatter('''
+        Message type:       %(levelname)s
+        Location:           %(pathname)s:%(lineno)d
+        Module:             %(module)s
+        Function:           %(funcName)s
+        Time:               %(asctime)s
+
+        Message:
+
+        %(message)s
+        ''')
+
+    info_log = os.path.join(logs_folder, config['INFO_LOG'])
+
+    info_file_handler = logging.handlers.RotatingFileHandler(
+        info_log, maxBytes=100000, backupCount=10)
+
+    info_file_handler.setLevel(logging.INFO)
+    info_file_handler.setFormatter(formatter)
+    app.logger.addHandler(info_file_handler)
+
+    error_log = os.path.join(logs_folder, config['ERROR_LOG'])
+
+    error_file_handler = logging.handlers.RotatingFileHandler(
+        error_log, maxBytes=100000, backupCount=10)
+
+    error_file_handler.setLevel(logging.ERROR)
+    error_file_handler.setFormatter(formatter)
+    app.logger.addHandler(error_file_handler)
+
+    if app.config["SEND_LOGS"]:
+        credentials = (config['MAIL_USERNAME'], config['MAIL_PASSWORD'])
+        mailhost = (config['MAIL_SERVER'], config['MAIL_PORT'])
+        mail_handler = SMTPHandler(secure=(),
+                                   mailhost=mailhost,
+                                   fromaddr=config['MAIL_DEFAULT_SENDER'],
+                                   toaddrs=config['RECEIVER'],
+                                   subject='Your Application Failed',
+                                   credentials=credentials)
+
+        mail_handler.setLevel(logging.ERROR)
+        mail_handler.setFormatter(formatter)
+        app.logger.addHandler(mail_handler)

+ 1 - 1
maple/topic/forms.py

@@ -6,7 +6,7 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-05-20 18:08:44 (CST)
-# Last Update:星期四 2016-7-14 19:21:49 (CST)
+# Last Update:星期二 2016-7-26 17:27:30 (CST)
 #          By:
 # Description:
 # **************************************************************************

+ 6 - 5
maple/upload/views.py

@@ -6,14 +6,13 @@
 # Author: jianglin
 # Email: xiyang0807@gmail.com
 # Created: 2016-06-25 00:50:56 (CST)
-# Last Update:星期五 2016-7-15 19:34:7 (CST)
+# Last Update:星期二 2016-7-26 17:58:36 (CST)
 #          By:
 # Description:
 # **************************************************************************
-from flask import (url_for, redirect, flash, send_from_directory)
+from flask import (url_for, redirect, flash, send_from_directory, current_app)
 from flask_maple.forms import flash_errors
 from flask_login import login_required
-from maple import app
 from .forms import AvatarForm
 from .controls import UploadModel
 import os
@@ -33,8 +32,10 @@ def avatar():
 
 
 def avatar_file(filename):
-    avatar_path = os.path.join(app.static_folder, app.config['AVATAR_FOLDER'])
+    avatar_path = os.path.join(current_app.static_folder,
+                               current_app.config.get('AVATAR_FOLDER',
+                                                      'avatars/'))
     if not os.path.exists(os.path.join(avatar_path, filename)):
-        avatar_path = os.path.join(app.static_folder, 'images/')
+        avatar_path = os.path.join(current_app.static_folder, 'images/')
         filename = 'Moo.png'
     return send_from_directory(avatar_path, filename)

+ 8 - 4
templates/base/base.html

@@ -71,11 +71,11 @@
         </ul>
     </div>
     {% else  %}
-    <a href="{{ url_for('auth.register') }}" class="btn btn-sm btn-primary pull-right">{{ _('Register')}}</a>
-    <a href="{{ url_for('auth.login') }}" class="btn btn-sm btn-primary pull-right">{{ _('Login') }}</a>
+    {{ a_pull_right('auth.register',_('Register')) }}
+    {{ a_pull_right('auth.login',_('Login'))}}
     {% endif %}
-    <a href="{{ url_for('tag.tag')}}" ><span class="btn btn-sm btn-primary pull-right">{{ _('All Tags')}}</span></a>
-    <a href="{{ url_for('forums.userlist')}}"><span class="btn btn-sm btn-primary pull-right">{{ _('Userlist') }}</span></a>
+    {{ a_pull_right('tag.tag',_('All Tags'))}}
+    {{ a_pull_right('forums.userlist',_('Userlist'))}}
     <a href="{{ url_for('forums.notice')}}"><span class="btn btn-sm btn-primary pull-right">
         {{ _('Notices') }}
         <span class="badge">
@@ -88,3 +88,7 @@
     {% block content %} {% endblock %}
 </div>
 {% endblock %}
+
+{% macro a_pull_right(url,name) -%}
+<a href="{{ url_for(url) }}" class="btn btn-sm btn-primary pull-right">{{ name }}</a>
+{%- endmacro %}

+ 4 - 0
templates/base/notice.html

@@ -4,6 +4,7 @@
 <small class="pull-right">{{ notice.publish | timesince }}</small>
 <p style="margin-bottom:0px">{{ notice.content['content'] }}</p>
 {%- endmacro %}
+
 {% macro reply(notice) -%}
 {% set content = notice.content %}
 <small style="color:#999;"> {{ link_base.user(notice.send_user)}} 回复了你创建的主题:
@@ -12,6 +13,7 @@
 <small class="pull-right"> {{ notice.publish | timesince }} </small>
 <p style="margin-bottom:0px">{{ content["content"] | safe_clean }}</p>
 {%- endmacro %}
+
 {% macro collect(notice) -%}
 {% set content = notice.content %}
 <small style="color:#999;"> {{ link_base.user(notice.send_user)}} 收藏了你创建的主题:
@@ -19,6 +21,7 @@
 </small>
 <small class="pull-right"> {{ notice.publish | timesince }} </small>
 {%- endmacro %}
+
 {% macro like(notice) -%}
 {% set content = notice.content %}
 <small style="color:#999;"> {{ link_base.user(notice.send_user)}} 在
@@ -27,6 +30,7 @@
 <small class="pull-right"> {{ notice.publish | timesince }} </small>
 <p style="margin-bottom:0px">{{ content["content"] | safe_clean }}</p>
 {%- endmacro %}
+
 {% macro user(notice) -%}
 {% set content = notice.content %}
 <small style="color:#999;"> {{ link_base.user(notice.send_user)}} 关注了你 </small>

+ 2 - 0
templates/forums/about.html

@@ -1,6 +1,7 @@
 {% extends 'base/base.html' %}
 {% block content %}
 {{ breadcrumb(active=_('About')) }}
+{% cache 300 %}
 <div class="panel panel-primary">
     <div class="panel-heading">
         {{ _('About')}}
@@ -9,4 +10,5 @@
         about
     </div>
 </div>
+{% endcache %}
 {% endblock %}

+ 2 - 0
templates/forums/contact.html

@@ -1,6 +1,7 @@
 {% extends 'base/base.html' %}
 {% block content %}
 {{ breadcrumb(active=_('Contact me')) }}
+{% cache 300 %}
 <div class="panel panel-primary">
     <div class="panel-heading">
         {{ _('Contact me') }}
@@ -9,4 +10,5 @@
           root@honmaple.com
     </div>
 </div>
+{% endcache %}
 {% endblock %}

+ 2 - 0
templates/forums/help.html

@@ -1,6 +1,7 @@
 {% extends 'base/base.html' %}
 {% block content %}
 {{ breadcrumb(active=_('Help')) }}
+{% cache 300 %}
 <div class="panel panel-primary">
     <div class="panel-heading">
         {{ _('Help') }}
@@ -9,4 +10,5 @@
         help
     </div>
 </div>
+{% endcache %}
 {% endblock %}

+ 30 - 24
templates/forums/index.html

@@ -1,6 +1,34 @@
 {% extends 'base/base.html' %}
 {% block content %}
 {{ breadcrumb() }}
+{% cache 60 %}
+{{ index_title() }}
+<div class="row hidden-sm hidden-xs">
+    {{ item(_('Forums'),url_for('forums.forums'),"icon-comments","#F86334")}}
+    {{ item(_('Wiki'),url_for('docs.docs'),"icon-book","#eeccaa")}}
+    {{ item(_('Blog'),'#',"icon-tasks")}}
+    {{ item(_('Good'),url_for('topic.good'),"icon-globe","#017e66")}}
+</div>
+{% endcache %}
+<div class="row">
+    <div class="col-md-9">
+        <div class="panel panel-default">
+            {% from 'topic/topic_list.html' import view_no_form as board_view %}
+            {{ board_view(topics,top_topics)}}
+            <div class="panel-footer clearfix">
+                <a class="pull-right" href="{{ url_for('topic.good')}}">
+                    {{ _('more good topics') }}
+                    <i class="icon-arrow-right"></i>
+                </a>
+            </div>
+        </div>
+    </div>
+    <div class="col-md-3" style="padding-left:0">
+        {{ panel_base.index() }}
+    </div>
+</div>
+{% endblock %}
+{% macro index_title() -%}
 <div class="panel panel-default hidden-xs">
     <div class="panel-body" style="text-align: center;">
         <div class="media" style="width: 480px; margin:0px auto; text-align: left;">
@@ -18,6 +46,8 @@
         </div>
     </div>
 </div>
+{%- endmacro %}
+
 {% macro item(name,url,icon,color="#337ab7") %}
 <div class="col-md-3">
     <div class="panel panel-default">
@@ -35,27 +65,3 @@
     </div>
 </div>
 {%- endmacro %}
-<div class="row hidden-sm hidden-xs">
-    {{ item(_('Forums'),url_for('forums.forums'),"icon-comments","#F86334")}}
-    {{ item(_('Wiki'),url_for('docs.docs'),"icon-book","#eeccaa")}}
-    {{ item(_('Blog'),'#',"icon-tasks")}}
-    {{ item(_('Good'),url_for('topic.good'),"icon-globe","#017e66")}}
-</div>
-<div class="row">
-    <div class="col-md-9">
-        <div class="panel panel-default">
-            {% from 'topic/topic_list.html' import view_no_form as board_view %}
-            {{ board_view(topics,top_topics)}}
-            <div class="panel-footer clearfix">
-                <a class="pull-right" href="{{ url_for('topic.good')}}">
-                    {{ _('more good topics') }}
-                    <i class="icon-arrow-right"></i>
-                </a>
-            </div>
-        </div>
-    </div>
-    <div class="col-md-3" style="padding-left:0">
-        {{ panel_base.index() }}
-    </div>
-</div>
-{% endblock %}

+ 2 - 1
templates/topic/ask.html

@@ -72,7 +72,7 @@
                     </table>
                 </div>
                 <div class="col-sm-10" style="margin-bottom:8px;">
-                    {{ form.content(class="form-control",style="border-radius:0px;margin-top:0",rows="8",onchange="preview()",placeholder="请输入问题描述") }}
+                    {{ form.content(class="form-control",rows="8",onchange="preview()",placeholder="请输入问题描述") }}
                 </div>
                 <div class="col-sm-offset-2 col-sm-10">
                     {{ form.choice(class="input-sm pull-right",style="padding:2")}}
@@ -87,6 +87,7 @@
 </div>
 {% endblock %}
 
+
 {% macro html() -%}
 <tr>
     <td>b:</td>