Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Logging in Django
Search
Jakh Daven
March 21, 2013
Programming
15k
6
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Logging in Django
Jakh Daven
March 21, 2013
More Decks by Jakh Daven
See All by Jakh Daven
Developing Ubuntu Apps for fun and profit
tuxcanfly
0
100
Other Decks in Programming
See All in Programming
【QA Test Talk Vol.8】AI-DLC による Whole Team Approach の加速
pkshadeck
PRO
0
170
「寝てても仕事が進む」Claude Codeで組む第二の脳
tomoyafujita2016
0
330
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
140
琵琶湖の水は止められてもNet--HTTPのリトライは止められない / You might be able to stop the water flow of Lake Biwa but you can't stop Net::HTTP retries
luccafort
PRO
0
680
AI Engineeringは、AIプロダクトだけのものか? 〜AIがソフトウェアを作る時代の新しい当たり前〜 / No AI in your product. AI Engineering in your development.
rkaga
4
400
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
550
Apache Hive: そしてCloud Native Lakehouseへ
okumin
1
220
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.6k
Japan Community Day at Kubecon + CloudNativeCon Japan 2026: Learning Container Privilege Control by Building My Own Low-Level Container Runtime
ternbusty
1
150
夏だ!祭りだ!祭りとはドメインモデリングでは?
ryugen04
0
250
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
590
楽しそうなつよつよエンジニアと目が死んでる僕/A brilliant engineer having a blast, and dead-eyed me.
3l4l5
2
170
Featured
See All Featured
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
400
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
200
Designing for Performance
lara
611
70k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
We Have a Design System, Now What?
morganepeng
55
8.3k
A Soul's Torment
seathinner
6
3.4k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
940
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
490
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.5k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
480
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
Transcript
Logging in Django Javed Khan @tuxcanfly
Why bother • Archive of events • Hints for debugging
• Reproducing errors • Statistical Analysis
To log or not to log • Convenient message •
State variables • logger.debug(“details, details”) • logger.info(“Something wonderful is about to happen...”) • logger.warn(“I have a bad feeling about this”) • logger.error(“oops!”) • logger.critical(“oh no!”)
Teh codez from django.utils.log import getLogger logger = getLogger('django.request') if
request.method not in request_method_list: logger.warning('Method Not Allowed (%s): %s', request. method, request.path, extra={ 'status_code': 405, 'request': request } )
Terminology • formatters • filters • handlers • loggers
Log levels • debug • info • warning • error
• critical Other methods: • logger.log • logger.exception
Configuration - Dictconfig { 'version': 1, 'disable_existing_loggers': False, 'formatters': {
'standard': { 'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s' }, }, 'handlers': { 'default': { 'level':'INFO', 'class':'logging.StreamHandler', }, }, 'loggers': { '': { 'handlers': ['default'], 'level': 'INFO', 'propagate': True }, 'django.request': { 'handlers': ['default'], 'level': 'WARN', 'propagate': False }, } }
Configuration - Dictconfig formatters: 'formatters': { 'verbose': { 'format': '%(levelname)s
%(asctime)s %(module)s % (process)d %(thread)d %(message)s' }, 'simple': { 'format': '%(levelname)s %(message)s' }, }, asctime - 'Sun Jun 20 23:21:05 1993'.
Configuration - Dictconfig filters: 'filters': { 'require_debug_false': { '()': 'django.utils.log.RequireDebugFalse',
} }, 'handlers': { 'mail_admins': { 'level': 'ERROR', 'filters': ['require_debug_false'], 'class': 'django.utils.log.AdminEmailHandler' } }, class RequireDebugFalse(logging.Filter): def filter(self, record): return not settings.DEBUG
Configuration - Dictconfig handlers: 'handlers': { 'null': { 'level': 'DEBUG',
'class': 'django.utils.log.NullHandler', }, 'console':{ 'level': 'DEBUG', 'class': 'logging.StreamHandler', 'formatter': 'simple' }, 'mail_admins': { 'level': 'ERROR', 'class': 'django.utils.log.AdminEmailHandler', 'filters': ['special'] } },
Configuration - Dictconfig handlers: • logging.handlers.RotatingFileHandler • logging.handlers.TimedRotatingFileHandler • logging.handlers.SMTPHandler
• logging.handlers.HTTPHandler
Configuration - Dictconfig loggers: 'loggers': { 'django': { 'handlers': ['null'],
'level': 'INFO', }, 'django.request': { 'handlers': ['mail_admins'], 'level': 'ERROR', 'propagate': False, }, 'foo.bar: { 'handlers': ['console', 'mail_admins'], 'level': 'INFO', 'filters': ['special'] } }
Common uses - debug sql 'handlers': { 'console': { 'level':
'DEBUG', 'class': 'logging.StreamHandler' } }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, }, }
Common uses - filter sql 'filters': { 'sql_inserts': { '()':
'django.utils.log.CallbackFilter', 'callback': lambda x: 'INSERT' in x.msg } }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', 'propagate': True, 'filters': ['sql_inserts'], }, }
Bonus Custom log levels: APOCALYPSE = 55 logging.addLevelName(APOCALYPSE, "APOCALYPSE") logger.log(APOCALYPSE,
"The end.")
Gotchas Circular import in Django < 1.5 settings.py: ... 'handlers':
{ 'default': { 'level':'INFO', 'class':'foo.bar.FooBarHandler', }, }, ... foo/bar.py: from django.conf import settings class FooBarHandler(object): ...
Gotchas Exception handler leaks secrets from django.views.decorators.debug import sensitive_variables, sensitive_post_parameters
@sensitive_post_parameters('password', 'credit_card_number') @sensitive_variables('password', 'credit_card_number') def my_super_secret_view(request): password = request.POST['password'] credit_card_number = request.POST['credit_card_number'] ... ---------- DEFAULT_EXCEPTION_REPORTER_FILTER = 'path.to.your.CustomExceptionReporterFilter' SafeExceptionReporterFilter HIDDEN_SETTINGS = re.compile ('API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|SIGNATURE')