Home 3. NLog
Post
Cancel

3. NLog

NLog 시작

  • Serilog는 사용 못한다고 치고.. NLog를 찾기로함. 여기서 안되면 포기.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    public class logger_2
    {
        public logger_2()
        {
            var target = new NLog.Targets.FileTarget();
            target.Name = "file_1";
            target.FileName = "D:\\logs\\file_1.txt";
            target.Layout = "${date:format=HH\\:MM\\:ss} ${logger} ${message}";
    
            var target_2 = new NLog.Targets.FileTarget();
            target_2.Name = "file_2";
            target_2.FileName = "D:\\logs\\file_2.txt";
            target_2.Layout = "${date:format=HH\\:MM\\:ss} ${logger} ${message}";
    
            var config = new NLog.Config.LoggingConfiguration();
            config.AddTarget(target.Name, target);
            config.AddTarget(target_2.Name, target_2);
    
            var rule = new NLog.Config.LoggingRule("*", LogLevel.Info, target);
            var rule_2 = new NLog.Config.LoggingRule("*", LogLevel.Info, target_2);
    
            config.LoggingRules.Add(rule);
            config.LoggingRules.Add(rule_2);
    
            LogManager.Configuration = config;
    
            var _logger = LogManager.GetLogger(target.Name);
            _logger.Info("Logger1 is initialized");
            LogManager.Flush();            
            var _logger_2 = LogManager.GetLogger(target_2.Name);
            _logger_2.Info("Logger2 is initialized");
        }
    }
    
    • 간단하게 쓰는 방법을 정리해 본건데 Serilog랑 쓰는건 비슷하기도 하고 간단해 보임.
    • 근데 확실히 다른점이 보이는데 이 차이 때문에 이거 될것같음 느낌이 좋음
    • NLog는 target로 Log를 어떻게, 어디에 쓸지 정의하는데 이게 console, file, db인데 (Serilog도 쌉가능) 보기에 target를 여러개 만들수 있고 그걸 AddTarget해서 쓴다는게 확연히 달라보임.
    • 단, config가 global인듯해보임.
    • 결론만 말하면 위 방식대로 하면 안됨. 세상에ㅁ재댤;ㅣ좋ㅁㄷㄱ
    • 원하는건 file_1.txt랑 file_2.txt가 각각 만들어지고 각각 따로 message를 찍을것 같은데 log내용이 아래같음.
      1
      2
      
      13:04:31 file_1 Logger1 is initialized
      13:04:31 file_2 Logger2 is initialized
      

      file_1, file_2가 만들어지고 위 message가 둘 파일에 같이 찍힘.

    • 근데 또 찾은 자료 중에 이렇게 하면 대충 된다고 하는걸 찾았는데1 내가 위에 한 방법에서 특별히 뭐 더 한것같지는 않은데 그냥 아무튼 안됨. 뭘 하던 저렇게 다른 파일을 상성하고 같은로그를 같이씀…
    • 근데 나랑 같은 문제로 NLog에 issue남긴걸 봤는데2 3 4 저 세 뭉탱이가 다 관련되어 보임. 정확히 같은 이유로 같은 구조로 만들길 원했고 이슈 닫은걸로보아 해결한것같음…

config 교체??

  • 그럼 상황에 따라 내가 쓰고싶은 Config를 AddTarget까지 해서 만들어 놓고 관리한다. -> 내가 쓰고싶은 Log에 맞는 config를 상황에 맞춰 NLog config에 덮어쓰고 Log를 쓴다
  • 느낌이 좋음
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    
    public class Logger
    {
        NLog.Config.LoggingConfiguration config;
        NLog.Logger logger;
    
        string logPath;
        string logName;
    
        //StackTrace st = new StackTrace();
        //StackFrame sf = new StackFrame(1, true);
        string id;
        public Logger()
        {
            this.id = Guid.NewGuid().ToString();
            config = new NLog.Config.LoggingConfiguration();
    
            NLog.Targets.FileTarget logfile = new NLog.Targets.FileTarget();
            logfile.FileName = "D:\\logs\\file_1.txt";
            logfile.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
              
            NLog.Targets.ConsoleTarget logconsole = new NLog.Targets.ConsoleTarget();
            logconsole.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
            NLog.Targets.DebuggerTarget de = new NLog.Targets.DebuggerTarget();
            de.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
    
            NLog.Targets.FileTarget logfile_2 = new NLog.Targets.FileTarget();
            logfile_2.FileName = "D:\\logs\\file_2.txt";
            logfile_2.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile);
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile_2);
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, de);
    
    
            config.AddTarget(this.id, logfile);
            // Apply config           
            NLog.LogManager.Configuration = config;
            logger = NLog.LogManager.GetLogger(this.id);
        }
    
        public Logger(string _path, string _name)
        {
            this.id = Guid.NewGuid().ToString();
    
            NLog.Targets.FileTarget logfile = new NLog.Targets.FileTarget();
            logfile.FileName = Path.Combine(_path, _name+"_${shortdate}.log");
            logfile.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
            logfile.Name = this.id;
              
            NLog.Targets.ConsoleTarget logconsole = new NLog.Targets.ConsoleTarget();
            logconsole.Layout = "${longdate} ${level:uppercase=true:truncate=5} \t ${message}";
            config = new NLog.Config.LoggingConfiguration();
            config.AddRule(LogLevel.Trace, LogLevel.Fatal, logfile);
            config.AddTarget(this.id, logfile);
              
            // Apply config           
            NLog.LogManager.Configuration = config;
            logger = NLog.LogManager.GetLogger(this.id);
        }
    
        public void LogFile(string _msg)
        {
            StackTrace st = new StackTrace();
            LogManager.Configuration = this.config;
            LogManager.ReconfigExistingLoggers();
            (LogManager.GetLogger(this.id)).Trace("[{0}][{1}]\t" + _msg, st.GetFrame(1).GetMethod().ReflectedType.Name, st.GetFrame(1).GetMethod().Name);
        }
    
        public void LogConsole()
        {
    
        }
    }
    
    • 테스트 하다가 바꾼게 많이서 정확하진 않은데 대충 이런 컨셉인데 위 Logger class를 넣어두는 dictionary가 하나 더 있었을거임 key는 id고 value가 Logger class.
    • 무튼 이건 내가 생각하는것처럼 동작함 끝임
    • 근데 아니네 매쟏러 ;ㅐㄷㄱㅎ ;ㅐㅣㄹ
    • 되는것처럼 보였는데 thread여러개 두고 테스트 해보면 가끔 A.txt에 쓰여져야할 Log가 B.Log에 쓰여짐
    • 이 현상은 규칙성도 안보이고 간헐적이라 … 사실 써도 가끔 한두줄이긴해서 써도 될것같았는데(고민 많이함) 전에 쓰던것도 이렇게 넘어가다 프로그램이 뻗었겠지…

Logfactory를 이용한 방법

  • 여기까지 내용은 얼마 안되보이고 테스트 내용도 사실 별 어려운 내용은 아님
  • 문제는
    • 보통 이 문제에 대해 검색해보면 log level에 따른 분류는 많아도 그 외 의도적으로(나처럼) Log를 나누는 자료는 없었음 당장 이거하기위해 찾으면서 딱 한번 직접적으로 질문한거 딱 한번봄
    • 안될꺼면 그냥 깔끔하게 안됐다면 포기했을텐데 file나누는건 성공하고 log를 모든파일에 동일하게 쓰거나(file이름만 다르지 내용은 같아짐) file가 안나눠지고 모든 내용이 한곳에 쓰인다거나, 로그가 섞여 쓰여지는등 됫듯말듯 안되니 내가좀 놓치고 있는게 아닌가 싶었음
    • 여기까지 찾는데 널널하게 한달정도 삽질한듯.
  • 그러다가 우연히 찾은게 하나 더 있는데 이건 어디서 찾았는지 출처가 없어짐………그사람들 복받았음좋겠다. 근데 아마 원래 쓸 수 있는 config랑 관계였나 그런거 찾다가 얻어걸린걸로 기억함…
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    public void mtd_2()
    {
        NLog.Config.LoggingConfiguration conf_1 = new NLog.Config.LoggingConfiguration();
        var target_1 = new NLog.Targets.FileTarget("targtet_1");
        target_1.FileName = "D:\\log\\1.txt";
        target_1.Layout = "${longdate} ${uppercase:${level}} ${message}";
        conf_1.AddTarget(target_1);
        conf_1.AddRule(LogLevel.Info, LogLevel.Fatal, target_1);
        NLog.LogFactory fac_1 = new LogFactory(conf_1);
    
        NLog.Logger log_1 = fac_1.GetLogger("loger_1");
        log_1.Info("log 1");
    
    
        NLog.Config.LoggingConfiguration conf_2 = new NLog.Config.LoggingConfiguration();
        var target_2 = new NLog.Targets.FileTarget("targtet_2");
        target_2.FileName = "D:\\log\\2.txt";
        target_2.Layout = "${longdate} ${uppercase:${level}} ${message}";
        conf_2.AddTarget(target_2);
        conf_2.AddRule(LogLevel.Info, LogLevel.Fatal, target_2);
        NLog.LogFactory fac_2 = new LogFactory(conf_2);
    
        NLog.Logger log_2 = fac_2.GetLogger("loger_2");
        log_2.Info("log 2");
    }
    
    • 이렇게 쓰는데 이 전처럼 conf를 만들고 target를 등록하는것까지 같은데 이걸 바로 NLog에 넣는게 아니라 LogFactory를 만들어 LogFactory에서 Logger를 받아오는식임 그러니까 이 전위 단계 중 LogFactory가 한단계 더 들어감
    • 이거 결과는 1.txt 생성, 2.txt생성 후 각각의 파일에 내용도 따로 쓴다. 내가 찾던거임.
  • 여기까지 내가 쓰고자 하는거 기본은 만들어진것같음…

last test

  • 그럼 하나더 테스트.
    • main
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      
        class NLogMain
        {
            static void Main(string[] args)
            {
      
                Logger_4 log4 = new Logger_4(@"D:\logs", "log_main");
                log4.info("in main, log init");
      
                temp temp = new temp();
                temp_2 temp_2 = new temp_2();
                Lib lib = new Lib();
      
            }
        }
      
        class temp
        {
            Logger_4 log4 = new Logger_4(@"D:\logs", "log_temp1");
                
            public temp()
            {
                try
                {
                    ThreadStart threadStart = new ThreadStart(run);
                    Thread th = new Thread(threadStart);
                    th.Start();
                }
                catch (Exception ex)
                {
                }
            }
      
            void run()
            {
                while (true)
                {
                    Thread.Sleep(500);
                    log4.info("temp1 msg");
                }
            }
      
            public void throwtest()
            {
                try
                {
                    int i = 0;
                    int ii = 1 / i;
                }
                catch (Exception e)
                {
      
                    throw;
                }
            }
        }
      
        class temp_2
        {
            Logger_4 log4 = new Logger_4(@"D:\logs", "log_temp2");
      
            public temp_2()
            {
                ThreadStart threadStart = new ThreadStart(run);
                Thread th = new Thread(threadStart);
                th.Start();
            }
      
            void run()
            {
                while (true)
                {
                    Thread.Sleep(500);
                    log4.info("temp2 msg");
                }
            }
        }
      
    • lib
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      
      public class Lib
      {
          Logger_4 log_1 = new Logger_4(@"D:\logs", "lib_1");
          Logger_4 log_2 = new Logger_4(@"D:\logs", "lib_2");
          Logger_4 log_3 = new Logger_4(@"D:\logs", "log_temp2");
      
          public Lib()
          {
              asdf();
              ThreadStart threadStart = new ThreadStart(run);
              Thread th = new Thread(threadStart);
              th.Start();
          }
      
          private void asdf()
          {
              log_1.info("lib1 msg");
          }
      
          void run()
          {
              while (true)
              {
                  Thread.Sleep(500);
      
                  log_1.info("lib1 msg");
                  log_2.info("lib2 msg");
                  log_3.info("lib3 msg");
                  //break;
              }
          }
      }
      
    • logger lib
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      
      public class Logger_4
      {
          private NLog.Logger logger;
      
          public Logger_4(string _path, string _name)
          {
              NLog.Config.LoggingConfiguration conf = new NLog.Config.LoggingConfiguration();
                  
              NLog.Targets.FileTarget target = new NLog.Targets.FileTarget(_name);
              target.FileName = Path.Combine(_path, _name + "_${shortdate}.log");
              target.Layout = "${longdate} ${uppercase:${level}} ${message}";
      
              conf.AddTarget(target);
              conf.AddRule(LogLevel.Trace, LogLevel.Fatal, target);
                  
              NLog.LogFactory logfac = new LogFactory(conf);
              this.logger = logfac.GetLogger(_name);
                  
          }
      
          public void info(string _msg)
          {
              this.logger.Info(_msg);
          }
      
      }
      
    • 설명
      • main은 lib, temp1, temp2를 참조함.
      • main, lib, temp1, temp2 는 loglib를 참조함.
      • main은 main용 로그, temp1,2는 각각 로그를 남기고 lib는 lib1, lib2, lib3 log를 각각 남기는데 lib3은 temp2와 같은곳에 남긴다.
    • 이지랄 떠는게 이렇게까진 쓸것같진 않은데 이렇게 비슷하게 쓰긴 했었음
    • 결과는 잘 됨. config만 갈아끼우며 사용하는식처럼 log가 섞이지도 않음 .
    • 드디어 이걸로 기본 준비는 다 끝난듯하다.

참고

This post is licensed under CC BY 4.0 by the author.

2. Serilog

Markdown

Comments powered by Disqus.