Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GUI] New "Checker Coverage" statistics tab to show all enabled checkers and … #4210

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/js/codechecker-api-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codechecker-api",
"version": "6.55.0",
"version": "6.56.0",
"description": "Generated node.js compatible API stubs for CodeChecker server.",
"main": "lib",
"homepage": "https://github.com/Ericsson/codechecker",
Expand Down
Binary file modified web/api/py/codechecker_api/dist/codechecker_api.tar.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.55.0'
api_version = '6.56.0'

setup(
name='codechecker_api',
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion web/api/py/codechecker_api_shared/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
with open('README.md', encoding='utf-8', errors="ignore") as f:
long_description = f.read()

api_version = '6.55.0'
api_version = '6.56.0'

setup(
name='codechecker_api_shared',
Expand Down
19 changes: 19 additions & 0 deletions web/api/report_server.thrift
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,17 @@ struct CheckerCount {
}
typedef list<CheckerCount> CheckerCounts

struct CheckerInfo {
1: string checkerName, // Analyzer name of the checker.
whisperity marked this conversation as resolved.
Show resolved Hide resolved
2: string analyzerName, // Analyzer name of the checker.
3: Severity severity, // Severity level of the checker.
4: list<i64> enabled, // Runs' names in which the checker enabled.
5: list<i64> disabled, // Runs' names in which the checker disabled.
whisperity marked this conversation as resolved.
Show resolved Hide resolved
6: i64 closed // Number of closed reports.
7: i64 outstanding // Number of outstanding reports.
}
typedef map<i64, CheckerInfo> CheckerInfos
whisperity marked this conversation as resolved.
Show resolved Hide resolved

struct CommentData {
1: i64 id,
2: string author,
Expand Down Expand Up @@ -852,6 +863,14 @@ service codeCheckerDBAccess {
5: i64 offset)
throws (1: codechecker_api_shared.RequestFailed requestError),

// It gives statistics for specific runs which checkers were
// enabled and how many reports are opened or closed.
// If the run id list is empty the statistics
// will be counted for all of the runs.
CheckerInfos getCheckerInfo(1: list<i64> runIds,
whisperity marked this conversation as resolved.
Show resolved Hide resolved
whisperity marked this conversation as resolved.
Show resolved Hide resolved
2: ReportFilter reportFilter)
throws (1: codechecker_api_shared.RequestFailed requestError),

// If the run id list is empty the metrics will be counted
// for all of the runs and in compare mode all of the runs
// will be used as a baseline excluding the runs in compare data.
Expand Down
2 changes: 1 addition & 1 deletion web/codechecker_web/shared/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# The newest supported minor version (value) for each supported major version
# (key) in this particular build.
SUPPORTED_VERSIONS = {
6: 55
6: 56
}

# Used by the client to automatically identify the latest major and minor
Expand Down
187 changes: 185 additions & 2 deletions web/server/codechecker_server/api/report_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import sqlalchemy
from sqlalchemy.sql.expression import or_, and_, not_, func, \
asc, desc, union_all, select, bindparam, literal_column
asc, desc, union_all, select, bindparam, literal_column, case, cast
from sqlalchemy.orm import contains_eager

import codechecker_api_shared
Expand All @@ -42,7 +42,8 @@
ReviewStatusRuleFilter, ReviewStatusRuleSortMode, \
ReviewStatusRuleSortType, RunData, RunFilter, RunHistoryData, \
RunReportCount, RunSortType, RunTagCount, \
SourceComponentData, SourceFileData, SortMode, SortType
SourceComponentData, SourceFileData, SortMode, SortType, \
ReviewStatus as API_ReviewStatus, DetectionStatus, CheckerInfo
whisperity marked this conversation as resolved.
Show resolved Hide resolved

from codechecker_common import util
from codechecker_common.logger import get_logger
Expand All @@ -58,6 +59,7 @@
from ..database.database import conv, DBSession, escape_like
from ..database.run_db_model import \
AnalysisInfo, AnalysisInfoChecker as DB_AnalysisInfoChecker, \
AnalysisInfoChecker, \
whisperity marked this conversation as resolved.
Show resolved Hide resolved
AnalyzerStatistic, \
BugPathEvent, BugReportPoint, \
CleanupPlan, CleanupPlanReportHash, Checker, Comment, \
Expand Down Expand Up @@ -2861,6 +2863,187 @@ def getCheckerCounts(self, run_ids, report_filter, cmp_data, limit,
results.append(checker_count)
return results

@exc_to_thrift_reqfail
@timeit
def getCheckerInfo(self, run_ids, report_filter):
self.__require_view()
with DBSession(self._Session) as session:
max_run_histories = session.query(
RunHistory.run_id,
func.max(RunHistory.id).label('max_run_history_id'),
) \
.filter(RunHistory.run_id.in_(run_ids) if run_ids else True) \
.group_by(RunHistory.run_id)

subquery = (
session.query(
(func.string_agg(
cast(Run.id, sqlalchemy.String).distinct(),
','
).label("run_id")
if session.bind.dialect.name == "postgresql"
else func.group_concat(Run.id.distinct()).label("run_id"))
if report_filter.isUnique
else Run.id.label("run_id"),
Checker.id.label("checker_id"),
whisperity marked this conversation as resolved.
Show resolved Hide resolved
Checker.checker_name,
Checker.analyzer_name,
Checker.severity,
Report.bug_id,
Report.detection_status,
Report.review_status,
)
.join(RunHistory)
.join(AnalysisInfo, RunHistory.analysis_info)
whisperity marked this conversation as resolved.
Show resolved Hide resolved
.join(AnalysisInfoChecker, (
(AnalysisInfo.id == AnalysisInfoChecker.analysis_info_id)
& (AnalysisInfoChecker.enabled.is_(True))))
.join(Checker, AnalysisInfoChecker.checker_id == Checker.id)
.outerjoin(Report, ((Checker.id == Report.checker_id)
& (Run.id == Report.run_id)))
.filter(RunHistory.id == max_run_histories.subquery()
.c.max_run_history_id)
)

if report_filter.isUnique:
subquery = subquery.group_by(
Checker.id,
Checker.checker_name,
Checker.analyzer_name,
Checker.severity,
Report.bug_id,
Report.detection_status,
Report.review_status
)

subquery = subquery.subquery()

query = (
session.query(
subquery.c.checker_id,
subquery.c.checker_name,
subquery.c.analyzer_name,
subquery.c.severity,
subquery.c.run_id,
case(
[
(
subquery.c.detection_status.in_(list(map(
detection_status_str,
(DetectionStatus.OFF,
DetectionStatus.UNAVAILABLE)
))),
False
)
],
else_=True
).label("isEnabled"),
whisperity marked this conversation as resolved.
Show resolved Hide resolved
case(
[
(
and_(
subquery.c.detection_status.in_(list(map(
detection_status_str,
(DetectionStatus.NEW,
DetectionStatus.UNRESOLVED,
DetectionStatus.REOPENED)
))),
subquery.c.review_status.in_(list(map(
review_status_str,
(API_ReviewStatus.UNREVIEWED,
API_ReviewStatus.CONFIRMED))))
),
True
)
],
else_=False
).label("isOpened"),
whisperity marked this conversation as resolved.
Show resolved Hide resolved
func.count(subquery.c.bug_id)
)
.group_by(
subquery.c.checker_id,
subquery.c.checker_name,
subquery.c.analyzer_name,
subquery.c.severity,
subquery.c.run_id,
case(
[
(
subquery.c.detection_status.in_(list(map(
detection_status_str,
(DetectionStatus.OFF,
DetectionStatus.UNAVAILABLE)
))),
False
)
],
else_=True
),
whisperity marked this conversation as resolved.
Show resolved Hide resolved
case(
[
(
and_(
subquery.c.detection_status.in_(list(map(
detection_status_str,
(DetectionStatus.NEW,
DetectionStatus.UNRESOLVED,
DetectionStatus.REOPENED)
))),
subquery.c.review_status.in_(list(map(
review_status_str,
(API_ReviewStatus.UNREVIEWED,
API_ReviewStatus.CONFIRMED))))
),
True
)
],
else_=False
)
)
)

checker_stats = {}
all_run_id = [runId for runId, _ in max_run_histories.all()]
for checker_id, \
checker_name, \
analyzer_name, \
severity, \
run_ids, \
is_enabled, \
is_opened, \
cnt \
in query.all():
checker_stat = checker_stats[checker_id] \
if checker_id in checker_stats \
else CheckerInfo(
checkerName=checker_name,
analyzerName=analyzer_name,
enabled=[],
disabled=all_run_id,
severity=severity,
closed=0,
outstanding=0
)
whisperity marked this conversation as resolved.
Show resolved Hide resolved

if is_enabled:
for r in (run_ids.split(",")
if type(run_ids) is str
whisperity marked this conversation as resolved.
Show resolved Hide resolved
else [run_ids]):
run_id = int(r)
if run_id not in checker_stat.enabled:
checker_stat.enabled.append(run_id)
if run_id in checker_stat.disabled:
checker_stat.disabled.remove(run_id)
whisperity marked this conversation as resolved.
Show resolved Hide resolved

if is_enabled and is_opened:
checker_stat.outstanding += cnt
else:
checker_stat.closed += cnt

checker_stats[checker_id] = checker_stat

return checker_stats

@exc_to_thrift_reqfail
@timeit
def getAnalyzerNameCounts(self, run_ids, report_filter, cmp_data, limit,
Expand Down
12 changes: 6 additions & 6 deletions web/server/vue-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion web/server/vue-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@mdi/font": "^6.5.95",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.55.0.tgz",
"codechecker-api": "file:../../api/js/codechecker-api-node/dist/codechecker-api-6.56.0.tgz",
"chart.js": "^2.9.4",
"chartjs-plugin-datalabels": "^0.7.0",
"codemirror": "^5.65.0",
Expand Down
5 changes: 4 additions & 1 deletion web/server/vue-cli/src/components/AnalysisInfoDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ import {
default as AnalysisInfoHandlingAPIMixin,
CheckerInfoAvailability,
CountKeys,
GroupKeys
GroupKeys,
decideNegativeCheckerStatusAvailability
} from "@/mixins/api/analysis-info-handling.mixin";

export default {
Expand Down Expand Up @@ -272,6 +273,8 @@ export default {

var analysisInfo = await this.loadAnalysisInfo(
this.runId, this.runHistoryId, this.reportId);
decideNegativeCheckerStatusAvailability(
analysisInfo, this.runId, this.runHistoryId, this.reportId);
whisperity marked this conversation as resolved.
Show resolved Hide resolved
this.highlightedCmds = analysisInfo.cmds.map(cmd =>
this.highlightOptions(cmd));
analysisInfo.groupAndCountCheckers();
Expand Down
2 changes: 2 additions & 0 deletions web/server/vue-cli/src/components/CountChips.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
outlined
dark
small
@click="$emit('showing-good-click')"
>
<v-icon
start
Expand All @@ -40,6 +41,7 @@
outlined
dark
small
@click="$emit('showing-bad-click')"
>
<v-icon
start
Expand Down
Loading
Loading