Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

igen fortsÀtter pÄ temat arrangemang Zero Touch PROD under RDS. Framtida DBA:er kommer inte att kunna ansluta till PROD-servrar direkt, men kommer att kunna anvÀnda Jenkins jobb för en begrÀnsad uppsÀttning verksamheter. DBA startar jobbet och fÄr efter en tid ett brev med en rapport om slutförandet av denna operation. LÄt oss titta pÄ sÀtt att presentera dessa resultat för anvÀndaren.

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Plain Text

LÄt oss börja med det mest triviala. Den första metoden Àr sÄ enkel att det egentligen inte finns nÄgot att prata om (författaren anvÀnder hÀdanefter FreeStyle-jobb):

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

sqlcmd gör nÄgot och vi presenterar det för anvÀndaren. Idealisk för till exempel backupjobb:

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Glöm förresten inte att sÀkerhetskopiering/ÄterstÀllning under RDS Àr asynkron, sÄ du mÄste vÀnta pÄ det:

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} substituted with db name by powershell
select @stat=lifecycle,@info=taskinfo from @rds where id=@xid
if @stat not in ('ERROR','SUCCESS','CANCELLED') goto again

Andra metoden, CSV

Allt hÀr Àr ocksÄ vÀldigt enkelt:

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Den hÀr metoden fungerar dock bara om data som returneras i CSV:en Àr "enkla". Om du försöker returnera, till exempel, en lista över TOP N CPU-intensiva frÄgor pÄ detta sÀtt, kommer CSV:en att "korrodera" pÄ grund av att frÄgetexten kan innehÄlla vilka tecken som helst - kommatecken, citattecken och till och med radbrytningar. DÀrför behöver vi nÄgot mer komplicerat.

Vackra skyltar i HTML

Jag ger dig ett kodavsnitt direkt

$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>My table</h2>"
  $Result | ConvertTo-HTML -Title "Rows" -Head $header -body $body `
    | Out-File "res.log" -Append -Encoding UTF8
  } else {
    "<h3>No data</h3>" | Out-File "res.log" -Append -Encoding UTF8
  }

Förresten, var uppmÀrksam pÄ raden med System.Management.Automation.PSCustomObject, den Àr magisk; om det finns exakt en rad i rutnÀtet sÄ uppstod nÄgra problem. Lösningen hÀmtades frÄn Internet utan större förstÄelse. Som ett resultat kommer du att fÄ utdata formaterad ungefÀr sÄ hÀr:

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Rita grafer

Varning: kinky kod nedan!
Det finns en rolig frÄga pÄ SQL-servern som visar CPU de sista N minuterna - det visar sig att kamrat Major kommer ihÄg allt! Testa detta frÄgesport:

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'%<SystemHealth>%') AS x) AS y 
ORDER BY 1 DESC OPTION (RECOMPILE);

AnvÀnd nu denna formatering ($Fragment-variabel)

<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>

Vi kan bilda brevets kropp:

$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
    }

Som kommer att se ut sÄ hÀr:

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Ja, Monsieur vet mycket om perversioner! Det Àr intressant att den hÀr koden innehÄller: Powershell (skriven i den), SQL, Xquery, HTML. Det Àr synd att vi inte kan lÀgga till Javascript i HTML (eftersom det Àr för att skriva), men att polera Python-kod (som kan anvÀndas i SQL) Àr allas skyldighet!

SQL profiler spÄra utdata

Det Ă€r tydligt att spĂ„ret inte kommer att passa in i CSV-filen pĂ„ grund av TextData-fĂ€ltet. Men att visa ett spĂ„rrutnĂ€t i en bokstav Ă€r ocksĂ„ konstigt – bĂ„de pĂ„ grund av storleken och för att dessa data ofta anvĂ€nds för vidare analys. DĂ€rför gör vi följande: vi ringer via invoke-SqlCmd ett visst manus, i vars djup det Ă€r gjort

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

NÀsta, pÄ andra server, tillgÀnglig för databasadministratören, finns en Traces-databas med en tom mall, en modelltabell, redo att acceptera alla angivna kolumner. Vi kopierar denna modell till en ny tabell med ett unikt namn:

$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 

Och nu kan vi skriva in vĂ„rt spĂ„r i den med hjĂ€lp av Data.SqlClient.SqlBulkCopy – Jag har redan gett ett exempel pĂ„ detta ovan. Ja, det skulle ocksĂ„ vara trevligt att maskera konstanter i TextData:

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

Vi ersÀtter siffror som Àr lÀngre Àn ett tecken med 999, och vi ersÀtter strÀngar som Àr lÀngre Àn ett tecken med 'str'. Siffror frÄn 0 till 9 anvÀnds ofta som flaggor, och vi rör dem inte, liksom tomma och enkaraktÀrsstrÀngar - 'Y', 'N', etc. finns ofta bland dem.

LÄt oss lÀgga lite fÀrg pÄ vÄra liv (strÀngt 18+)

I tabeller vill man ofta markera celler som krÀver uppmÀrksamhet. Till exempel FAILS, hög grad av fragmentering, etc. Naturligtvis kan detta göras i ren SQL, generera HTML med PRINT och stÀlla in filtypen till HTML i Jenkins:

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>'

Varför skrev jag en sÄdan kod?

Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Men det finns en vackrare lösning. Konvertera till HTML lÄter oss inte fÀrga cellerna, men vi kan göra det i efterhand. Till exempel vill vi vÀlja celler med en fragmenteringsnivÄ pÄ mer Àn 80 och mer Àn 90. LÄt oss lÀgga till stilar:

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

I sjÀlva frÄgan lÀgger vi till en dummy-kolumn omedelbart innan kolumn vi vill fÀrglÀgga. Kolumnen ska kallas SQLmarkup-nÄgot:

case  
  when ps.avg_fragmentation_in_percent>=90.0 then 'SQLmarkup-red'
  when ps.avg_fragmentation_in_percent>=80.0 then 'SQLmarkup-yellow'
  else 'SQLmarkup-default' 
  end as [SQLmarkup-1], 
ps.avg_fragmentation_in_percent, 

Nu, efter att ha tagit emot HTML-koden som genererats av Powershell, tar vi bort dummykolumnen frÄn rubriken, och i datakroppen kommer vi att överföra vÀrdet frÄn kolumnen till stilen. Detta görs med bara tvÄ byten:

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

Resultat:
Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

Är det inte elegant? Fast nej, den hĂ€r fĂ€rgen pĂ„minner mig om nĂ„got
Automatisering av SQL-server i Jenkins: returnerar resultatet vackert

KĂ€lla: will.com

Köp pĂ„litlig hosting för webbplatser med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster