ログをわかりやすく表示
DBに格納するログがあまりにも役に立たなかったんで、テーブル自体も新調することに。
ちなみにSQL Serverです。
Logs | |
---|---|
id | int |
log_level | char(5) |
message | nvarchar(255) |
time_and_date | datetime |
Exceptions | |
---|---|
id | int |
l_id | int |
name | nvarchar(64) |
StackTraces | |
---|---|
id | int |
e_id | int |
line | nvarchar(255) |
こんな感じのテーブル。
全部のログが例外を持っているわけではないからテーブルとしては分割しておいた。
スタックトレースは直接入れてもよかったけど、ntext型は使いたくなかった*1んで、行ごとに分割してnvarchar(255)として入れることに。
で、Management Studioで直接ログを見るときは、
SELECT L.time_and_date AS '日時' , L.log_level AS 'ログレベル' , L.message AS 'メッセージ' , E.name AS '例外クラス' , ST.line AS 'スタックトレース' FROM Logs L LEFT OUTER JOIN Exceptions E ON L.id = E.l_id LEFT OUTER JOIN StackTraces ST ON E.id = ST.e_id ORDER BY L.id, E.id, ST.id
な感じでいいんだけど、誰々曰く「ログレベルとかメッセージとか、いちいち同じ内容のものが出てわかりにくい!スタックトレースもぶっちゃけ最後のあたりだけでいい!!」だそうで。
なら削ればいいじゃない、ということでこんなSQL
SELECT -- ログレベル -- 例外IDが同じで、自分より小さいIDがあるなら表示しない CASE WHEN EXISTS(SELECT * FROM StackTraces CST WHERE E.id = CST.e_id AND CST.id < ST.id) THEN '' ELSE L.log_level END AS 'ログレベル' -- メッセージ -- 例外IDが同じで、自分より小さいIDがあるなら表示しない , CASE WHEN EXISTS(SELECT * FROM StackTraces CST WHERE E.id = CST.e_id AND CST.id < ST.id) THEN '' ELSE L.message END AS 'メッセージ' -- 例外クラス -- 例外IDが同じで、自分より小さいIDがあるなら表示しない -- そもそも例外を持たないログの場合は「なし」と表示 , CASE WHEN EXISTS(SELECT * FROM StackTraces CST WHERE E.id = CST.e_id AND CST.id < ST.id) THEN '' ELSE coalesce(E.name, 'なし') AS '例外クラス' -- スタックトレース(概要) -- スタックトレースの各行の後ろ32文字分を表示 -- そもそもスタックトレースを持たないログの場合は「なし」と表示(NULLと文字列を連結しても結果はNULL) , coalesce('...' + right(ST.line, 32), 'なし') AS 'スタックトレース' , L.time_and_date AS '日時' FROM Logs L LEFT OUTER JOIN Exceptions E ON L.id = E.l_id LEFT OUTER JOIN StackTraces ST ON E.id = ST.e_id ORDER BY L.id, E.id, ST.id
それにしてもスタイルが定まらない・・・
*1:DBはSQL Server2000だけど、SQL Server2005のツールを使っているからいろいろと紛らわしくなる