Skip to content

Commit

Permalink
Add trends (#28)
Browse files Browse the repository at this point in the history
  • Loading branch information
webtonize authored Jan 11, 2024
1 parent f4cb2e0 commit 2ba035f
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 30 deletions.
145 changes: 119 additions & 26 deletions src/bicep/modules/azdo-main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ var workbook = {
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: [
'value::all'
'psrule-scan-ado'
]
}
]
Expand All @@ -92,7 +92,7 @@ var workbook = {
type: 3
content: {
version: 'KqlItem/1.0'
query: 'PSRule_CL\r\n| sort by TimeGenerated asc \r\n| extend \r\n a=parse_json(Annotations_s),\r\n f=parse_json(Field_s)\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| summarize \r\n [\'Audit DateTime\']=max(TimeGenerated),\r\n [\'Failed Checkpoints\']=countif(Outcome_s == \'Fail\'),\r\n [\'Passed Checkpoints\']=countif(Outcome_s == \'Pass\'),\r\n [\'Rules Checked\']=dcount(RuleName_s),\r\n [\'Resources Checked\']=dcount(TargetName_s)\r\n by \r\n RunId_s\r\n//| project RunId_s, todatetime([\'Audit DateTime\']), [\'Rules Checked\'], [\'Resources Checked\'], [\'Failed Checkpoints\'], [\'Passed Checkpoints\']\r\n| sort by [\'Audit DateTime\'] desc\r\n| top 4 by [\'Audit DateTime\'] desc'
query: 'PSRule_CL\r\n| sort by TimeGenerated asc \r\n| extend \r\n a=parse_json(Annotations_s),\r\n f=parse_json(Field_s)\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| summarize \r\n [\'Audit DateTime\']=format_datetime(max(TimeGenerated), "yyyy-MM-dd HH:mm"),\r\n [\'Failed Checkpoints\']=countif(Outcome_s == \'Fail\'),\r\n [\'Passed Checkpoints\']=countif(Outcome_s == \'Pass\'),\r\n [\'Total Checkpoints\']=count(Outcome_s),\r\n [\'Rules Checked\']=dcount(RuleName_s),\r\n [\'Resources Checked\']=dcount(TargetName_s)\r\n by \r\n RunId_s\r\n//| project RunId_s, todatetime([\'Audit DateTime\']), [\'Rules Checked\'], [\'Resources Checked\'], [\'Failed Checkpoints\'], [\'Passed Checkpoints\']\r\n| sort by [\'Audit DateTime\'] desc\r\n| extend\r\n [\'Pass Percentage\']=round(100 * todecimal([\'Passed Checkpoints\']) / todecimal([\'Total Checkpoints\']), 2)\r\n| extend\r\n [\'Trend\']=round([\'Pass Percentage\'] - next([\'Pass Percentage\']), 2) \r\n| top 4 by [\'Audit DateTime\'] desc'
size: 4
timeContext: {
durationMs: 2592000000
Expand All @@ -103,8 +103,9 @@ var workbook = {
tileSettings: {
titleContent: {
columnMatch: 'Audit DateTime'
formatter: 6
formatter: 1
dateFormat: {
showUtcTime: null
formatName: 'shortDateTimePattern'
}
tooltipFormat: {
Expand All @@ -117,50 +118,79 @@ var workbook = {
tooltip: 'Resources checked'
}
}
leftContent: {
columnMatch: 'Failed Checkpoints'
formatter: 12
formatOptions: {
palette: 'red'
}
tooltipFormat: {
tooltip: 'Failed checkpoints'
}
}
rightContent: {
columnMatch: 'Passed Checkpoints'
formatter: 12
columnMatch: 'Trend'
formatter: 18
formatOptions: {
palette: 'green'
thresholdsOptions: 'icons'
thresholdsGrid: [
{
operator: '=='
thresholdValue: '0'
representation: 'Subtract'
text: '{0}{1}'
}
{
operator: '<'
thresholdValue: '0'
representation: 'trenddown'
text: '{0}{1}'
}
{
operator: '>'
thresholdValue: '0'
representation: 'trendup'
text: '{0}{1}'
}
{
operator: 'Default'
thresholdValue: null
representation: 'success'
text: '{0}{1}'
}
]
compositeBarSettings: {
labelText: ''
columnSettings: []
}
}
numberFormat: {
unit: 1
options: {
style: 'decimal'
minimumFractionDigits: 2
}
}
tooltipFormat: {
tooltip: 'Passed checkpoints'
tooltip: 'Pass trend'
}
}
secondaryContent: {
columnMatch: 'Rules Checked'
formatter: 2
columnMatch: 'Pass Percentage'
formatter: 22
formatOptions: {
compositeBarSettings: {
labelText: ''
labelText: 'Pass percentage ["Pass Percentage"]%'
columnSettings: [
{
columnName: 'Failed Checkpoints'
color: 'redBright'
}
{
columnName: 'Passed Checkpoints'
color: 'green'
}
{
columnName: 'Failed Checkpoints'
color: 'redBright'
}
]
}
}
numberFormat: {
unit: 1
options: {
style: 'decimal'
}
}
tooltipFormat: {
tooltip: 'Rules checked'
tooltip: 'Pass Percentage'
}
}
showBorder: true
Expand Down Expand Up @@ -273,13 +303,14 @@ var workbook = {
type: 3
content: {
version: 'KqlItem/1.0'
query: 'PSRule_CL\r\n| sort by TimeGenerated asc \r\n| extend \r\n a=parse_json(Annotations_s),\r\n f=parse_json(Field_s)\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| summarize \r\n [\'Audit DateTime\']=max(TimeGenerated),\r\n [\'Failed Checkpoints\']=countif(Outcome_s == \'Fail\'),\r\n [\'Passed Checkpoints\']=countif(Outcome_s == \'Pass\'),\r\n [\'Rules Checked\']=dcount(RuleName_s),\r\n [\'Resources Checked\']=dcount(TargetName_s)\r\n by \r\n RunId_s\r\n| project RunId_s, todatetime([\'Audit DateTime\']), [\'Rules Checked\'], [\'Resources Checked\'], [\'Failed Checkpoints\'], [\'Passed Checkpoints\']\r\n| sort by [\'Audit DateTime\'] desc\r\n'
query: 'PSRule_CL\r\n| sort by TimeGenerated asc \r\n| extend \r\n a=parse_json(Annotations_s),\r\n f=parse_json(Field_s)\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| summarize \r\n [\'Audit DateTime\']=max(TimeGenerated),\r\n [\'Failed Checkpoints\']=countif(Outcome_s == \'Fail\'),\r\n [\'Passed Checkpoints\']=countif(Outcome_s == \'Pass\'),\r\n [\'Total Checkpoints\']=count(Outcome_s),\r\n [\'Rules Checked\']=dcount(RuleName_s),\r\n [\'Resources Checked\']=dcount(TargetName_s)\r\n by \r\n RunId_s\r\n| extend\r\n [\'Pass Percentage\']=round(100 * todecimal([\'Passed Checkpoints\']) / todecimal([\'Total Checkpoints\']), 2)\r\n| project RunId_s, todatetime([\'Audit DateTime\']), [\'Rules Checked\'], [\'Resources Checked\'], [\'Failed Checkpoints\'], [\'Passed Checkpoints\'], [\'Pass Percentage\']\r\n| sort by [\'Audit DateTime\'] desc\r\n| extend\r\n [\'Trend\']=round([\'Pass Percentage\'] - next([\'Pass Percentage\']), 2)'
size: 0
timeContext: {
durationMs: 2592000000
}
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
visualization: 'table'
gridSettings: {
formatters: [
{
Expand Down Expand Up @@ -328,6 +359,12 @@ var workbook = {
viewerMode: false
}
}
numberFormat: {
unit: 17
options: {
style: 'decimal'
}
}
}
{
columnMatch: 'Resources Checked'
Expand Down Expand Up @@ -364,6 +401,12 @@ var workbook = {
viewerMode: false
}
}
numberFormat: {
unit: 17
options: {
style: 'decimal'
}
}
}
{
columnMatch: 'Failed Checkpoints'
Expand All @@ -379,6 +422,56 @@ var workbook = {
aggregation: 'Sum'
}
}
{
columnMatch: 'Pass Percentage'
formatter: 1
numberFormat: {
unit: 1
options: {
style: 'decimal'
}
}
}
{
columnMatch: 'Trend'
formatter: 18
formatOptions: {
thresholdsOptions: 'icons'
thresholdsGrid: [
{
operator: '=='
thresholdValue: '0'
representation: 'Subtract'
text: '{0}{1}'
}
{
operator: '<'
thresholdValue: '0'
representation: 'trenddown'
text: '{0}{1}'
}
{
operator: '>'
thresholdValue: '0'
representation: 'trendup'
text: '{0}{1}'
}
{
operator: 'Default'
thresholdValue: null
representation: 'success'
text: '{0}{1}'
}
]
}
numberFormat: {
unit: 1
options: {
style: 'decimal'
minimumFractionDigits: 2
}
}
}
]
sortBy: [
{
Expand Down
6 changes: 3 additions & 3 deletions src/bicep/modules/azdo-resource-state.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ var workbook = {
}
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: 'c442098b2437a6f6f3496768ba2f698790ecab2f'
value: 'psrule-scan-ado/287'
}
{
id: 'ae4e2baa-2cc1-4dc6-a31b-0b0ca2dcf2c1'
Expand Down Expand Up @@ -93,7 +93,7 @@ var workbook = {
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: [
'value::all'
'psrule-scan-ado'
]
}
]
Expand Down Expand Up @@ -223,7 +223,7 @@ var workbook = {
type: 3
content: {
version: 'KqlItem/1.0'
query: 'PSRule_CL\r\n| where RunId_s == \'{runId:value}\'\r\n| extend a=parse_json(Annotations_s), f=parse_json(Field_s)\r\n| extend Severity=a.severity, [\'Rule Help Url\']=a.[\'online version\'],Category=a.category\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| extend severity_level = case(\r\n Severity == "Informational" and Outcome_s == \'Fail\', 1,\r\n Severity == "Important" and Outcome_s == \'Fail\', 2,\r\n Severity == "Severe" and Outcome_s == \'Fail\', 3,\r\n Severity == "Critical" and Outcome_s == \'Fail\', 4,\r\n 0)\r\n| summarize\r\n [\'Resource state\'] = arg_max(severity_level, *),\r\n [\'Failed Rules\'] = countif(Outcome_s == \'Fail\'),\r\n [\'Passed Rules\'] = countif(Outcome_s == \'Pass\')\r\n by tostring(TargetName_s)\r\n| extend Findings = case(\r\n [\'Resource state\'] == 1, "Informational",\r\n [\'Resource state\'] == 2, "Important",\r\n [\'Resource state\'] == 3, "Severe",\r\n [\'Resource state\'] == 4, "Critical",\r\n [\'Resource state\'] == 0, "Passed all rules",\r\n "Not found")\r\n| project Organization, Project, [\'Resource Name\']=ResourceName, [\'Resource Type\'] = TargetType_s, Findings, [\'Failed Rules\'], [\'Passed Rules\'], [\'Resource FQN\'] = TargetName_s\r\n| where Findings == \'{SeverityFilter}\' or \'All Resources\' == \'{SeverityFilter}\'\r\n'
query: 'PSRule_CL\r\n| where RunId_s == \'{runId:value}\'\r\n| extend a=parse_json(Annotations_s), f=parse_json(Field_s)\r\n| extend Severity=a.severity, [\'Rule Help Url\']=a.[\'online version\'],Category=a.category\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| extend severity_level = case(\r\n Severity == "Informational" and Outcome_s == \'Fail\', 1,\r\n Severity == "Important" and Outcome_s == \'Fail\', 2,\r\n Severity == "Severe" and Outcome_s == \'Fail\', 3,\r\n Severity == "Critical" and Outcome_s == \'Fail\', 4,\r\n 0)\r\n| summarize\r\n [\'Resource state\'] = arg_max(severity_level, *),\r\n [\'Failed Rules\'] = countif(Outcome_s == \'Fail\'),\r\n [\'Passed Rules\'] = countif(Outcome_s == \'Pass\')\r\n by tostring(TargetName_s)\r\n| sort by [\'Resource state\'] desc\r\n| extend Findings = case(\r\n [\'Resource state\'] == 1, "Informational",\r\n [\'Resource state\'] == 2, "Important",\r\n [\'Resource state\'] == 3, "Severe",\r\n [\'Resource state\'] == 4, "Critical",\r\n [\'Resource state\'] == 0, "Passed all rules",\r\n "Not found")\r\n| project Organization, Project, [\'Resource Name\']=ResourceName, [\'Resource Type\'] = TargetType_s, Findings, [\'Failed Rules\'], [\'Passed Rules\'], [\'Resource FQN\'] = TargetName_s\r\n| where Findings == \'{SeverityFilter}\' or \'All Resources\' == \'{SeverityFilter}\'\r\n'
size: 0
timeContext: {
durationMs: 2592000000
Expand Down
41 changes: 40 additions & 1 deletion src/bicep/modules/azdo-resources-by-rule.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ var workbook = {
defaultValue: 'value::all'
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: [
'Azure.DevOps.Tasks.VariableGroup.Description'
]
}
{
id: '69ed445b-75d8-41bd-bd99-ed5a99a0cc3a'
Expand All @@ -60,7 +63,7 @@ var workbook = {
}
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: 'daf923fb2463077368e92134a02eda43787659ec'
value: 'psrule-scan-ado/288'
}
{
id: '01f572fc-067d-4429-9be7-9299a08122fd'
Expand Down Expand Up @@ -110,6 +113,9 @@ var workbook = {
defaultValue: 'value::all'
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
value: [
'value::all'
]
}
]
style: 'above'
Expand All @@ -118,6 +124,39 @@ var workbook = {
}
name: 'parameters - 0'
}
{
type: 3
content: {
version: 'KqlItem/1.0'
query: 'PSRule_CL\r\n| where DisplayName_s in ({ruleName}) or \'All Rules\' in ({ruleName})\r\n| extend a=parse_json(Annotations_s), f=parse_json(Field_s)\r\n| extend Severity=a.severity, [\'Rule Help Url\']=a.[\'online version\'],Category=a.category\r\n| extend \r\n expandedId=parse_json(tostring(f.id))\r\n| extend \r\n Organization=expandedId.organization,\r\n [\'Project\']=expandedId.[\'project\'],\r\n ResourceName=expandedId.resourceName\r\n| where (Organization in ({Organization}) or \'All Organizations\' in ({Organization})) and (Project in ({Project}) or \'All Projects\' in ({Project})) \r\n| summarize\r\n [\'Passed Resources\']=countif(Outcome_s == \'Pass\'),\r\n [\'Failed Resources\']=countif(Outcome_s == \'Fail\'),\r\n [\'Percentage Passed\']=round(100 * todecimal(countif(Outcome_s == \'Pass\')) / todecimal(count()), 2),\r\n [\'Audit Date Time\']=max(TimeGenerated)\r\n by RunId_s\r\n| project [\'Audit Date Time\'], [\'Percentage Passed\']'
size: 4
aggregation: 2
timeContext: {
durationMs: 2592000000
}
queryType: 0
resourceType: 'microsoft.operationalinsights/workspaces'
visualization: 'linechart'
chartSettings: {
xAxis: 'Audit Date Time'
yAxis: [
'Percentage Passed'
]
showLegend: true
showDataPoints: true
ySettings: {
numberFormatSettings: {
unit: 1
options: {
style: 'decimal'
useGrouping: true
}
}
}
}
}
name: 'query - 2'
}
{
type: 3
content: {
Expand Down

0 comments on commit 2ba035f

Please sign in to comment.