Log4net Appender到Azure文档Db

时间:2017-03-20 11:02:45

标签: azure log4net azure-cosmosdb

我正在尝试通过引用文章http://korrozia.blogspot.in/2016/11/how-to-store-log4net-messages-to-azure.html为Log4net编写自定义appender。文档正在Azure Doc DB中创建,但日志消息未显示在文档中。下面是我的自定义appender代码

public class DocumentDbAppender: AppenderSkeleton
{
    private DocumentClient client;

    public string DatabaseId
    {
        get;
        set;
    }

    public string CollectionId
    {
        get;
        set;
    }

    public string EndpointUrl
    {
        get;
        set;
    }

    public string AuthKey
    {
        get;
        set;
    }

    protected override void Append(LoggingEvent loggingEvent)
    {
        try
        {
            using (client = new DocumentClient(new Uri(EndpointUrl), AuthKey))
            {
                var database = RetrieveOrCreateDatabaseAsync(DatabaseId).Result;

                var collection = RetrieveOrCreateCollectionAsync(database.SelfLink, 
                    CollectionId).Result;

                var document = CreateDocumentAsync(client, collection.SelfLink, loggingEvent).Result;
            }
        }
        catch (DocumentClientException de)
        {
            Exception baseException = de.GetBaseException();
            Debug.Print("Status code {0} error occurred: {1}, Message: {2}", de.StatusCode, 
                de.Message, baseException.Message);
        }
        catch (Exception e)
        {
            Exception baseException = e.GetBaseException();
            Debug.Print("Error: {0}, Message: {1}", e.Message, baseException.Message);
        }
    }

    private async Task<Database> RetrieveOrCreateDatabaseAsync(string id)
    {
        // Try to retrieve the database (Microsoft.Azure.Documents.Database) whose Id is equal to databaseId            
        var database = client.CreateDatabaseQuery().Where(db => db.Id == DatabaseId).
            AsEnumerable().FirstOrDefault();

        // If the previous call didn't return a Database, it is necessary to create it
        if (database == null)
        {
            database = await client.CreateDatabaseAsync(new Database { Id = DatabaseId }).ConfigureAwait(false);
            Debug.Print("Created Database: id - {0} and selfLink - {1}", database.Id, database.SelfLink);
        }

        return database;
    }

    private async Task<DocumentCollection> RetrieveOrCreateCollectionAsync(string databaseSelfLink, 
        string id)
    {
        // Try to retrieve the collection (Microsoft.Azure.Documents.DocumentCollection) whose 
        // Id is equal to collectionId
        var collection = client.CreateDocumentCollectionQuery(databaseSelfLink).
            Where(c => c.Id == id).ToArray().FirstOrDefault();

        // If the previous call didn't return a Collection, it is necessary to create it
        if (collection == null)
        {
            collection = await client.CreateDocumentCollectionAsync(databaseSelfLink, 
                new DocumentCollection { Id = id }).ConfigureAwait(false);
        }

        return collection;
    }

    private async Task<Document> CreateDocumentAsync(DocumentClient client, 
        string collectionSelfLink, LoggingEvent loggingEvent)
    {

        var doc = await client.CreateDocumentAsync(collectionSelfLink,
            loggingEvent).ConfigureAwait(false);

        return doc;
    }

}

我的Web.config如下所示

<log4net>
<!--This is for local testing. Comment out this appender when moved to azure cloud-->
<!--<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
  <file value=".\\Logs\\WebApi.log"/>
  <appendToFile value="true"/>
  <rollingStyle value="Size"/>
  <maxSizeRollBackups value="10"/>
  <maximumFileSize value="10MB"/>
  <staticLogFileName value="true"/>
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.25M - %m%n"/>
  </layout>
</appender>-->

  <appender name="DocumentDbAppender"
    type="MyApp.Infra.Logger.DocumentDbAppender, MyApp.Infra.Logger">
    <DatabaseId>Diagnostics</DatabaseId>
    <CollectionId>Logs</CollectionId>
    <EndpointUrl>https://mydb.documents.azure.com:443/</EndpointUrl>
    <AuthKey>UB0w==</AuthKey>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.25M - %m%n"/>
      <!--<conversionPattern value="%m"/>-->
    </layout>
</appender>

我正在创建logger实例,如下所示

  log4net.Util.LogLog.InternalDebugging = true;

  log4net.Config.XmlConfigurator.Configure();
  log4netLogger = log4net.LogManager.GetLogger(
                System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

如果我只是写一条信息消息,它在文档DB中就像下面那样

{
  "$type": "log4net.Core.LoggingEvent, log4net",
  "LoggerName": MyApp.Infra.Logger.Log4NetLogger",
  "Level": {
    "$type": "log4net.Core.Level, log4net",
    "Name": "INFO",
    "Value": 40000,
    "DisplayName": "INFO"
  },
  "Message": null,
  "ThreadName": null,
  "TimeStamp": "2017-03-20T15:57:17.7133358+05:30",
  "LocationInfo": null,
  "UserName": null,
  "ExceptionString": null,
  "Properties": null,
  "Domain": null,
  "Identity": null,
  "id": "23071629-d896-4812-9a87-89871d969780"
}

请注意,Message为空。我不确定为什么会这样。如果我使用Rolling File Appender,我可以毫无问题地收到消息。

1 个答案:

答案 0 :(得分:0)

从您提供的the link,我们可以找到它覆盖附加方法,并使用Append方法中的CreateDocumentAsync method为LoggingEvent对象创建文档。当您编写信息消息时,请尝试检查Exception对象ex是否为 null

LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType).Info("info mes", ex);

此外,请在调用CreateDocumentAsync方法创建文档之前,在Append(LoggingEvent loggingEvent)方法中设置断点以观察 loggingEvent 的属性。