Использование log4net для регистрации вывода Powershell в динамических переменных базы данных - PullRequest
0 голосов
/ 29 июля 2011

Я создаю веб-интерфейс, чтобы помочь автоматизировать наш процесс развертывания, и собираюсь написать сценарий powershell для этого развертывания, и мне хотелось бы, чтобы это был Write-Debug (или любой оператор для регистрации, просто дайте мне знать, какой использовать: )) операторы для записи в переменную базы данных развернутого package Log. Я до сих пор не использовал log4net, поэтому, пожалуйста, не смейтесь, если я делаю это совершенно неправильно.

Я полагаю, что поскольку местоположение является динамическим, мне придется кодировать приложения log4net, но будет ли проще / лучше делать все содержимое log4net внутри скрипта powershell? Я прочитал this и обнаружил, что должен использовать ps.Streams.Debug.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e) для получения информации об отладке записи.

Вот что у меня есть:

public static void Test(Package pkg)
    {
        //Do roll_out
        //Creates a cmd prompt
        PowerShell ps = PowerShell.Create();
        string myCommand = @"C:\Users\evan.layman\Desktop\test.ps1";

    ps.AddCommand(myCommand);

    ps.Streams.Debug.DataAdded += new EventHandler<DataAddedEventArgs>(delegate(object sender, DataAddedEventArgs e)
    {
        PSDataCollection<DebugRecord> debugStream = (PSDataCollection<DebugRecord>)sender;
        DebugRecord record = debugStream[e.Index];

        Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
        hierarchy.Root.RemoveAllAppenders(); /*Remove any other appenders*/

        AdoNetAppender appender = new AdoNetAppender();
        appender.ConnectionString = ConfigurationManager.ConnectionStrings["DeploymentConnectionString"].ConnectionString;
        appender.CommandText = "with cte as (SELECT * FROM Package PackageID =" + pkg.PackageID + ") UPDATE cte SET (Log) VALUES (?logText)";
        AdoNetAppenderParameter param = new AdoNetAppenderParameter();
        param.DbType = System.Data.DbType.String;
        param.ParameterName = "logText";
        param.Layout = new log4net.Layout.RawTimeStampLayout();
        appender.AddParameter(param);
        BasicConfigurator.Configure(appender);

        ILog log = LogManager.GetLogger("PowerShell");
        log.Debug(record.Message);
        //log.DebugFormat("{0}:{1}", DateTime.UtcNow, record);
        //log.Warn(record, new Exception("Log failed"));
    });
    Collection<PSObject> commandResults = ps.Invoke();

Надеюсь, я смогу заставить это работать :)

1 Ответ

1 голос
/ 01 августа 2011

Я бы сохранил как можно больше конфигурации log4net из вашего кода.В вашем коде конфигурация воссоздается для каждого оператора отладки, что неэффективно.

Можно сделать то, что вы хотите, используя свойства контекста события в log4net.Я немного рассказал о контексте события log4net в моем блоге .

Вот краткий пример, близкий к существующей базе кода ...

Этот код C # показывает, как использовать глобальные свойства log4net для хранения пользовательских данных контекста события;обратите внимание на настройку значения глобального свойства «PackageID» перед выполнением конвейера ...

using System;
using System.Management.Automation;
using log4net;

// load log4net configuration from app.config
[assembly:log4net.Config.XmlConfigurator]

namespace ConsoleApplication1
{
    class Program
    {
        private static PowerShell _ps;
        private static ILog Log = log4net.LogManager.GetLogger(typeof (Program));

        static void Main(string[] args)
        {
            string script = "write-debug 'this is a debug string' -debug";

            for (int packageId = 1; packageId <= 5; ++packageId)
            {
                using (_ps = PowerShell.Create())
                {
                    _ps.Commands.AddScript(script);
                    _ps.Streams.Debug.DataAdded += WriteDebugLog;

                    // set the PackageID global log4net property 
                    log4net.GlobalContext.Properties["PackageID"] = packageId;

                    // sync invoke your pipeline
                    _ps.Invoke();

                    // clear the PackageID global log4net property 
                    log4net.GlobalContext.Properties["PackageID"] = null;
                }
            }        
        }

        private static void WriteDebugLog(object sender, DataAddedEventArgs e)
        {
            // get the debug record and log the message
            var record = _ps.Streams.Debug[e.Index];
            Log.Debug(record.Message);            
        }
    }
}

А вот app.config, который сбрасывает журналы в базу данных;обратите внимание на пользовательский параметр PackageID в SQL и то, как значение извлекается из стека свойств log4net:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
  <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<log4net>
  <appender name="Ado" type="log4net.Appender.AdoNetAppender">
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <connectionString value="data source=vbox-xp-sql;initial catalog=test1;integrated security=false;persist security info=True;User ID=test1;Password=password" />
    <commandText value="INSERT INTO Log ([Message],[PackageID]) VALUES (@message, @packageid)" />
    <parameter>
      <parameterName value="@message" />
      <dbType value="String" />
      <size value="4000" />
      <layout type="log4net.Layout.PatternLayout" value="%message" />
    </parameter>
    <parameter>
      <parameterName value="@packageid" />
      <dbType value="Int32" />
      <size value="4" />
      <!-- use the current value of the PackageID property -->
      <layout type="log4net.Layout.PatternLayout" value="%property{PackageID}" />
    </parameter>
  </appender>

  <root>
    <level value="ALL" />
    <appender-ref ref="Ado" />
  </root> 
</log4net>
</configuration>

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...