Nine MVP's Blog

21/04/2012

Application Design : Logging 2

Filed under: Core System — Tags: , — Nine MVP @ 6:58 pm

ตอนที่แล้ว
https://nine69.wordpress.com/2012/03/15/application-design-logging-1/

ในตอนนี้ขอลงรายละเอียดเรื่องราวทั้งหมดนี้ครับ

  1. การใช้งาน NLog เบื้องต้นกับ .NET Application
  2. การ config Alternate Source
  3. แนวคิดการเก็บ Audit Data ของข้อมูลในระบบ

ต่อไปสำหรับการเก็บ Log ของการทำงานใน Application นั้น จะขอแนะนำการใช้งาน

NLog Framework

มาทำความรู้จักเจ้า NLog กัน  โดย NLog เป็น Logging Framework ที่มีความสามารถและประสิทธิภาพในการทำงานที่อยู่ในระดับที่ดี ซึ่งสามารถทำการบันทึก log ได้หลากหลายชนิด บันทึก log พร้อมกันได้หลายชนิดในรูปแบบข้อมูลที่สามารถกำหนดให้แตกต่างกันได้ เพียงแค่ทำการ config เท่านั้นหรือจะเขียนโปรแกรมกำหนดก็ได้  สามารถกำหนด buffer ของการเขียน  ทำการบันทึกแบบ async ทำ load balancing และรองรับ Failover  รวมไปถึงสามารถนำไปใช้กับ .NET/ SliverLight / Windows Phone/ Mono ได้อีกด้วย 

Target Source ที่รองรับ

  • Files – บันทึกลงไฟล์เดียวหรือจะหลาย file, กำหนดให้ rename หรือจะ zip ด้วยก็ได้ แถมยังกำหนด size ของ file เพื่อให้ split file ออกตามขนาดที่กำหนดก็ได้
  • Event Log – สามารถบันทึกแบบ local และ remote ก็ได้
  • Database – เก็บ log ลง database
  • Network – ยิง log ออกไปด้วย protocol ชนิดต่าง ๆ ไม่ว่าจะ TCP, UDP, SOAP, MSMQ เป็นต้น
  • Command-line- สามารถ show log ออก console app ได้ด้วยสีสันต่าง ๆ
  • E-Mail – กำหนดให้ส่ง email ออกไปตาม config
  • ASP.NET trace – บันทึกเข้าไว้ใน trace ของ asp.net

เริ่มต้นใช้งาน NLog เบื้องต้น

    สำหรับหัวข้อต่อไปต้องใช้ Software ต่อไปนี้

  1. Visual Studio 2005 ขึ้นไป (บทความใช้ VS2010)
  2. NuGet  (download here)
  3. MS SQL
  4. Internet

เปิด Visual Studio ขึ้นมาแล้วทำการสร้าง Console Project ตามภาพ

image

เสร็จแล้วจะได้โปรเจ็คตามภาพด้านล่างนี้

image

ต่อไปให้ทำการเรียก Package Manager Console ขึ้นมาเพื่อทำการติดตั้งตัว NLog ในโปรแกรมของเรา

image

หลังจากได้ Package Manager Console Window มาแล้วก็ทำการรันคำสั่งด้านล่างนี้

PM> Install-Package NLog

ก็จะได้ output ต่อท้ายว่า

Successfully installed ‘NLog 2.0.0.2000’.

Successfully added ‘NLog 2.0.0.2000’ to NLog01.

จากนั้นให้ติดตั้งตั้ว Schema ของ NLog เพิ่มดังนี้

PM> Install-Package NLog.Schema

ก็จะได้ output ต่อท้ายว่า

Attempting to resolve dependency ‘NLog.Config (≥ 2.0.0.0)’.

Attempting to resolve dependency ‘NLog (≥ 2.0.0.2000)’.

Successfully installed ‘NLog.Config 2.0.0.2000’.

Successfully installed ‘NLog.Schema 2.0.0.2000’.

Successfully added ‘NLog.Config 2.0.0.2000’ to NLog01.

    เข้าไปดูใน Project เพื่อตรวจสอบจะต้องได้ภาพตามนี้

    image

    จากนั้นเปิด file NLog.config มาแก้ไขตามนี้

image

อธิบาย config

1: เปลี่ยนไปตาม .NET Framwork version ที่ใช้งานในโปรเจ็ค

2: ทำการใช้งาน target source แบบ File โดยกำหนด option

– fileName :  ให้เก็บ log ไว้ที่เดียวกับที่โปรแกรมอยู่ และสร้าง log folder ขึ้นถ้่าหากไม่มี /  ตามด้วยชื่อไฟล์ โดยเอา date format ตามด้วย .log

– layout :  เมื่อจะเขียน log ทุก level จะต้องเขียนด้วย format ของ วันที่ LEVEL และตามด้วย ข้อความของ Log ที่จะบันทึก

3: บอกตัว log ให้ทำการบันทึกลง Target Source ใดๆบ้าง

– minlevel :  กำหนดไว้ต่ำสุดที่ Trace Level

– writeTo :  อ้างไปยัง target source ที่ชื่อว่า file (ในข้อ2) 

    จากนั้นให้เปิด Program.cs ขึ้นมาเพื่อแก้ไข Code ตามตารางด้านล่างนี้

    Code Snippet
    1. using System;
    2. using NLog;
    3.  
    4. namespace NLog01
    5. {
    6.     public class Program
    7.     {
    8.         //  NLog instance
    9.         private static Logger logger = LogManager.GetCurrentClassLogger();
    10.  
    11.         private static void Main(string[] args)
    12.         {
    13.             TestLog(); //  method  test
    14.             Console.ReadLine();
    15.         }
    16.  
    17.         public static void TestLog()
    18.         {
    19.             logger.Trace("Test trace message");
    20.             logger.Debug("Test debug message");
    21.             logger.Info("Test informational message");
    22.             logger.Warn("Test warning message");
    23.             logger.Error("Test error message");
    24.             logger.Fatal("Test fatal error message");
    25.             //  Log() method  Level
    26.             logger.Log(LogLevel.Info, "Test fatal error message");
    27.         }
    28.     }
    29. }

    อธิบาย code

    1. line2: เรียกใช้ namespace ของ NLog

    2. line17-27:  เป็นการทดสอบเขียน Log ใน Level ต่าง ๆ  รวมไปถึงการกำหนด level ผ่าน Log() method ได้เอง

    3. line13:  เรียกใช้ TestLog() ที่ได้เขียนไว้

      จากนั้นก็ทดสอบ run โดยกด F5 ก็จะได้หน้าต่างดำๆ ค้างนิ่งอยู่ตามภาพ และกด Enter หรือ Key อื่น ๆ ลงไปเพื่อจบโปรแกรม

      image

      กลับมาที่ Visual Studio แล้วไปที่ Solution Explorer แล้วกดตามลำดับหมายเลขในรูปด้านล่าง

      image

    4. เลือกโปรเจ็ค
    5. กดเพื่อดู file/folder ทั้งหมดในโปรเจ็ค
    6. กดเข้าไปใน bin –> Debug –> logs –> จะพบ file log เกิดขึ้นใน folder ดังกล่าว
    7. เปิด file log ขึ้นมาเพื่อดูผลลัพธ์ ก็จะพบ log message ที่เราได้สั่งบันทึกไปตามรูปด้านล่าง image
    8. จากนั้นหากเราจะกำหนดให้ File Target จำกัดขนาดของ log file และ split ออกตามขนาดเพื่อความง่ายในการเปิดมาอ่าน โดยเปิดให้เพิ่ม config เข้าไปตามนี้
      Code Snippet
      1. <?xml version="1.0" encoding="utf-8" ?>
      2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.netfx40.xsd"
      3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" internalLogFile="int.log">
      4.      <!–See http://nlog-project.org/wiki/Configuration_file   
      5.   for information on customizing logging rules and outputs.   –>
      6.   <targets>
      7.     <!– add your targets here –>
      8.     <target xsi:type="File" name="file" fileName="${basedir}/logs/${shortdate}.log"
      9.             layout="${longdate} ${uppercase:${level}} ${message}"
      10.             archiveEvery="Day"
      11.             archiveAboveSize="10000"
      12.             archiveNumbering="Sequence" />
      13.   </targets>
      14.   <rules>    
      15.     <!– add your logging rules here –>
      16.     <logger name="*" minlevel="Trace" writeTo="file" />
      17.   </rules>
      18. </nlog>

    9.  เสร็จแล้วไปปรับ Code ใน Program.cs มาแก้ไข TestLog() ใหม่ตามนี้ เพื่อจำลองสร้าง log file ขนาดใหญ่

    Code Snippet
    1. public static void TestLog()
    2. {
    3.     for (int i = 0; i < 500; i++)
    4.     {
    5.         logger.Trace("Test trace message");
    6.         logger.Debug("Test debug message");
    7.         logger.Info("Test informational message");
    8.         logger.Warn("Test warning message");
    9.         logger.Error("Test error message");
    10.         logger.Fatal("Test fatal error message");
    11.         //  Log() method  Level
    12.         logger.Log(LogLevel.Info, "Test fatal error message");
    13.     }
    14. }

    -10.  ทดลองรันโปรแกรมดูด้วยการกด F5 แล้วกลับไปดูใน Log Folder จะพบ log file หลากตัวเกิดขึ้นเนื่องจากเรากำหนด size ของไฟล์ไว้นั้นเอง

    image

    และเราก็ยังสามารถ config เพิ่มเติมได้อีกมากมายสามารถเข้าไปอ่านรายละเอียดได้ที่นี่ http://nlog-project.org/wiki/File_target

    การเก็บ log ใน Event Log ของ Windows

    ต่อไปเราจะเก็บ log ลงไปใน Event Log มีขั้นตอนดังนี้    

    1.  ไปที่ Solution Explorer และเปิด NLog.config ขึ้นมาเพื่อแก้ไข

    2. เพิ่ม config เข้าไปตามตารางด้านล่าง

    Code Snippet
    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.netfx40.xsd"
    3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" internalLogFile="int.log">
    4.      <!–See http://nlog-project.org/wiki/Configuration_file   
    5.   for information on customizing logging rules and outputs.   –>
    6.   <targets>
    7.     <!– add your targets here –>
    8.     <target xsi:type="File" name="file" fileName="${basedir}/logs/${shortdate}.log"
    9.             layout="${longdate} ${uppercase:${level}} ${message}"
    10.             archiveEvery="Day"
    11.             archiveAboveSize="10000"
    12.             archiveNumbering="Sequence" />
    13.     <target xsi:type="EventLog" name="evl" layout=" ${longdate}|${level:uppercase=true}|${logger}|${message}"
    14.             machineName="NINE-WNB"
    15.             source="NLog01" eventId="9001" log="Application" />
    16.   </targets>
    17.   <rules>    
    18.     <!– add your logging rules here –>
    19.     <logger name="*" minlevel="Trace" writeTo="file" />
    20.     <logger name="*" minlevel="Trace" writeTo="evl" />
    21.   </rules>
    22. </nlog>

      line13-15:  เป็นการเพิ่ม event log target เข้าไป

      line14: อย่าลิมแก้เป็นชื่อ computer name ของตัวเองนะครับ

      3.  จากนั้นกลับไปแก้ file Program.cs ใน method TestLog() โดยลบ For Loop ออกตามด้านล่างนี้

      Code Snippet
      1. public static void TestLog()
      2. {
      3.     logger.Trace("Test trace message");
      4.     logger.Debug("Test debug message");
      5.     logger.Info("Test informational message");
      6.     logger.Warn("Test warning message");
      7.     logger.Error("Test error message");
      8.     logger.Fatal("Test fatal error message");
      9.     // custom log level
      10.     logger.Log(LogLevel.Info, "Test fatal error message");
      11. }

      4.  และทำการ กด F5 เพื่อรันโปรแกรมทดสอบ กด Enter เพื่อจบโปรแกรม

      5.. เสร็จแล้วไปเปิด Start –> Administrative Tools –> Event Viewer เพื่อดูผลก็จะพบ log ที่เราสั่งบันทึกไปตามรูปด้านล่าง

      image

    การเก็บ log ลงใน Database

    เริ่มต้นด้วยการสร้าง Database ใน MS SQL ชื่อว่า Logging

    จากนั้นนำ script ไปสร้าง Table ใน Database ด้วย script ด้านล่างนี้

    Code Snippet
    1. CREATE TABLE [dbo].[MyLog](
    2.     [Id] [bigint] IDENTITY(1,1) NOT NULL,
    3.     [CreateDate] [varchar](50) NULL,
    4.     [Origin] [nvarchar](50) NULL,
    5.     [Level] [varchar](50) NULL,
    6.     [Message] [nvarchar](1000) NULL,
    7.     [Exception] [nvarchar](max) NULL,
    8.     [StackTrace] [nvarchar](4000) NULL,
    9.     [Module] [varchar](100) NULL,
    10.     [User] [nvarchar](200) NULL,
    11. CONSTRAINT [PK_MyLog] PRIMARY KEY CLUSTERED
    12. (
    13.     [Id] ASC
    14.   )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS= ON) ON [PRIMARY]
    15. ) ON [PRIMARY]
    16.  
    17. GO

    เมื่อสร้าง Database และ Table ตาม script ตามข้างต้นเสร็จแล้ว

    กลับมาที่ Visual Studio ไปเปิดไฟล์ NLog.config ขึ้นมาเพื่มค่าตามตารางด้านล่างนี้

    Code Snippet
    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <nlog xmlns="http://www.nlog-project.org/schemas/NLog.netfx40.xsd"
    3.       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" internalLogFile="int.log">
    4.      <!–See http://nlog-project.org/wiki/Configuration_file   
    5.   for information on customizing logging rules and outputs.   –>
    6.   <targets>
    7.     <!– add your targets here –>
    8.     <target xsi:type="File" name="file" fileName="${basedir}/logs/${shortdate}.log"
    9.             layout="${longdate} ${uppercase:${level}} ${message}"
    10.               archiveEvery="Day"archiveAboveSize="10000" archiveNumbering="Sequence" />
    11.     <target xsi:type="EventLog" name="evl" layout=" ${longdate}|${level:uppercase=true}|${logger}|${message}"
    12.             machineName="NINE-WNB" source="NLog01" eventId="9001" log="Application" />
    13.     <target xsi:type="Database" name="db" keepConnection="false"
    14.             useTransactions="true"
    15.             connectionString="Data Source=NINE-WNB\MSSQL2K8R2;Initial Catalog=LoggingDB;Integrated Security=True">
    16.       <commandText>
    17.         insert into MyLog ([CreateDate], [Origin], [Level], [Message], [Exception], [StackTrace], [Module], [User]) values (@createDate, @origin, @logLevel, @message, @exception, @stackTrace, @module, @user);
    18.       </commandText>
    19.       <parameter name="@createDate" layout="${longdate}"/>
    20.       <parameter name="@origin" layout="${callsite}"/>
    21.       <parameter name="@logLevel" layout="${level}"/>
    22.       <parameter name="@message" layout="${message}"/>
    23.       <parameter name="@exception" layout="${exception:format=Message,StackTrace}"/>
    24.       <parameter name="@stackTrace" layout="${stacktrace}"/>
    25.       <parameter name="@module" layout="${mdc:item=module}"/>
    26.       <parameter name="@user" layout="${mdc:item=user}"/>
    27.     </target>
    28.     
    29.   </targets>
    30.   <rules>    
    31.     <!– add your logging rules here –>
    32.     <logger name="*" minlevel="Trace" writeTo="file" />
    33.     <logger name="*" minlevel="Trace" writeTo="evl" />
    34.     <logger name="*" minlevel="Trace" writeTo="db" />
    35.   </rules>
    36. </nlog>

    อธิบาย config

    1: line3: ตรง option internalLogFile จะเป็นการบันทึกหากเกิด error จากการทำงานของ NLog

    2: line13-29:  จะเป็นการเพิ่ม database target เข้ามาใน NLog โดยค่า default จะเป็น driver ของ MSSQL

    3: line15: ให้แก้เป็น connection string ของเครื่องตัวเองครับ

    4: line25,26: เป็นการอ้างถึงค่าเพิ่มเติมที่ต้องการจะส่งมาจากโปรแกรมเพื่อบันทึกลง log table

    5: line 34: เป็นการสั่งให้ NLog ทำการบันทึกลง Target ที่ชื่อ db

     

    ต่อไปเปิดไฟล์ Program.cs เพื่อแก้ไขโค้ดตามตารางด้านล่างนี้

    Code Snippet
    1. public static void TestLog()
    2. {
    3.     //Assign variable value
    4.     NLog.MappedDiagnosticsContext.Set("module", "Main Program");
    5.     NLog.MappedDiagnosticsContext.Set("user", "Nine");
    6.  
    7.     //write log
    8.     logger.Trace("Test trace message");
    9.     logger.Debug("Test debug message");
    10.     logger.Info("Test informational message");
    11.     logger.Warn("Test warning message");
    12.     logger.Error("Test error message");
    13.     logger.Fatal("Test fatal error message");
    14.  
    15.     // custom log level
    16.     logger.Log(LogLevel.Info, "Test fatal error message");
    17. }

    จากโค้ดด้านบนเป็นการส่งค่าที่ต้องการจะบันทึก จากโปรแกรมลง Log Table เพื่อเก็บ User ที่ทำรายการ และ Module ที่ทำการบันทึก Log ในครั้งนี้

    ทำการกด F5 เพื่อทดสอบ

    กด Enter เพื่อจบโปรแกรม

    และลองไปเปิด Table ใน Database ดูจะได้ผลลัพธ์ตามภาพด้านล่าง

    image

    ตัว NLog ยังรองรับ Database อีกหลายชนิดไม่แต่เพียง MS SQL Server เพียงอย่างเดียว

    จึงจบการสอนใช้งานตัว NLog ไว้แค่นี้หวังว่าพอจะได้แนวทางการนำไปใช้งานกัน ซึ่งจริงๆแล้วตัว NLog นั้นยังมีความสามารถมากกว่านี้ครับ ลองไปอ่านเพิ่มเติมจากเว็บไซต์หลักของเขาที่นี่ http://nlog-project.org/

     

     

    แชร์แนวคิดการเก็บ Audit Data ในระบบ

      ก่อนที่เราจะไปเข้ารายละเอียดของแต่ละ Application แต่ละชนิดกัน จะพูดถึงว่าแต่ละระบบเองก็จะมีส่วนของ Security ที่มีใช้งานกันเช่น ใช้ user account ในการเข้าใช้งานในระบบ ก็ต้องใส่ username/password เข้ามาเพื่อตรวจสอบตัวตนว่ามีสทธิ์เข้าใช้งานระบบหรือไม่ ส่วนกรณีที่เป็น public access application เราอาจจะเก็บข้อมุลจาก client ที่เข้ามาใช้งานเท่าที่จำเป็น เช่น IP Address, การเข้าใช้งานในแต่ละหน้า เป็นต้น
      การบันทึกข้อมูลที่เป็น information data ในระบบนั้น ความเป็นเจ้าของข้อมูล ทั้งการ Create/Update เนื่องจากเมื่อมีการแก้ไขข้อมูลไปแล้ว แน่นอนว่าข้อมูลนั้นจะมีการเปลี่ยนแปลงไปเป็นข้อมูลใหม่ ซึ่งในหลายโอกาสจะเกิดปัญหา ไม่ว่าต้องการรู้ว่าใครสร้างข้อมูลนี้ ใครเป็นคนแก้ไขข้อมูลนี้ เมื่อไหร่เวลาไหน เป็นต้น ซึ่งความต้องการเหล่านี้ทำให้เราจำเป็นที่จะต้องเก็บข้อมูลเหล่านั้นเอาไว้เพื่อตอบโจทย์เหล่านี้

    เก็บข้อมูลเฉพาะ username / datetime

    เช่นตัวอย่าง Customer table

    ID FirstName Age Salary Status CreatedBy CreatedDate ModifiedBy ModifiedDate
    1 Nine xx 10000 Active Nine 10/12/2011 13:00:23 Nine 01/02/2012 07:45:45

    จากตางรางด้านบน จะเหมาะสำหรับข้อมูลที่เราให้ความสำคัญของการตรวจสอบครับ

    ข้อดีคือ

    • เก็บข้อมูลแค่ผู้สร้างและแก้ไขล่าสุด
    • ใช้พื้นที่ในการเก็บไม่เยอะมาก ข้อเสีย
    • ไม่ได้เก็บข้อมูลที่ถูกแก้ไขไป และไม่สามารถเรียกดูย้อนหลังได้
    • อาจจะต้องมีการบันทึกข้อมูลกระจายไปยังที่อื่นเพื่อทำ log เพิ่มเติม

    เก็บข้อมูลที่ถูกแก้ไขทั้ง row

    ซึ่งบางระบบก็อาจจะทำเป็น log table นั้น ๆ เพิ่มมาตามจำนวน table ที่มีในระบบ เมื่อมีการ Update Table ก็จะมาทำการ insert ลงใน table นี่เพิ่ม เช่น แก้ไข Customer Table 1 row ก็จะไป insert ลงใน Customer_Log Table 1 row เป็นต้น

    ตัวอย่าง Customer Table

    ID FirstName Age Salary Status LastModifiedBy LastModifiedDate
    1 Peter 30 50000 Deleted User3 10/02/2012 08:30:49

    Customer_Log Table

    LogNo ID FirstName Age Salary Status ModifiedBy ModifiedDate
    1 1 Peter X 20 500000 Active User1 01/02/2012 07:45:45
    2 1 Peter 30 50000 Active User2 01/02/2012 19:55:50
    3 1 Peter 30 50000 Deleted User3 10/02/2012 08:30:49

    ข้อดีคือ

    • สามารถเก็บข้อมูลที่ถูกแก้ไขไว้ได้ทั้งหมด ใช้ในกรณีที่ต้องการ audit ข้อมูลอย่างละเอียด
      ข้อเสืยคือ
    • หากมี 400 table ที่ต้องการเก็บ log ก็ต้อง x2 ตามจำนวน และข้อมูล history จะเยอะมากกินพื้นที่ใน disk
    • อาจจะต้องมีการย้ายข้อมูล log ออกจาก table เป็นประจำ หรืออาจจะแยกเป็น 2 Database เก็บกันคนละที่
    • อาจจะต้องใช้ trigger เข้าช่วยในการบันทึก log เพื่อลดการเขียนโปรแกรม

    ยังมีวิธีการเก็บ log ข้อมูลอีกหลายวิธีแต่ละวิธีก็จะมีข้อดีข้อเสียแตกต่างกันไป ดังนั้นอาจจะต้องเลือกวิธีที่เหมาะสมกับควาต้องการของระบบ ซึ่งการเก็บ log ของการเปลี่ยนแแปลงข้อมูลนั้นอาจจะจำเป็นต้องใช้งานในวันข้างหน้า แต่บาง table ก็อาจจะไม่ต้องทำการเก็บบันทึกก็ได้เนื่องจากอาจจะไม่ใช่ข้อมูลสำคัญของระบบเป็นต้น

    สรุปความ

    ก็ขอจบเรื่องของ Logging เอาไว้เพียงแค่ 2 ตอนนี้หวังว่าพอจะเป็นประโยชน์กับนักพัฒนาระบบที่มีความสนใจและกำลังค้นคว้าศึกษาครับ

    Download Source Code

     http://dl.dropbox.com/u/34809954/LoggingSrc.zip


    image

    About Me:

    Chalermpon Areepong : Nine (นาย)

    Microsoft MVP Thailand ASP.NET

    ASP.NET & MVC Developers Thailand Group : http://www.facebook.com/groups/MVCTHAIDEV/

    Greatfriends.biz Community Leader : http://greatfriends.biz

    Email : nine_biz-talk.net at hotmail dot com

    Blog : https://nine69.wordpress.com

    2 Comments »

    1. ขอบคุณครับ

      Comment by โปรแกรมเมอร์ใส้แห้ง โอ้เย — 23/04/2012 @ 6:01 pm


    RSS feed for comments on this post. TrackBack URI

    Leave a Reply

    Please log in using one of these methods to post your comment:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s

    Create a free website or blog at WordPress.com.

    %d bloggers like this: