第十二篇 Integration Services:高级日志记录

时间:2023-03-08 15:50:45
第十二篇 Integration Services:高级日志记录

本篇文章是Integration Services系列的第十二篇,详细内容请参考原文


简介
在前一篇文章我们配置了SSIS内置日志记录,演示了简单和高级日志配置,保存并查看日志配置,生成自定义日志消息。在第十篇我们讨论了bubbling事件的行为,分享操纵事件冒泡默认行为的方法,并介绍了父子模式。
在这一篇,我们将结合已经学到的知识事件冒泡、日志记录、父子模式创建一个自定义的SSIS包日志记录模式。
回顾SSIS任务事件
打开Precedence.dtsx包。你的控制流面板应该如图12.1所示:
第十二篇 Integration Services:高级日志记录
图12.1
从第九到第十一篇,我们关注在序列容器1。在第九篇,我们在Script Task 4和序列容器1上创建了OnError事件处理程序——我们描述为事件"监听器"。在第十篇,我们为Precedence.dtsx包添加一个OnError事件处理程序扩展了这个模式。对于每一个OnError事件处理程序,我们添加一个脚本任务来显示包含下面SSIS变量的消息对话框:
->System::ErrorCode
->System::ErrorDescription
->System::SourceName
在我们开始测试前,让我们验证和/或修改之前的Precedence.dtsx包的某些设置。首先,点击Precedence.dtsx包控制流的空白区并按F4显示属性。修改DisableEventHandlers属性为True,如图12.2所示:
第十二篇 Integration Services:高级日志记录
图12.2
在我们做更多修改前,通过按F5在BIDS调试器下执行Precedence.dtsx包。对于"Succeed Script Task 2?"的选择不会影响演示的目的,但是现在以及这篇文章剩余部分我们会选择"是"按钮(图12.3)引起 Script Task 2成功。
第十二篇 Integration Services:高级日志记录
图12.3
当提示"Succeed Script Task 4?"时,选择否按钮从Script Task 4引起一个错误事件:
第十二篇 Integration Services:高级日志记录
图12.4
当Script Task 4产生一个错误事件,在第九篇中配置的OnError事件处理程序会忽略,因为我们在包级禁用了事件处理程序(图12.1)。下一个消息对话框显示Script Task 3完成如图12.5所示:
第十二篇 Integration Services:高级日志记录
图12.5
接受Script Task 3的消息,让Precedence.dtsx包完成执行,最终如图12.6所示:
第十二篇 Integration Services:高级日志记录
图12.6
如果你的Precedence.dtsx包行为如上所述,我们就已经为第十二篇准备好了。
禁用内置日志记录
我们要做的第一件事是移除SSIS包上已存在的日志记录配置。为了开始这个过程,点击SSIS下拉菜单选择日志记录,如图12.7所示:
第十二篇 Integration Services:高级日志记录
图12.7
当打开配置SSIS日志窗口后,点击删除按钮(图12.8),删除已存在的文本日志文件配置:
第十二篇 Integration Services:高级日志记录
图12.8
严格来说,这将停止Precedence.dtsx包上的日志记录。But I like to clean up SSIS packages,我提倡去掉配置SSIS日志中容器树下Precedence包前的复选框,如图12.9所示:
第十二篇 Integration Services:高级日志记录
图12.9
我同时推荐删除日志文件连接管理器,如图12.10所示:
第十二篇 Integration Services:高级日志记录
图12.10
当提示确认删除连接时,点击是按钮,如图12.11所示:
第十二篇 Integration Services:高级日志记录
图12.11
这将会彻底清除我们在第十一篇中配置的内置日志记录。在BIDS调试器下执行包确保它按期望执行。
回顾事件冒泡
在第十篇,我们介绍了父子SSIS设计模式。我们创建一个名叫Parent.dtsx的新包,并在Parent.dtsx包的控制流添加了个执行包任务。我们配置执行包任务调用Precedence.dtsx包。在第十篇的结尾,"最后一件事"我们禁用了Precedence.dtsx包的事件处理程序(这一篇开始,也做了此操作)。然后我们在BIDS调试器下执行Parent.dtsx包,并观察Precedence.dtsx包中Script Task 4引发的错误事件消息对话框。观察到的行为是一个事件冒泡的结果。
为了回顾事件冒泡(个人认为要符合此节后续内容,Precedence.dtsx包DisableEventHandlers属性应该设置为False),从解决方案资源管理器打开Parent.dtsx。我喜欢配置BIDS环境查看父子包更方便。左键按住Precedence.dtsx页签,并将它往操作面板拖动,当你看到一个小页面时放开左键,你就会被提示新建水平或垂直选项卡组。选择新建垂直选项卡组,如图12.12所示:
第十二篇 Integration Services:高级日志记录
图12.12
BIDS会调整包如图12.13所示,让接下来的父子执行更方便:
第十二篇 Integration Services:高级日志记录
图12.13
点击Parent.dtsx包的控制流面板的空白区,确保选择了Parent.dtsx.按F5执行Parent.dtsx包,会调用Precedence.dtsx,Script Task 2选择是,Script Task 4选择否。接受Script Task 4和序列容器1的OnError事件处理程序产生的事件处理程序消息。接受Script Task 3提示的完成消息对话框。执行应该完成并且BIDS应该如图12.14所示:
第十二篇 Integration Services:高级日志记录
图12.14
在Precedence.dtsx,注意Script Task 4失败,序列容器1成功。在Parent.dtsx,注意执行包任务失败。因为序列容器1的ForceExecutionResult属性保持设置为"Success"。注意接下来Parent包的OnError事件处理程序的执行,如图12.15所示:
第十二篇 Integration Services:高级日志记录
图12.15
这里我会指出几件有趣的事。首先,在父子SSIS设计模式,错误事件从Precedence.dtsx包的底部(Script Task 4)冒泡到Parent.dtsx包的顶部。Figure 12.16 shows my “artist’s concept” of what is really and truly happening here.The Precedence.dtsx package acts as if it is "in scope" of the Parent.dtsx package’s Execute Package Task——仿佛它是执行包任务中的一个可执行文件虚拟文件夹。在真实环境,你不可能看到图12.16所示关系的包资源管理器。执行包任务不包含一个可执行文件虚拟文件夹,and if they did you would not see the Package Explorer from the child package included therein (at least not in a current version of SSIS at the time of this writing). 图形代表父子SSIS设计模式的事件冒泡行为:
第十二篇 Integration Services:高级日志记录
图12.16
其次,错误事件,Script Task 4最初产生,一直保持原始变量的值。错误代码、错误描述、源保持静态。哪怕它从子包冒泡到父包,如图12.17所示:
第十二篇 Integration Services:高级日志记录
图12.17
这种行为适用于所有的SSIS任务事件,不只是OnError事件。现在让我们把事件冒泡为我们工作。
准备父子SSIS设计模式日志记录
首先,我们需要一个日志记录的数据库库和表。让我们创建一个名为"SSISStairwayConfig"的数据库,我使用代码12.1创建这个数据库:

Use master
go /* SSISStairwayConfig database */
If Not Exists(Select name
From sys.databases
Where name = 'SSISStairwayConfig')
begin
print 'Creating SSISStairwayConfig database'
Create Database SSISStairwayConfig
print 'SSISStairwayConfig database created'
end
Else
print 'SSISStairwayConfig database already exists.'
print ''
go

代码12.1
其次,我使用代码12.2创建"lg"架构和"SSISErrors"表:

Use SSISStairwayConfig
go
/* log schema */
If Not Exists(Select name
From sys.schemas
Where name = 'lg')
begin
print 'Creating lg schema'
declare @sql varchar(100) = 'Create Schema lg'
exec(@sql)
print 'Lg schema created'
end
Else
print 'Lg schema already exists.'
print ''
/* lg.SSISErrors table */
If Not Exists(Select s.name + '.' + t.name
From sys.tables t
Join sys.schemas s
On s.schema_id = t.schema_id
Where s.name = 'lg'
And t.name = 'SSISErrors')
begin
print 'Creating lg.SSISErrors table'
Create Table lg.SSISErrors
(
ID int identity(1,1)
Constraint PK_SSISErrors Primary Key Clustered
,ErrorDateTime datetime Not Null
Constraint DF_logSSISErrors_ErrorDateTime
Default(GetDate())
,ErrorDescription varchar(max) Null
,ErrorCode int Null
,SourceName varchar(255) Null
)
print 'Lg.SSISErrors created'
end
Else
print 'Lg.SSISErrors table already exists.'
print ''

代码12.2
我们会从SSIS包获取错误数据到SSISStairwayConfig.lg.SSISErrors表。
应用父子SSIS设计模式到日志记录
打开Parent.dtsx包的事件处理程序页签,可执行文件选择Parent,事件处理程序选择OnError,如图12.18所示:
第十二篇 Integration Services:高级日志记录
图12.18
拖一个执行SQL任务到事件处理程序面板,在脚本任务和执行SQL任务间连接一个成功优先约束,如图12.19所示:
第十二篇 Integration Services:高级日志记录
图12.19
打开执行SQL任务编辑器,修改ConnectionType属性为ADO.NET如图12.20所示:
第十二篇 Integration Services:高级日志记录
图12.20
点击Connection属性值的下拉列表,选择<新建连接...>如图12.21所示:
第十二篇 Integration Services:高级日志记录
图12.21
新建连接选项为我们做了三件事。第一,它选择正确的连接管理器类型:ADO.NET连接。第二,它在连接管理器页签创建一个新的ADO.NET连接管理器,如图12.22所示:
第十二篇 Integration Services:高级日志记录
图12.22
第三,新建连接选项打开配置ADO.NET连接管理器,如图12.23所示:
第十二篇 Integration Services:高级日志记录
图12.23
点击新建按钮配置数据连接。在服务器名,选择或键入SSISStairwayConfig数据库所在实例的服务器和实例名称。在选择或输入一个数据库名,选择或键入SSISStairwayConfig。如图12.24所示:
第十二篇 Integration Services:高级日志记录
图12.24
点击测试连接按钮验证你有对SSISStairwayConfig数据库的访问权限。如果由于某些原因你不能访问SSISStairwayConfig数据库,你将看到类似图12.25所示的对话框(我通过删除SSISStairwayConfig中的最后一个g模拟这个错误):
第十二篇 Integration Services:高级日志记录
图12.25
如果测试成功,你会看到类似图12.26对话框:
第十二篇 Integration Services:高级日志记录
图12.26
点击确定按钮关闭连接管理器,并返回到配置ADO.NET连接管理器窗口,如图12.27所示:
第十二篇 Integration Services:高级日志记录
图12.27
Data connections are stored in your Windows profile on your workstation.Data connection information will remain available on your workstation and be accessible when developing SSIS packages in the future.点击确定按钮关闭配置ADO.NET连接管理器。
SSIS命名连接管理器"WORK\SQL08R2.SSISStairwayConfig",并在执行SQL任务的Connection属性使用这个名称。SSIS同样命名真实的连接管理器"WORK\SQL08R2.SSISStairwayConfig"如图12.28所示:
第十二篇 Integration Services:高级日志记录
图12.28
接下来点击SQLStatement属性的文本框末端省略号,打开输入SQL查询窗口。键入代码12.3所示的语句:

Insert Into lg.SSISErrors
(ErrorCode
,ErrorDescription
,SourceName)
Values
(@ErrorCode
,@ErrorDescription
,@SourceName)

代码12.3
输入SQL查询窗口应该如图12.29所示:
第十二篇 Integration Services:高级日志记录
图12.29
点击确定按钮关闭输入SQL查询窗口。
我们创建的插入数据包含三个参数:ErrorCode、ErrorDescription和SourceName。在执行SQL任务编辑器的左侧点击参数映射打开参数映射页,我们将把SQL查询参数和OnError事件处理程序变量连接起来。
点击添加按钮,通过点击变量名称下拉列表将变量名称修改为"System::ErrorCode",修改参数名称为ErrorCode。System::ErrorCode变量是一个Int32数据类型,并且它的值会代替插入数据中的@ErrorCode参数。
方向的值有:Input、Output和ReturnValue.数据类型列包含了ADO.Net数据类型的列表。为什么是ADO.Net数据类型?因为执行SQL任务的ConnectionType就是它。如果我们选择OLEDB连接类型,这里的数据类型会有所不同。
ADO.Net和OLEDB连接类型的另一个不同:ADO.Net连接中我可以在SQL语句和参数名称列使用参数的名称;在OLEDB连接中我必须在SQL语句使用?而且参数名称要使用数字(0对应第一个?,1对应第二个...)。我发现ADO.Net语法在插入(以及其他)语句中更明了。
点击添加按钮添加其他参数,最终参数映射如图12.30所示:
第十二篇 Integration Services:高级日志记录
图12.30
在BIDS调试器下执行SSIS包,观察OnError事件处理程序如图12.31所示:
第十二篇 Integration Services:高级日志记录
图12.31
在Script Task 4选择否,The Parent.dtsx SSIS package’s OnError event handler responded, as did the Execute SQL Task.我们可以通过打开SSMS执行代码12.4中的语句查看结果:

Use SSISStairwayConfig
go
Select * From lg.SSISErrors

代码12.4
我的结果如图12.32所示:
第十二篇 Integration Services:高级日志记录
图12.32
Pop quiz: in the Parent-Child pattern, how many lines of code or objects are required in the child package to log errors? (Answer: 0)
我们从一致性和集合得到额外的好处:每一个错误信息都以相同的格式和位置记录。
总结
在这一篇我们结合了之前所学的冒泡、日志记录、父子模式创建一个自定义的SSIS包日志记录模式。我们使用Parent.dtsx包的OnError事件处理程序和执行SQL任务来捕获和保存子包引发的错误信息。We accomplished this without adding additional logic to the child package and we achieved a consistent format and location for storing SSIS error information.