استمرار موضوع ترتيب Zero Touch PROD تحت RDS مرة أخرى. لن تتمكن DBAs في المستقبل من الاتصال بملقمات PROD مباشرة ، ولكنها ستكون قادرة على استخدام وظائف
Jenkins لمجموعة محدودة من العمليات. DBA يبدأ العمل وبعد فترة من الوقت يتلقى رسالة مع تقرير عن الانتهاء من هذه العملية. لنلقِ نظرة على طرق تقديم هذه النتائج إلى المستخدم.

نص عادي
لنبدأ مع أكثر تافهة. الطريقة الأولى بسيطة للغاية بحيث لا يوجد شيء يمكن الحديث عنه بشكل عام (يستخدم المؤلف فيما يلي وظائف FreeStyle):
sqlcmd يفعل شيئا ، ونحن نقدمه للمستخدم. مثالي ، على سبيل المثال ، لمهام النسخ الاحتياطي:

بالمناسبة ، لا ننسى أنه تحت 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}'
الطريقة الثانية ، CSV
كل شيء هنا بسيط للغاية أيضًا:

ومع ذلك ، لا تعمل هذه الطريقة إلا إذا كانت البيانات التي يتم إرجاعها إلى ملف 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 يعرض وحدة المعالجة المركزية في الدقائق الأخيرة من N - اتضح أن Comrade Major يتذكر كل شيء! جرب هذا واحد:
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 }
والتي سوف تبدو مثل هذا:

نعم ، المسيو يعرف الكثير عن الانحرافات! ومن المثير للاهتمام ، أن هذا الرمز يحتوي على: Powershell (مكتوب عليه) ، SQL ، Xquery ، HTML. إنه لأمر مؤسف أننا لا نستطيع إضافة Javascript إلى HTML (لأن هذا مخصص للكتابة) ، ولكن من واجب الجميع طحن كود Python (والذي يمكن استخدامه في SQL)!
مزود تتبع منشئ ملفات التعريف SQL
من الواضح أن التتبع لن "يلائم" ملف CSV بسبب حقل TextData. لكن من الغريب أيضًا عرض الشبكة في خطاب - بسبب الحجم ولأنه يتم استخدام هذه البيانات في كثير من الأحيان لإجراء مزيد من التحليل. لذلك ، نحن نقوم بما يلي:
ندعو من خلال
استدعاء - SqlCmd النصي معين ، في الأمعاء التي يتم ذلك
select SPID,EventClass,TextData, Duration,Reads,Writes,CPU, StartTime,EndTime,DatabaseName,HostName, ApplicationName,LoginName from ::fn_trace_gettable ( @filename , default )
علاوة على ذلك ، على خادم
آخر يمكن الوصول إليه بواسطة DBA ، هناك قاعدة Traces فارغة ، لوحة Model ، جاهزة لقبول جميع الأعمدة المحددة. نقوم بنسخ هذا النموذج إلى جدول جديد باسم فريد:
$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:
نستبدل الأرقام بأكثر من حرف واحد بطول 999 ، ونستبدل السلاسل الأطول من حرف واحد بحرف "str". غالبًا ما يتم استخدام الأرقام من 0 إلى 9 كأعلام ، ونحن لا نلمسها ، وكذلك السلاسل الفارغة والأحادية الأحرف - من بينها غالبًا ما توجد "Y" و "N" ، إلخ.
أضف ألوانًا لحياتنا (بدقة أكبر من 18 عامًا)
غالبًا ما ترغب في إبراز الخلايا التي تتطلب الانتباه في الأجهزة اللوحية. على سبيل المثال ، FAILS ، مستوى عال من التجزئة ، إلخ. بالطبع ، يمكن القيام بذلك أيضًا باستخدام SQL عارية ، وتكوين HTML باستخدام PRINT ، ويمكنك في Jenkins تعيين نوع ملف 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
لماذا كتبت هذا الكود؟

ولكن هناك حل أكثر جمالا. لا يسمح لنا برنامج
ConvertTo-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>
في qi نفسه ، سنقوم بإضافة عمود وهمية
مباشرة إلى العمود الذي نريد تلوينه. يجب أن يسمى العمود
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,
الآن ، بعد تلقي HTML الذي أنشأه Powershell ، سنقوم بإزالة العمود الوهمي من الرأس ونقل القيمة من العمود إلى النمط في نص البيانات. يتم ذلك في اثنين فقط من التباديل:
$html = $html ` -replace "<th>SQLmarkup[^<]*</th>", "" ` -replace "<td>SQLmarkup-(.+?)</td><td>",'<td class="SQLmarkup-$1">'
النتيجة:

أليس كذلك أنيق؟ على الرغم من لا ، هذا شيء يذكرني هذا التلوين
