Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

PĂ«rsĂ«ri duke vazhdon temat e organizimit Zero Touch PROD nĂ«n RDS. DBA-tĂ« e ardhshme nuk do tĂ« kenĂ« mundĂ«si tĂ« lidhen drejtpĂ«rdrejt me serverĂ«t PROD, por do tĂ« mund tĂ« pĂ«rdorin Jenkins punĂ«t pĂ«r njĂ« grup tĂ« kufizuar operacionesh. DBA-ja nis njĂ« punĂ« dhe pas njĂ« kohe merr njĂ« email me njĂ« raport mbi pĂ«rfundimin e kĂ«saj operacioni. Le tĂ« shohim mĂ«nyrat si mund t’i paraqesim kĂ«to rezultate pĂ«rdoruesit.

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Plain Text

Le të fillojmë me mënyrën më të thjeshtë. Mënyra e parë është aq e thjeshtë, saqë fakti që diskutohet është i tepruar (autori këtu dhe më tej përdor punë FreeStyle):

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

sqlcmd bën diçka dhe ne e paraqesim këtë përdoruesit. Përshtatet në mënyrë të shkëlqyer për, për shembull, punët e backup:

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Mos harro, për më tepër, se nën RDS backup/restorimi është asinkron, kështu që mirë do të ishte të prisni:

declare @rds table
  (id int, task_type varchar(128), database_name sysname, pct int, duration int, 
   lifecycle varchar(128), taskinfo varchar(max) null, 
   upd datetime, cre datetime,
   s3 varchar(256), ovr int, KMS varchar(256) null)
waitfor delay '00:00:20' 
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}'
select @xid=max(id) from @rds

again:
waitfor delay '00:00:02'
delete from @rds
insert into @rds exec msdb.dbo.rds_task_status @db_name='{db}' 
# {db} zëvendësohet me emrin e db nga powershell
select @stat=lifecycle,@info=taskinfo from @rds where id=@xid
if @stat not in ('ERROR','SUCCESS','CANCELLED') goto again

Mënyra e dytë, CSV

Këtu gjithçka është po aq e thjeshtë:

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

MegjithatĂ«, kjo metodĂ« funksionon vetĂ«m nĂ«se tĂ« dhĂ«nat qĂ« kthehen nĂ« CSV janĂ« "tĂ« thjeshta". NĂ«se provoni tĂ« ktheni, pĂ«r shembull, njĂ« listĂ« TOP N tĂ« pyetjeve intensive pĂ«r CPU, atĂ«herĂ« CSV do tĂ« "ndahen" pĂ«r shkak se teksti i pyetjes mund tĂ« pĂ«rmbajĂ« çdo shenjĂ« — presje, cita, dhe madje edhe shkĂ«putje rreshtash. Prandaj, do tĂ« na duhen disa gjĂ«ra mĂ« komplekse.

Tabela të bukura në HTML

Le të paraqesim menjëherë një fragment kodi

$Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@
  
$Result = invoke-Sqlcmd -ConnectionString $jstr -Query "select * from DbInv" `
  | Select-Object -Property * -ExcludeProperty "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result -eq $null) { $cnt = 0; }
elseif ($Result.getType().FullName -eq "System.Management.Automation.PSCustomObject") { $cnt = 1; }
else { $cnt = $Result.Rows.Count; } 
if ($cnt -gt 0) {
  $body = "<h2>Tabela ime</h2>"
  $Result | ConvertTo-HTML -Title "Rows" -Head $header -body $body `
    | Out-File "res.log" -Append -Encoding UTF8
  } else {
    "<h3>Nuk ka të dhëna</h3>" | Out-File "res.log" -Append -Encoding UTF8
  }

Kujdes, vini re linjën me System.Management.Automation.PSCustomObject, ajo është magjike, nëse në grid ka vetëm një linjë, mund të kenë lindur disa probleme. Zgjidhja është marrë nga interneti pa u shqetësuar shumë. Si rezultat, do të merrni një output të formatuar kështu:

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Grafikë

Kujdes: kodi i çmendur më poshtë!
Ka njĂ« pyetje tĂ« kĂ«ndshme nĂ« SQL Server, e cila tregon CPU-nĂ« pĂ«r minutat e fundit N — del se shoku major e ka gjithçka tĂ« regjistruar! Provoni kĂ«tĂ« pyetje:

DECLARE @ts_now bigint = (SELECT cpu_ticks/(cpu_ticks/ms_ticks) 
  FROM sys.dm_os_sys_info WITH (NOLOCK)); 
SELECT TOP(256) 
  DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS [EventTime],
  SQLProcessUtilization AS [SQLCPU], 
  100 - SystemIdle - SQLProcessUtilization AS [OtherCPU]
FROM (SELECT record.value('(./Record/@id)[1]', 'int') AS record_id, 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') 
    AS [SystemIdle], 
  record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') 
    AS [SQLProcessUtilization], [timestamp] 
  FROM (SELECT [timestamp], CONVERT(xml, record) AS [record] 
  FROM sys.dm_os_ring_buffers WITH (NOLOCK)
  WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' 
    AND record LIKE N'%%') AS x) AS y 
ORDER BY 1 DESC OPTION (RECOMPILE);

Tani, duke përdorur këtë formatim (variabla $Fragment)

<table style="width: 100%"><tbody><tr style="background-color: white; height: 2pt;">
  <td style="width: SQLCPU%; background-color: green;"></td>
  <td style="width: OtherCPU%; background-color: blue;"></td>
  <td style="width: REST%; background-color: #C0C0C0;"></td></tr></tbody>
</table>

Mund të formojmë trupin e email-it:

$Result = invoke-Sqlcmd -ConnectionString $connstr -Query $Query `
  | Select-Object -Property * -ExcludeProperty `
  "ItemArray", "RowError", "RowState", "Table", "HasErrors"
if ($Result.HasRows) {
  foreach($item in $Result) 
    { 
    $time = $itemEventTime 
    $sqlcpu = $item.SQLCPU
    $other = $itemOtherCPU
    $rest = 100 - $sqlcpu - $other
    $f = $fragment -replace "SQLCPU", $sqlcpu
    $f = $f -replace "OtherCPU", $other
    $f = $f -replace "REST", $rest
    $f | Out-File "res.log" -Append -Encoding UTF8
    }

Që do të duket kështu:

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Po, me siguri, zotëri di si ta kthejë në të çmendur! Nga e çuditshme është se ky kod përmban në vete: Powershell (në të është shkruar), SQL, Xquery, HTML. Do të ishte mirë që HTML të përfshinte Javascript (siç është për email), por përmirësimi i kodit në Python (i cili mund të përdoret në SQL) është detyrë e secilit!

Dalja e gjurmës së profiler-it SQL

QartĂ«, qĂ« gjurma "nuk do tĂ« hyjĂ«" nĂ« CSV pĂ«r shkak tĂ« fushĂ«s TextData. Por pĂ«r ta paraqitur gjurmĂ«n nĂ« grid nĂ« email Ă«shtĂ« gjithashtu e çuditshme — tĂ« shkakton pĂ«rmasĂ« dhe madje pĂ«r shkak se shpesh kĂ«to tĂ« dhĂ«na pĂ«rdoren pĂ«r analizĂ« tĂ« mĂ«tejshme. Prandaj ne bĂ«jmĂ« si mĂ« poshtĂ«: thĂ«rrasim pĂ«rmes invoke-SqlCmd njĂ« skenar, nĂ« tĂ« cilin bĂ«het

select 
  SPID,EventClass,TextData,
  Duration,Reads,Writes,CPU,
  StartTime,EndTime,DatabaseName,HostName,
  ApplicationName,LoginName
   from ::fn_trace_gettable ( @filename , default )  

Më pas, në një tjetër serveri, e cila është në dispozicion të DBA-së, ekziston një bazë Traces me një model të zbrazët, një tabelë Model, e cila është e gatshme të pranojë të gjitha kolonat e cituara. Ne e kopjojmë këtë model në një tabelë të re me një emër unik:

$dt = Get-Date -format "yyyyMMdd"
$tm = Get-Date -format "hhmmss"
$tableName = $srv + "_" + $dt + "_" + $tm
$copytab = "select * into " + $tableName + " from Model"
invoke-SqlCmd -ConnectionString $tstr -Query $copytab 

Dhe tani mund ta regjistrojmĂ« gjurmĂ«n tonĂ« pĂ«rmes Data.SqlClient.SqlBulkCopy — njĂ« shembull i kĂ«tij Ă«shtĂ« dhĂ«nĂ« mĂ« sipĂ«r. Po, do tĂ« ishte mirĂ« tĂ« bĂ«jmĂ« mascarĂ« tĂ« konstantave nĂ« TextData:

# mask data
foreach ($Row in $Result)
{ 
  $v = $Row["TextData"]
  $v = $v -replace "'([^']{2,})'", "'str'" -replace "[0-9][0-9]+", '999'
  $Row["TextData"] = $v
}

Ne zĂ«vendĂ«sojmĂ« numrat me mĂ« shumĂ« se njĂ« karakter tĂ« gjatĂ« me 999, dhe stringjet mĂ« tĂ« gjata se njĂ« karakter i zĂ«vendĂ«sojmĂ« me 'str'. Numrat nga 0 nĂ« 9 shpesh pĂ«rdoren si tregues, dhe nuk i prekim ato, as siç janĂ« stringjet e zbrazĂ«ta dhe ato me njĂ« karakter — mes tyre shpesh gjenden 'Y', 'N' etj.

Shtojmë ngjyra në jetën tonë (rreptësisht 18+)

Në tabela shpesh dëshirohet të nxirren qeliza që kërkojnë vëmendje. Për shembull, FAILS, niveli i lartë i fragmentimit etj. Sigurisht, kjo mund të bëhet edhe me SQL të pastër, duke formuar HTML nëpërmjet PRINT, ndersa në Jenkins vendosim llojin e skedarit HTML:

declare @body varchar(max), @chunk varchar(max)
set @body='<font face="Lucida Console" size="3">'
set @body=@body+'<b>Server name: '+@@servername+'</b><br>'
set @body=@body+'<br><br>'
set @body=@body+'<table><tr><th>Job</th><th>Last Run</th><th>Avg Duration, sec</th><th>Last Run, Sec</th><th>Last Status</th></tr>'
print @body

DECLARE tab CURSOR FOR SELECT '<tr><td>'+name+'</td><td>'+
  LastRun+'</td><td>'+
  convert(varchar,AvgDuration)+'</td><td>'+
  convert(varchar,LastDuration)+'</td><td>'+
    case when LastStatus<>'Succeeded' then '<font color="red">' else '' end+
      LastStatus+
      case when LastStatus<>'Succeeded' then '</font>' else '' end+
     +'</td><td>'
  from #j2
OPEN tab;  
FETCH NEXT FROM tab into @chunk
WHILE @@FETCH_STATUS = 0  
BEGIN
  print @chunk
  FETCH NEXT FROM tab into @chunk;  
END  
CLOSE tab;  
DEALLOCATE tab;
print '</table>'

Përse e shkrova këtë kod?

Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Por ka një zgjidhje më të bukur. ConvertTo-HTML nuk na lejon të ngjyrosim qelizat, por mund ta bëjmë këtë pas faktit. Për shembull, ne duam të theksojmë qelizat me një nivel fragmentimi mbi 80 dhe mbi 90. Le të shtojmë stilet:

.SQLmarkup-red { color: red; background-color: yellow; }
.SQLmarkup-yellow { color: black; background-color: #FFFFE0; }
.SQLmarkup-default { color: black; background-color: white; }

Në vetë këshillën, do të shtojmë një kolonë fiktive drejt për kolonës që duam të ngjyrosim. Kolona duhet të quhet SQLmarkup-diçka:

rast  
  kur ps.avg_fragmentation_in_percent>=90.0 atëherë 'SQLmarkup-red'
  kur ps.avg_fragmentation_in_percent>=80.0 atëherë 'SQLmarkup-yellow'
  përndryshe 'SQLmarkup-default' 
  mbyll si [SQLmarkup-1], 
ps.avg_fragmentation_in_percent, 

Tani, duke marrë HTML-në e krijuar nga Powershell, ne do ta heqim kolonën fiktive nga titulli, dhe në trupin e të dhënave do ta transferojmë vlerën nga kolona në stil. Kjo bëhet me vetëm dy zëvendësime:

$html = $html `
  -zëvendëso "<th>SQLmarkup[^<]*</th>", "" `
  -zëvendëso "<td>SQLmarkup-(.+?)</td><td>",'<td class="SQLmarkup-$1">'

Rezultati:
Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Nuk është mëse elegante? Sidoqoftë, diçka kjo ngjyrosje më kujton
Automatizimi i SQL server në Jenkins: kthen rezultatin në mënyrë të bukur

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster