Skip to content

Commit f9eabcc

Browse files
Merge pull request #42 from leftrightleft/mttr
Add MTTR Metric to GHAS Dashboards
2 parents 10b3b76 + 6a94df0 commit f9eabcc

File tree

3 files changed

+112
-65
lines changed

3 files changed

+112
-65
lines changed

github_app_for_splunk/default/data/ui/views/code_scanning_overview.xml

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<label>Code Scanning Alerts</label>
33
<search id="baseSearch">
44
<query>
5-
`github_webhooks` (eventtype="GitHub::CodeScanning" OR eventtype="GitHub::Push") | eval action='action', tool=if(isnotnull('alert.tool.name'),'alert.tool.name','unknown'), repository=if(isnotnull('repository.name'),'repository.name','unknown'), severity=if(isnotnull('alert.rule.security_severity_level'),'alert.rule.security_severity_level','none'), create_time=if(isnotnull('alert.created_at'),'alert.created_at','unknown'), received_time='_time', alert_url=if(isnotnull('alert.html_url'),'alert.html_url','unknown'), eventtype='eventtype', created=strptime(create_time, "%Y-%m-%dT%H:%M:%S%Z"), duration=received_time - created, duration_str=tostring(avg(duration), "duration")
5+
`github_webhooks` (eventtype="GitHub::CodeScanning" OR eventtype="GitHub::Push") | eval action='action', tool=if(isnotnull('alert.tool.name'),'alert.tool.name','unknown'), repository=if(isnotnull('repository.name'),'repository.name','unknown'), severity=if(isnotnull('alert.rule.security_severity_level'),'alert.rule.security_severity_level','none'), create_time=if(isnotnull('alert.created_at'),'alert.created_at','unknown'), received_time='_time', alert_url=if(isnotnull('alert.html_url'),'alert.html_url','unknown'), eventtype='eventtype', created=strptime(create_time, "%Y-%m-%dT%H:%M:%S%Z"), resolved_at=case('alert.dismissed_at' != "null", 'alert.dismissed_at', isnotnull('alert.fixed_at'), 'alert.fixed_at', isnotnull('alert.resolved_at'),'alert.resolved_at', 1=1, _time), duration = toString(round(strptime(resolved_at, "%Y-%m-%dT%H:%M:%S") - strptime(create_time, "%Y-%m-%dT%H:%M:%S"))), duration_str=tostring(avg(duration), "duration")
66
</query>
77
<earliest>$timeTkn.earliest$</earliest>
88
<latest>$timeTkn.latest$</latest>
@@ -46,62 +46,78 @@
4646
</fieldset>
4747
<row>
4848
<panel>
49+
<title>Mean Time to Resolution (MTTR)</title>
50+
<single>
51+
<search base="baseSearch">
52+
<query>| search eventtype="GitHub::CodeScanning" (action=fixed OR action=closed_by_user) tool=$tool_name$ repository=$repoTkn$
53+
| eval action=action, , repository=if(isnotnull('repository.name'),'repository.name','unknown')
54+
| eval age = avg(duration)
55+
| appendpipe [ stats avg(age) as totalTime ]
56+
| eval mttr = toString(round(totalTime), "duration"), clean_mttr = replace (mttr , "\+" , " days, ")
57+
| stats max(clean_mttr)
58+
59+
</query>
60+
</search>
61+
<option name="drilldown">none</option>
62+
</single>
63+
</panel>
64+
<panel>
65+
<title>Created</title>
4966
<single>
50-
<title>Created</title>
5167
<search base="baseSearch">
5268
<query>| search tool=$tool_name$ repository=$repoTkn$ action="created" | stats count</query>
5369
</search>
5470
<option name="drilldown">none</option>
55-
<option name="height">50</option>
71+
<option name="height">100</option>
5672
<option name="rangeColors">["0x53a051","0x0877a6","0xf8be34","0xf1813f","0xdc4e41"]</option>
5773
<option name="refresh.display">progressbar</option>
5874
</single>
5975
</panel>
6076
<panel>
77+
<title>Fixed</title>
6178
<single>
62-
<title>Fixed</title>
6379
<search base="baseSearch">
6480
<query>| search tool=$tool_name$ repository=$repoTkn$ action="fixed" | stats count</query>
6581
</search>
6682
<option name="drilldown">none</option>
67-
<option name="height">50</option>
83+
<option name="height">100</option>
6884
<option name="refresh.display">progressbar</option>
6985
</single>
7086
</panel>
7187
<panel>
88+
<title>Reopened</title>
7289
<single>
73-
<title>Reopened</title>
7490
<search base="baseSearch">
7591
<query>| search tool=$tool_name$ repository=$repoTkn$ action="reopened" | stats count</query>
7692
</search>
7793
<option name="drilldown">none</option>
78-
<option name="height">50</option>
94+
<option name="height">100</option>
7995
<option name="refresh.display">progressbar</option>
8096
</single>
8197
</panel>
8298
</row>
8399
<row>
84100
<panel>
101+
<title>Alert Found/Fixed Ratio</title>
85102
<chart>
86-
<title>Alert Found/Fixed Ratio</title>
87103
<search base="baseSearch">
88104
<query>| search tool=$tool_name$ repository=$repoTkn$ (action=created OR action=fixed)
89-
| timechart count(_raw) by action
105+
| timechart count(_raw) by action
90106
| accum created
91-
| accum fixed
92-
| rename created as "Found"
107+
| accum fixed
108+
| rename created as "Found"
93109
| rename fixed as "Fixed"</query>
94110
</search>
95111
<option name="charting.axisTitleX.visibility">collapsed</option>
96112
<option name="charting.chart">line</option>
97113
<option name="charting.drilldown">none</option>
98-
<option name="refresh.display">progressbar</option>
99114
<option name="height">150</option>
115+
<option name="refresh.display">progressbar</option>
100116
</chart>
101117
</panel>
102118
<panel>
119+
<title>Commit/Alert Ratio</title>
103120
<chart>
104-
<title>Commit/Alert Ratio</title>
105121
<search base="baseSearch">
106122
<query>| search (eventtype="GitHub::Push" repository=$repoTkn$) OR ((action=created OR action=reopened) tool=$tool_name$ repository=$repoTkn$ )
107123
| timechart count(_raw) by eventtype
@@ -122,8 +138,8 @@
122138
</chart>
123139
</panel>
124140
<panel>
141+
<title>New Alerts by Tool</title>
125142
<chart>
126-
<title>New Alerts by Tool</title>
127143
<search base="baseSearch">
128144
<query>| search tool=$tool_name$ repository=$repoTkn$ (action=created OR action=appeared_in_branch) | timechart count(_raw) by tool</query>
129145
</search>
@@ -141,8 +157,9 @@
141157
<title>Fixed Alerts</title>
142158
<search base="baseSearch">
143159
<query> | search (action=fixed OR action=closed_by_user) repository=$repoTkn$ tool=$tool_name$
144-
| table repository, tool, alert_url,duration_str
145-
| rename repository AS "Repository" duration_str AS "Time to Resolution",tool AS "Tool", alert_url AS "Alert URL"
160+
|eval clean_duration = replace (duration_str , "\+" , " days, ")
161+
| table repository, tool, alert_url,clean_duration
162+
| rename repository AS "Repository" clean_duration AS "Time to Resolution",tool AS "Tool", alert_url AS "Alert URL"
146163
| sort -"Time to Resolution"
147164
</query>
148165
</search>
@@ -157,11 +174,8 @@
157174
<search base="baseSearch">
158175
<query>| search (action=created OR action=reopened) repository=$repoTkn$ tool=$tool_name$ | chart usenull=f count over repository by severity</query>
159176
</search>
177+
<option name="dataOverlayMode">heatmap</option>
160178
<option name="drilldown">none</option>
161-
<format type="color" field="critical">
162-
<colorPalette type="minMidMax" maxColor="#DC4E41" minColor="#FFFFFF"></colorPalette>
163-
<scale type="minMidMax"></scale>
164-
</format>
165179
<format type="color" field="high">
166180
<colorPalette type="minMidMax" maxColor="#F8BE34" minColor="#FFFFFF"></colorPalette>
167181
<scale type="minMidMax"></scale>

github_app_for_splunk/default/data/ui/views/dependabot_alerts.xml

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
<form version="1.1">
1+
<form version="1.1" theme="dark">
22
<label>Dependabot Alerts</label>
33
<search id="baseSearch">
44
<query>
5-
`github_webhooks` (eventtype="GitHub::VulnerabilityAlert" OR eventtype="GitHub::Push") | eval action='action', repository=if(isnotnull('repository.name'),'repository.name','unknown'), severity=if(isnotnull('alert.severity'),'alert.severity','none'), create_time=if(isnotnull('alert.created_at'),'alert.created_at','unknown'), received_time='_time', alert_url=if(isnotnull('alert.external_reference'),'alert.external_reference','unknown'), eventtype='eventtype', created=strptime(create_time, "%Y-%m-%dT%H:%M:%S%Z"), duration=received_time - created, duration_str=tostring(avg(duration), "duration")
5+
`github_webhooks` eventtype="GitHub::VulnerabilityAlert" | eval action='action', repository=if(isnotnull('repository.name'),'repository.name','unknown'), severity=if(isnotnull('alert.severity'),'alert.severity','none'), create_time=if(isnotnull('alert.created_at'),'alert.created_at','unknown'), received_time='_time', alert_url=if(isnotnull('alert.external_reference'),'alert.external_reference','unknown'), eventtype='eventtype', created=strptime(create_time, "%Y-%m-%dT%H:%M:%S%Z"), resolved_at=case('alert.dismissed_at' != "null", 'alert.dismissed_at', isnotnull('alert.fixed_at'), 'alert.fixed_at', isnotnull('alert.resolved_at'),'alert.resolved_at', 1=1, _time), duration = toString(round(strptime(resolved_at, "%Y-%m-%dT%H:%M:%S") - strptime(create_time, "%Y-%m-%dT%H:%M:%S"))), duration_str=tostring(avg(duration), "duration")
66
</query>
77
<earliest>$timeTkn.earliest$</earliest>
88
<latest>$timeTkn.latest$</latest>
@@ -17,7 +17,7 @@
1717
</default>
1818
</input>
1919
<input type="multiselect" token="repoTkn" searchWhenChanged="true">
20-
<label>Repositories</label>
20+
<label>Repositories</label>
2121
<choice value="*">All</choice>
2222
<default>*</default>
2323
<initialValue>*</initialValue>
@@ -45,14 +45,31 @@
4545
</input>
4646
</fieldset>
4747
<row>
48+
<panel>
49+
<single>
50+
<title>Mean Time to Resolution (MTTR)</title>
51+
<search base="baseSearch">
52+
<query>| search severity=$severity_label$ repository=$repoTkn$ action="resolve"
53+
| eval age = avg(duration)
54+
| appendpipe [ stats avg(age) as totalTime ]
55+
| eval mttr = toString(round(totalTime), "duration"), clean_mttr = replace (mttr , "\+" , " days, ")
56+
| stats max(clean_mttr)
57+
</query>
58+
</search>
59+
<option name="drilldown">none</option>
60+
<option name="height">100</option>
61+
<option name="rangeColors">["0x53a051","0x0877a6","0xf8be34","0xf1813f","0xdc4e41"]</option>
62+
<option name="refresh.display">progressbar</option>
63+
</single>
64+
</panel>
4865
<panel>
4966
<single>
5067
<title>Created</title>
5168
<search base="baseSearch">
5269
<query>| search severity=$severity_label$ repository=$repoTkn$ action="create" | stats count</query>
5370
</search>
5471
<option name="drilldown">none</option>
55-
<option name="height">50</option>
72+
<option name="height">100</option>
5673
<option name="rangeColors">["0x53a051","0x0877a6","0xf8be34","0xf1813f","0xdc4e41"]</option>
5774
<option name="refresh.display">progressbar</option>
5875
</single>
@@ -64,7 +81,7 @@
6481
<query>| search severity=$severity_label$ repository=$repoTkn$ (action="resolve") | stats count</query>
6582
</search>
6683
<option name="drilldown">none</option>
67-
<option name="height">50</option>
84+
<option name="height">100</option>
6885
<option name="refresh.display">progressbar</option>
6986
</single>
7087
</panel>
@@ -75,7 +92,7 @@
7592
<query>| search severity=$severity_label$ repository=$repoTkn$ (action="dismiss") | stats count</query>
7693
</search>
7794
<option name="drilldown">none</option>
78-
<option name="height">50</option>
95+
<option name="height">100</option>
7996
<option name="refresh.display">progressbar</option>
8097
</single>
8198
</panel>
@@ -97,29 +114,20 @@
97114
<option name="charting.chart">line</option>
98115
<option name="charting.drilldown">none</option>
99116
<option name="refresh.display">progressbar</option>
100-
<option name="height">150</option>
117+
<option name="height">200</option>
101118
</chart>
102119
</panel>
103120
<panel>
104121
<chart>
105-
<title>Commit/Alert Ratio</title>
122+
<title>Vulnerabilities by Repo</title>
106123
<search base="baseSearch">
107-
<query>| search (eventtype="GitHub::Push" repository=$repoTkn$) OR ((action=create) severity=$severity_label$ repository=$repoTkn$ )
108-
| timechart count(_raw) by eventtype
109-
| accum "GitHub::Push"
110-
| accum "GitHub::VulnerabilityAlert"
111-
| rename GitHub::Push as "Pushes"
112-
| rename GitHub::VulnerabilityAlert as "Dependabot Alerts"
113-
| fields - err0r</query>
124+
<query>| search severity=$severity_label$ repository=$repoTkn$ action=create | chart count by repository
125+
</query>
114126
</search>
115-
<option name="charting.axisTitleX.visibility">collapsed</option>
116-
<option name="charting.axisY.scale">log</option>
117-
<option name="charting.axisY2.enabled">1</option>
118-
<option name="charting.chart">line</option>
119-
<option name="charting.chart.overlayFields">DC_cumulative</option>
127+
<option name="charting.chart">pie</option>
120128
<option name="charting.drilldown">none</option>
121129
<option name="charting.legend.mode">standard</option>
122-
<option name="height">150</option>
130+
<option name="height">200</option>
123131
<option name="refresh.display">progressbar</option>
124132
</chart>
125133
</panel>
@@ -132,7 +140,7 @@
132140
<option name="charting.chart">column</option>
133141
<option name="charting.chart.stackMode">stacked</option>
134142
<option name="charting.drilldown">none</option>
135-
<option name="height">150</option>
143+
<option name="height">200</option>
136144
<option name="refresh.display">progressbar</option>
137145
</chart>
138146
</panel>
@@ -170,4 +178,4 @@
170178
</table>
171179
</panel>
172180
</row>
173-
</form>
181+
</form>

0 commit comments

Comments
 (0)