Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Дахиад л зохион байгуулалтын сэдвийг үргэлжлүүлж байна Zero Touch PROD RDS дор. Ирээдүйн DBA-ууд PROD сервертэй шууд холбогдох боломжгүй, харин ашиглах боломжтой болно Jenkins хязгаарлагдмал багц үйл ажиллагаанд зориулсан ажлын байр. DBA нь ажлаа эхлүүлж, хэсэг хугацааны дараа энэ үйл ажиллагаа дууссан тухай тайлан бүхий захидал хүлээн авдаг. Эдгээр үр дүнг хэрэглэгчдэд үзүүлэх арга замуудыг харцгаая.

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Энгийн текст

Хамгийн өчүүхэн зүйлээс эхэлье. Эхний арга нь маш энгийн тул ярих зүйл алга (зохиогч цаашид FreeStyle ажлуудыг ашигладаг):

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

sqlcmd ямар нэг зүйл хийдэг бөгөөд бид үүнийг хэрэглэгчдэд танилцуулдаг. Жишээлбэл, нөөцлөх ажилд тохиромжтой:

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Дашрамд хэлэхэд, RDS нөөцлөх/сэргээх нь асинхрон биш тул та үүнийг хүлээх хэрэгтэй гэдгийг битгий мартаарай.

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

Хоёрдахь арга, CSV

Энд бүх зүйл маш энгийн:

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Гэсэн хэдий ч, энэ арга нь зөвхөн CSV-д буцаж ирсэн өгөгдөл "энгийн" тохиолдолд л ажиллана. Хэрэв та жишээлбэл, TOP N CPU-ийн эрчимтэй асуулгын жагсаалтыг ийм байдлаар буцаахыг оролдвол асуулгын текст нь таслал, ишлэл, тэр ч байтугай мөр таслал зэрэг ямар ч тэмдэгт агуулсан байж болох тул CSV нь "зэврэх" болно. Тиймээс бидэнд илүү төвөгтэй зүйл хэрэгтэй байна.

HTML хэл дээрх үзэсгэлэнтэй тэмдгүүд

Би танд нэн даруй кодын хэсгийг өгөх болно

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

Дашрамд хэлэхэд, System.Management.Automation.PSCustomObject гэсэн мөрөнд анхаарлаа хандуулаарай, энэ нь ид шидтэй, хэрэв сүлжээнд яг нэг мөр байгаа бол зарим асуудал гарч ирнэ. Уг шийдлийг нэг их ойлголгүй интернетээс авсан. Үүний үр дүнд та дараах форматтай гаралтыг авах болно:

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

График зурах

Анхааруулга: доорх кодтой!
SQL сервер дээр сүүлийн N минутын турш CPU-г харуулсан инээдтэй асуулт байна - Нөхөр хошууч бүгдийг санаж байгаа нь харагдаж байна! Энэ асуулт хариултыг туршиж үзээрэй:

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

Одоо энэ форматыг ашиглаж байна ($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>

Бид захидлын үндсэн хэсгийг үүсгэж болно:

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

Энэ нь иймэрхүү харагдах болно:

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Тийм ээ, эрхэм хүн гажуудлын талаар ихийг мэддэг! Энэ код нь Powershell (үүнд бичигдсэн), SQL, Xquery, HTML агуулсан байгаа нь сонирхолтой юм. Бид HTML-д Javascript-г нэмж чадахгүй байгаа нь харамсалтай (бичих зориулалттай учраас), гэхдээ Python кодыг (SQL-д ашиглаж болно) өнгөлөх нь хүн бүрийн үүрэг юм!

SQL профайлын ул мөр гаралт

TextData талбараас болж ул мөр нь CSV-д багтахгүй нь тодорхой байна. Гэхдээ мөрийн сүлжээг захидалд харуулах нь бас хачирхалтай юм - хэмжээ, энэ өгөгдлийг цаашдын шинжилгээнд ихэвчлэн ашигладаг учраас хоёулаа. Тиймээс бид дараахь зүйлийг хийдэг: бид дамжуулан дууддаг invoke-SqlCmd тодорхой скрипт, түүний гүнд үүнийг хийдэг

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

Дараа нь, дээр найз DBA-д хандах боломжтой сервер дээр бүх заасан баганыг хүлээн авахад бэлэн загвар хавтан бүхий Traces мэдээллийн сан байна. Бид энэ загварыг өвөрмөц нэртэй шинэ хүснэгтэд хуулна.

$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 

Одоо бид түүн рүү мөрийг ашиглан бичиж болно Data.SqlClient.SqlBulkCopy -Үүний жишээг би дээр хэлсэн. Тийм ээ, TextData дахь тогтмолуудыг далдлах нь бас сайхан байх болно:

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

Бид нэг тэмдэгтээс илүү урттай тоог 999-ээр, нэг тэмдэгтээс урт тэмдэгтүүдийг 'str'-ээр сольдог. 0-ээс 9 хүртэлх тоонуудыг ихэвчлэн туг болгон ашигладаг бөгөөд бид тэдгээрт хүрдэггүй, мөн хоосон, нэг тэмдэгттэй мөрүүд - 'Y', 'N' гэх мэт тэмдэгтүүд ихэвчлэн олддог.

Амьдралдаа өнгө нэмэцгээе (18+)

Хүснэгтэнд та ихэвчлэн анхаарал шаарддаг нүднүүдийг тодруулахыг хүсдэг. Жишээлбэл, FAILS, өндөр түвшний хуваагдал гэх мэт. Мэдээжийн хэрэг, үүнийг нүцгэн SQL дээр хийж, PRINT ашиглан HTML үүсгэж, Женкинс дэх файлын төрлийг 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>'

Би яагаад ийм код бичсэн юм бэ?

Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Гэхдээ илүү гоё шийдэл бий. HTML рүү хөрвүүлэх эсийг будахыг зөвшөөрдөггүй, гэхдээ бид үүнийг хийсний дараа үүнийг хийж чадна. Жишээлбэл, бид 80-аас дээш, 90-ээс дээш хуваагдсан нүднүүдийг сонгохыг хүсч байна. Загвар нэмье:

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

Асуулгад бид хуурамч багана нэмэх болно шууд өмнө багана бид өнгө оруулахыг хүсч байна. Баганыг дуудах хэрэгтэй SQLmarkup-ямар нэг зүйл:

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, 

Одоо Powershell-ийн үүсгэсэн HTML-г хүлээн авсны дараа бид толгойн хэсгээс дамми баганыг устгаж, өгөгдлийн үндсэн хэсэгт утгыг баганаас хэв маяг руу шилжүүлэх болно. Үүнийг зөвхөн хоёр орлуулалтаар хийдэг:

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

Үр дүн:
Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Дэгжин биш гэж үү? Үгүй ч гэсэн энэ өнгө надад ямар нэг зүйлийг сануулж байна
Женкинс дэх SQL серверийн автоматжуулалт: үр дүнг сайхан буцаана

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх