编写自定义日志提供程序代码

适用范围:SQL Server Azure 数据工厂中的 SSIS Integration Runtime

创建继承自 LogProviderBase 基类的类并将 DtsLogProviderAttribute 属性应用于该类后,必须重写基类的属性和方法的实现以提供自定义功能。

有关自定义日志提供程序的工作示例,请参阅为自定义日志提供程序开发用户界面

配置日志提供程序

初始化日志提供程序

重写 InitializeLogProvider 方法以缓存对连接集合和事件接口的引用。 可以稍后在日志提供程序的其他方法中使用这些缓存的引用。

使用 ConfigString 属性

在设计时。日志提供程序从“配置” 列接收配置信息。 此配置信息与日志提供程序的 ConfigString 属性对应。 默认情况下,此列包含一个文本框,您可以从该文本框中检索任何字符串信息。 随 Integration Services 提供的大部分日志提供程序都使用此属性存储连接管理器的名称,以供提供程序连接外部数据源时使用。 如果日志提供程序使用 ConfigString 属性,可使用 Validate 方法验证此属性,并确保此属性已正确设置。

验证日志提供程序

重写 Validate 方法以确保提供程序已正确配置并且可以执行。 通常,最低级别的验证应确保 ConfigString 已正确设置。 在日志提供程序从 Success 方法返回 Validate 之前,执行不能继续。

下面的代码示例演示 Validate 的实现,它确保连接管理器的名称已指定、连接管理器存在于包中以及连接管理器返回 ConfigString 属性中的文件名。

public override DTSExecResult Validate(IDTSInfoEvents infoEvents)  
{  
    if (this.ConfigString.Length == 0 || connections.Contains(ConfigString) == false)  
    {  
        infoEvents.FireError(0, "MyTextLogProvider", "The ConnectionManager " + ConfigString + " specified in the ConfigString property cannot be found in the collection.", "", 0);  
        return DTSExecResult.Failure;  
    }  
    else  
    {  
        string fileName = connections[ConfigString].AcquireConnection(null) as string;  
  
        if (fileName == null || fileName.Length == 0)  
        {  
            infoEvents.FireError(0, "MyTextLogProvider", "The ConnectionManager " + ConfigString + " specified in the ConfigString property cannot be found in the collection.", "", 0);  
            return DTSExecResult.Failure;  
        }  
    }  
    return DTSExecResult.Success;  
}  
Public Overrides Function Validate(ByVal infoEvents As IDTSInfoEvents) As DTSExecResult  
    If Me.ConfigString.Length = 0 Or connections.Contains(ConfigString) = False Then  
        infoEvents.FireError(0, "MyTextLogProvider", "The ConnectionManager " + ConfigString + " specified in the ConfigString property cannot be found in the collection.", "", 0)  
        Return DTSExecResult.Failure  
    Else   
        Dim fileName As String =  connections(ConfigString).AcquireConnectionCType(as string, Nothing)  
  
        If fileName = Nothing Or fileName.Length = 0 Then  
            infoEvents.FireError(0, "MyTextLogProvider", "The ConnectionManager " + ConfigString + " specified in the ConfigString property cannot be found in the collection.", "", 0)  
            Return DTSExecResult.Failure  
        End If  
    End If  
    Return DTSExecResult.Success  
End Function  

使日志提供程序持久化

通常不需要对连接管理器实现自定义持久性。 自定义持久性仅在对象的属性使用复杂数据类型时才需要。 有关详细信息,请参阅开发用于 Integration Services 的自定义对象

使用日志提供程序进行日志记录

有三个所有日志提供程序都必须重写的运行时方法:OpenLogLogCloseLog

重要

在单个包的验证和执行期间,将多次调用 OpenLogCloseLog 方法。 请确保您的自定义代码不会导致较早的日志条目被下一次打开和关闭日志的操作所覆盖。 如果已选择在测试包中记录验证事件,则应该看到的第一个记录事件是 OnPreValidate;如果您看到的第一个记录事件是 PackageStart,则表示初始验证事件已被覆盖。

打开日志

大部分日志提供程序都连接外部数据源,如文件或数据库,以便存储在包执行期间收集的事件信息。 与运行时的任何其对象一样,与外部数据源的连接通常使用连接管理器对象来完成。

OpenLog 方法在包执行开始时调用。请重写此方法以建立与外部数据源的连接。

下面的示例代码演示了在 OpenLog 执行期间打开一个文本文件供写入的日志提供程序。 该提供程序通过调用在 AcquireConnection 属性中指定的连接管理器的 ConfigString 方法来打开文件。

public override void OpenLog()  
{  
    if(!this.connections.Contains(this.ConfigString))  
        throw new Exception("The ConnectionManager " + this.ConfigString + " does not exist in the Connections collection.");  
  
    this.connectionManager = connections[ConfigString];  
    string filePath = this.connectionManager.AcquireConnection(null) as string;  
  
    if(filePath == null || filePath.Length == 0)  
        throw new Exception("The ConnectionManager " + this.ConfigString + " is not a valid FILE ConnectionManager");  
  
    //  Create a StreamWriter to append to.  
    sw = new StreamWriter(filePath,true);  
  
    sw.WriteLine("Open log" + System.DateTime.Now.ToShortTimeString());  
}  
Public Overrides  Sub OpenLog()  
    If Not Me.connections.Contains(Me.ConfigString) Then  
        Throw New Exception("The ConnectionManager " + Me.ConfigString + " does not exist in the Connections collection.")  
    End If  
  
    Me.connectionManager = connections(ConfigString)  
    Dim filePath As String =  Me.connectionManager.AcquireConnectionCType(as string, Nothing)  
  
    If filePath = Nothing Or filePath.Length = 0 Then  
        Throw New Exception("The ConnectionManager " + Me.ConfigString + " is not a valid FILE ConnectionManager")  
    End If  
  
    '  Create a StreamWriter to append to.  
    sw = New StreamWriter(filePath,True)  
  
    sw.WriteLine("Open log" + System.DateTime.Now.ToShortTimeString())  
End Sub  

写入日志条目

每次包中的对象通过对某一事件接口调用 Fire<event> 方法来引发事件时,都会调用 Log 方法。 每次引发事件时,都会提供其上下文的相关信息,通常是说明性消息。 但是,并非所有对 Log 方法的调用都包含每个方法参数的信息。 例如,一些具有自我说明性名称的标准事件不提供 MessageText,并且 DataCode 和 DataBytes 只提供可选的补充信息。

下面的代码示例实现了 Log 方法,并将事件写入前述打开的流中。

public override void Log(string logEntryName, string computerName, string operatorName, string sourceName, string sourceID, string executionID, string messageText, DateTime startTime, DateTime endTime, int dataCode, byte[] dataBytes)  
{  
    sw.Write(logEntryName + ",");  
    sw.Write(computerName + ",");  
    sw.Write(operatorName + ",");  
    sw.Write(sourceName + ",");  
    sw.Write(sourceID + ",");  
    sw.Write(messageText + ",");  
    sw.Write(dataBytes + ",");  
    sw.WriteLine("");  
}  
Public Overrides  Sub Log(ByVal logEnTryName As String, ByVal computerName As String, ByVal operatorName As String, ByVal sourceName As String, ByVal sourceID As String, ByVal executionID As String, ByVal messageText As String, ByVal startTime As DateTime, ByVal endTime As DateTime, ByVal dataCode As Integer, ByVal dataBytes() As Byte)  
    sw.Write(logEnTryName + ",")  
    sw.Write(computerName + ",")  
    sw.Write(operatorName + ",")  
    sw.Write(sourceName + ",")  
    sw.Write(sourceID + ",")  
    sw.Write(messageText + ",")  
    sw.Write(dataBytes + ",")  
    sw.WriteLine("")  
End Sub  

关闭日志

CloseLog 方法在包执行结束时、包中的所有对象都执行完毕后或包由于错误而停止时调用。

下面的代码示例演示了 CloseLog 方法的实现,该方法用于关闭在 OpenLog 方法执行期间打开的文件流。

public override void CloseLog()  
{  
    if (sw != null)  
    {  
        sw.WriteLine("Close log" + System.DateTime.Now.ToShortTimeString());  
        sw.Close();  
    }  
}  
Public Overrides  Sub CloseLog()  
    If Not sw Is Nothing Then  
        sw.WriteLine("Close log" + System.DateTime.Now.ToShortTimeString())  
        sw.Close()  
    End If  
End Sub  

另请参阅

创建自定义日志提供程序
为自定义日志提供程序开发用户界面