|
| 1 | +/*#info |
| 2 | +
|
| 3 | + # Autor |
| 4 | + Rodrigo Ribeiro Gomes |
| 5 | + |
| 6 | + # Detalhes |
| 7 | + Essa é uma proc que criei para o Power Alerts. |
| 8 | + Pelo menos, uma das primeiras versoes... Serve pra improtar xevents de pouco em pouco para uma tabela. |
| 9 | + Ja nao atualizo ela tem tempo e a versão atual do power alerts tem melhorias. |
| 10 | + Mas, de qualquer maneira, resolvi deixar aqui (com autorização da Power Tuning). |
| 11 | + Recomendo que use o power alerts, se quiser uma solução completa pro seu banco: https://poweralerts.com.br |
| 12 | +*/ |
| 13 | +ALTER PROCEDURE |
| 14 | + stpPowerAlert_ImportXEvent( |
| 15 | + @XeSession nvarchar(1000) |
| 16 | + ,@DestinationTable nvarchar(100) |
| 17 | + ,@Columns XML |
| 18 | + ,@Debug bit = 0 |
| 19 | + ,@EventNameCol nvarchar(200) = 'Nm_Event' |
| 20 | + ,@EventTsCol nvarchar(200) = 'Dt_Event' |
| 21 | + ,@IncludeEventData bit = 0 |
| 22 | + ,@AutomaticDestTable bit = 1 -- If table have 1 AutoCol, then create tables from xml. |
| 23 | + -- If table dont have auto col, then use data types from table... |
| 24 | + ,@StopStart bit = 0 |
| 25 | + ,@topEvents int = 10000 |
| 26 | + ) |
| 27 | +AS |
| 28 | + SET NOCOUNT ON; |
| 29 | + IF OBJECT_ID('tempdb..#PowerAlert_Debug') IS NOT NULL |
| 30 | + SET @Debug = 1 |
| 31 | + |
| 32 | + DECLARE |
| 33 | + @filenamePattern nvarchar(1000) |
| 34 | + ,@metaPattern nvarchar(1000) |
| 35 | + ,@CurrentFile nvarchar(1000) |
| 36 | + ,@CurrentOffset int |
| 37 | + ,@DirName nvarchar(1000) |
| 38 | + ,@StartTime datetime |
| 39 | + ,@EndTime datetime |
| 40 | + ,@FileImportStartTime datetime |
| 41 | + ,@FileImportEndTime datetime |
| 42 | + ,@TotalTime int |
| 43 | + ,@InsertColList nvarchar(max) |
| 44 | + ,@AutomaticTableMode varchar(100) |
| 45 | + ,@spsql nvarchar(max) |
| 46 | + ,@sql nvarchar(max) |
| 47 | + ,@XeCol nvarchar(max) |
| 48 | + ,@evtDataColTEmplate nvarchar(1000) = 'e.XeEventData.value(''#XPATH'',''#TYPE'')' |
| 49 | + ,@evtDataXmlTemplate nvarchar(1000) = 'e.XeEventData.query(''#XPATH'')' |
| 50 | + ,@BaseFileName nvarchar(1000) |
| 51 | + ; |
| 52 | + |
| 53 | + SELECT |
| 54 | + @filenamePattern = REPLACE(CONVERT(nvarchar(1000),value),'.xel','_0_*.xel') |
| 55 | + ,@BaseFileName = RIGHT(@filenamePattern, CHARINDEX('\', REVERSE(@filenamePattern) ) - 1) |
| 56 | + FROM |
| 57 | + sys.server_event_sessions AS [session] |
| 58 | + JOIN sys.server_event_session_targets AS [target] |
| 59 | + ON [session].event_session_id = [target].event_session_id |
| 60 | + JOIN sys.server_event_session_fields AS field |
| 61 | + ON field.event_session_id = [target].event_session_id |
| 62 | + AND field.object_id = [target].target_id |
| 63 | + WHERE |
| 64 | + field.name = 'filename' |
| 65 | + and [session].name= @XeSession |
| 66 | + |
| 67 | + IF @@ROWCOUNT = 0 |
| 68 | + RETURN 1; |
| 69 | + |
| 70 | + IF @Debug = 1 RAISERROR(' Base Dir: %s, BAseName: %s',0,1,@filenamePattern,@BaseFileName) WITH NOWAIT; |
| 71 | + |
| 72 | + |
| 73 | + SET @DirName = LEFT(@filenamePattern,LEN(@filenamePattern)-CHARINDEX('\',REVERSE(@filenamePattern))) |
| 74 | + |
| 75 | + IF OBJECT_ID('tempdb..#EventData') IS NOT NULL DROP TABLE #EventData; |
| 76 | + CREATE TABLE #EventData(XeEventData XML, SrcFile nvarchar(1000)) |
| 77 | + |
| 78 | + |
| 79 | + IF OBJECT_ID('tempdb..#FileList') IS NOT NULL DROP TABLE #FileList; |
| 80 | + CREATE TABLE #FileList(Id int not null identity primary key,FilePath nvarchar(2000), depth int, IsFile int) |
| 81 | + |
| 82 | + INSERT INTO #FileList(FilePath,depth,IsFile) |
| 83 | + EXEC master.sys.xp_dirtree @DirName,1,1 |
| 84 | + |
| 85 | + DELETE FROM #FileList WHERE FilePath NOT LIKE '%'+@BaseFileName+'_0_%.xel' |
| 86 | + |
| 87 | + declare @Id int = -1; |
| 88 | + |
| 89 | + IF @StopStart = 1 |
| 90 | + BEGIN |
| 91 | + SET @sql = 'ALTER EVENT SESSION '+QUOTENAME(@XeSession)+' ON SERVER STATE = STOP'; |
| 92 | + |
| 93 | + |
| 94 | + |
| 95 | + IF EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name = @XeSession) |
| 96 | + BEGIN |
| 97 | + IF @Debug = 1 RAISERROR(' Stopping event session: %s',0,1,@sql) WITH NOWAIT; |
| 98 | + EXEC(@sql); |
| 99 | + END |
| 100 | + END |
| 101 | + |
| 102 | + |
| 103 | + IF @Debug = 1 |
| 104 | + RAISERROR(' All data imported in %d ms',0,1, @TotalTime) WITH NOWAIT; |
| 105 | + |
| 106 | + -- Load list of colmns.... |
| 107 | + DECLARE @XeCols TABLE( |
| 108 | + ColId int identity |
| 109 | + ,ColName nvarchar(300) UNIQUE |
| 110 | + ,MainExpr nvarchar(2000) |
| 111 | + ,ExprType nvarchar(500) |
| 112 | + ,AlternateExpr XML |
| 113 | + ,DestCol nvarchar(300) UNIQUE |
| 114 | + ) |
| 115 | + |
| 116 | + DECLARE @DestTableColumnTypes TABLE(ColName sysname, ColType nvarchar(300)); |
| 117 | + DECLARE |
| 118 | + @DestTableDb sysname |
| 119 | + ,@DestTableName sysname |
| 120 | + |
| 121 | + |
| 122 | + IF LEFT(@DestinationTable,1) = '#' |
| 123 | + SELECT @DestTableDb = 'tempdb', @DestTableName = @DestinationTable |
| 124 | + ELSE |
| 125 | + SELECT @DestTableDb = PARSENAME(@DestinationTable,3), @DestTableName = ISNULL(quotename(PARSENAME(@DestinationTable,2)),'.')+quotename(PARSENAME(@DestinationTable,1)) |
| 126 | + |
| 127 | + set @spsql = @DestTableDb+'..sp_executesql'; |
| 128 | + |
| 129 | + IF @AutomaticDestTable = 1 |
| 130 | + BEGIN |
| 131 | + set @sql = 'SELECT |
| 132 | + C.name |
| 133 | + ,T.name+CASE |
| 134 | + WHEN T.name LIKE ''%char%'' THEN ''(''+ISNULL(CONVERT(varchar(10),NULLIF(C.max_length,-1)),''max'')+'')'' |
| 135 | + WHEN T.name IN (''numeric'',''decimal'') THEN ''(''+CONVERT(varchar(10),C.precision)+'',''+CONVERT(varchar(10),C.scale)+'')'' |
| 136 | + ELSE '''' |
| 137 | + END |
| 138 | + FROM sys.columns C |
| 139 | + INNER JOIN |
| 140 | + sys.types T |
| 141 | + ON T.system_type_id = C.system_type_id |
| 142 | + WHERE object_id = OBJECT_ID(@TableName)' |
| 143 | + |
| 144 | + insert into @DestTableColumnTypes |
| 145 | + exec @spsql @sql,N'@TableName nvarchar(500)',@DestTableName |
| 146 | + END |
| 147 | + |
| 148 | + insert into @XeCols(ColName,AlternateExpr,ExprType,DestCol) values('EventTs','''<x>(event/@timestamp)[1]</x>''','datetime','Dt_Event') |
| 149 | + insert into @XeCols(ColName,AlternateExpr,ExprType,DestCol) values('EventName','<x>(event/@name)[1]</x>','nvarchar(30)','Nm_Event') |
| 150 | + |
| 151 | + IF @IncludeEventData = 1 |
| 152 | + insert into @XeCols(ColName,AlternateExpr,ExprType,DestCol) values('EventXML','<x>.</x>','XML','EventXML') |
| 153 | + |
| 154 | + |
| 155 | + IF @Debug = 1 RAISERROR(' Mergin columnst list...',0,1) WITH NOWAIT; |
| 156 | + |
| 157 | + MERGE |
| 158 | + @XeCols D |
| 159 | + USING ( |
| 160 | + SELECT |
| 161 | + ColName = C.x.value('@name','nvarchar(300)') |
| 162 | + ,MainExpr = C.x.value('@x','nvarchar(2000)') |
| 163 | + ,ExprType = COALESCE(C.x.value('@type','nvarchar(500)'),CT.ColType) |
| 164 | + ,AlternateExpr = C.x.query('./x') |
| 165 | + ,DestCol = ISNULL(C.x.value('@dest','nvarchar(500)'),C.x.value('@name','nvarchar(300)')) |
| 166 | + FROM |
| 167 | + @Columns.nodes('col') C(x) |
| 168 | + LEFT JOIN |
| 169 | + @DestTableColumnTypes CT |
| 170 | + ON CT.ColName = ISNULL(C.x.value('@dest','nvarchar(500)'),C.x.value('@name','nvarchar(300)')) COLLATE DATABASE_DEFAULT |
| 171 | + ) S |
| 172 | + ON S.ColName = D.ColName |
| 173 | + WHEN NOT MATCHED THEN |
| 174 | + INSERT(ColName,MainExpr,ExprType,AlternateExpr,DestCol) |
| 175 | + VALUES(S.ColName,S.MainExpr,S.ExprType,S.AlternateExpr,S.DestCol) |
| 176 | + WHEN MATCHED THEN |
| 177 | + UPDATE SET DestCol = S.DestCol |
| 178 | + ; |
| 179 | + |
| 180 | + -- null type columns... |
| 181 | + DECLARE @NullCols nvarchar(max); |
| 182 | + |
| 183 | + SET @NullCols = STUFF((SELECT ','+ColName FROM @XeCols WHERE ExprType IS NULL FOR XML PATH(''),TYPE).value('.','nvarchar(max)'),1,1,'') |
| 184 | + |
| 185 | + IF @NullCols IS NOT NULL |
| 186 | + BEGIN |
| 187 | + RAISERROR('Columns %s dont have a defined data type. Check if mapping names ir correct or use automatic table.',16,1, @NullCols); |
| 188 | + RETURN; |
| 189 | + END |
| 190 | + |
| 191 | + IF @AutomaticDestTable = 1 AND EXISTS(SELECT * FROM @DestTableColumnTypes HAVING COUNT(*) = 1 AND COUNT(CASE WHEN ColName = '_auto_' THEN ColName END) = 1) |
| 192 | + SET @AutomaticTableMode = 'RecreateTable' |
| 193 | + |
| 194 | + IF @AutomaticTableMode = 'RecreateTable' |
| 195 | + BEGIN |
| 196 | + SET @sql = 'ALTER TABLE '+@DestTableName+' ADD '+STUFF(( |
| 197 | + SELECT ','+quotename(DestCol)+' '+ExprType |
| 198 | + FROM @XeCols |
| 199 | + ORDER BY ColId |
| 200 | + FOR XML PATH(''),TYPE |
| 201 | + ).value('.','nvarchar(1000)'),1,1,'') |
| 202 | + +' ALTER TABLE '+@DestTableName+' DROP COLUMN _auto_;' |
| 203 | + |
| 204 | + SET XACT_ABORT ON; |
| 205 | + BEGIN TRAN; |
| 206 | + EXEC @spsql @sql; |
| 207 | + COMMIT; |
| 208 | + END |
| 209 | + |
| 210 | + |
| 211 | + IF @Debug = 1 |
| 212 | + SELECT * FROM @XeCols |
| 213 | + |
| 214 | + |
| 215 | + |
| 216 | + |
| 217 | + IF @Debug = 1 RAISERROR(' Building xe event cols...',0,1) WITH NOWAIT; |
| 218 | + |
| 219 | + SET @XeCol = STUFF(( |
| 220 | + SELECT |
| 221 | + ','+QUOTENAME(ISNULL(DestCol,ColName))+' = '+ISNULL(REPLACE( |
| 222 | + ' COALESCE( |
| 223 | + NULL |
| 224 | + '+AlternateXPaths+' |
| 225 | + )' |
| 226 | + |
| 227 | + ,'#TYPE',ExprType),'NULL') |
| 228 | + FROM |
| 229 | + @XeCols c |
| 230 | + OUTER APPLY ( |
| 231 | + SELECT |
| 232 | + AlternateXPaths = T.sx.value('.','nvarchar(max)') |
| 233 | + FROM ( |
| 234 | + select |
| 235 | + ','+CASE |
| 236 | + WHEN UPPER(ExprType) = 'XML' THEN REPLACE(@evtDataXmlTemplate,'#XPATH',ExprPath) |
| 237 | + ELSE REPLACE(@evtDataColTEmplate,'#XPATH',ExprPath) |
| 238 | + END |
| 239 | + from ( |
| 240 | + SELECT |
| 241 | + ExprPath = NULLIF(x.p.value('data(.)','nvarchar(1000)'),'') |
| 242 | + ,ExprOrder = NULLIF(x.p.value('@order','int'),'') |
| 243 | + FROM c.AlternateExpr.nodes('x') x(p) |
| 244 | + ) XP |
| 245 | + WHERE |
| 246 | + XP.ExprPath IS NOT NULL |
| 247 | + ORDER BY |
| 248 | + ExprOrder |
| 249 | + FOR XML PATH(''),TYPE |
| 250 | + ) T(sx) |
| 251 | + ) S |
| 252 | + ORDER BY |
| 253 | + c.ColId |
| 254 | + FOR XML PATH(''),TYPE |
| 255 | + ).value('.','nvarchar(max)'),1,1,'') |
| 256 | + |
| 257 | + |
| 258 | + IF @Debug = 1 RAISERROR(' Building insert col list...',0,1) WITH NOWAIT; |
| 259 | + |
| 260 | + SET @InsertColList = STUFF(( |
| 261 | + SELECT |
| 262 | + ','+DestCol |
| 263 | + FROM |
| 264 | + @XeCols |
| 265 | + ORDER BY |
| 266 | + ColId |
| 267 | + FOR XML PATH(''),TYPE |
| 268 | + ).value('.','nvarchar(max)'),1,1,'') |
| 269 | + |
| 270 | + |
| 271 | + IF @Debug = 1 |
| 272 | + BEGIN |
| 273 | + RAISERROR('PowerAlertImportXeEvent: InsertColList: %s',0,1,@InsertColList) WITH NOWAIT; |
| 274 | + END |
| 275 | + |
| 276 | + SET @sql = ' |
| 277 | + |
| 278 | + '+ISNULL('INSERT '+@DestinationTable+'('+@InsertColList+')','')+' |
| 279 | +
|
| 280 | + SELECT |
| 281 | + '+@XeCol+' |
| 282 | + FROM |
| 283 | + #EventData e |
| 284 | +
|
| 285 | + ' |
| 286 | + |
| 287 | + IF @Debug = 1 |
| 288 | + BEGIN |
| 289 | + RAISERROR(' IMPORT SQL: %s',0,1,@sql) WITH NOWAIT; |
| 290 | + END |
| 291 | + |
| 292 | + DECLARE @RunError int,@RunRows int, @ErrorMsg nvarchar(1000) |
| 293 | + |
| 294 | + |
| 295 | + |
| 296 | + WHILE 1 = 1 |
| 297 | + BEGIN |
| 298 | + SELECT TOP 1 |
| 299 | + @CurrentFile = @DirName+'\'+FilePath |
| 300 | + ,@Id = Id |
| 301 | + FROM |
| 302 | + #FileList |
| 303 | + WHERE |
| 304 | + Id > @Id |
| 305 | + ORDER BY |
| 306 | + Id |
| 307 | + |
| 308 | + IF @@ROWCOUNT = 0 BREAK; |
| 309 | + |
| 310 | + SET @metaPattern = REPLACE(@CurrentFile,'.xel','.xem'); |
| 311 | + SET @metaPattern = @DirName+'\*.xem' |
| 312 | + IF @Debug = 1 RAISERROR(' Importing File %s (top %d events)',0,1, @CurrentFile, @topEvents) WITH NOWAIT; |
| 313 | + SET @FileImportStartTime = GETDATE() |
| 314 | + INSERT INTO |
| 315 | + #EventData |
| 316 | + SELECT top(@topEvents) |
| 317 | + F.event_data |
| 318 | + ,F.file_name |
| 319 | + FROM |
| 320 | + sys.fn_xe_file_target_read_file ( @CurrentFile,@metaPattern, null, null) as F |
| 321 | + SET @FileImportEndTime = GETDATE() |
| 322 | + SET @TotalTime = DATEDIFF(MS,@FileImportStartTime,@FileImportEndTime); |
| 323 | + |
| 324 | + IF @Debug = 1 RAISERROR(' File %s, imported in %d ms',0,1,@CurrentFile, @TotalTime) WITH NOWAIT; |
| 325 | + |
| 326 | + |
| 327 | + IF @Debug = 1 RAISERROR(' Running import sql...',0,1) WITH NOWAIT; |
| 328 | + BEGIN TRY |
| 329 | + SET @StartTime = GETDATE(); |
| 330 | + EXEC sp_executesql @sql |
| 331 | + SET @EndTime = GETDATE(); |
| 332 | + END TRY |
| 333 | + BEGIN CATCH |
| 334 | + set @RunError = ERROR_NUMBER(); |
| 335 | + set @ErrorMsg = ERROR_MESSAGE(); |
| 336 | + |
| 337 | + IF @RunError = 2389 |
| 338 | + RAISERROR('Error 2398 when running dynamic sql... Review the xpath expressions or data type choosen is correct. USe @Debug = 1 to inspect output sql... Original msg: %s',16,1,@ErrorMsg) |
| 339 | + ELSE |
| 340 | + RAISERROR(@ErrorMsg,16,1); |
| 341 | + |
| 342 | + return; |
| 343 | + END CATCH |
| 344 | + |
| 345 | + SET @TotalTime = DATEDIFF(MS,@StartTime,@EndTime); |
| 346 | + IF @Debug = 1 RAISERROR(' Running Done! Total time: %d ms',0,1,@TotalTime) WITH NOWAIT; |
| 347 | + |
| 348 | + END |
| 349 | + |
| 350 | + IF @StopStart = 1 |
| 351 | + BEGIN |
| 352 | + SET @sql = 'ALTER EVENT SESSION '+QUOTENAME(@XeSession)+' ON SERVER STATE = START'; |
| 353 | + |
| 354 | + IF NOT EXISTS(SELECT * FROM sys.dm_xe_sessions WHERE name = @XeSession) |
| 355 | + BEGIN |
| 356 | + IF @Debug = 1 RAISERROR(' Starting event session: %s',0,1,@sql) WITH NOWAIT; |
| 357 | + EXEC(@sql); |
| 358 | + END |
| 359 | + END |
| 360 | + |
| 361 | + |
| 362 | + RETURN 0; |
| 363 | + |
| 364 | + |
0 commit comments