Skip to content

Commit

Permalink
feat: grouping exceptions with the same messages for glitchtip (#330)
Browse files Browse the repository at this point in the history
* feat: grouping exceptions with the same messages for glitchtip

Signed-off-by: Olga Lavtar <[email protected]>

* feat: grouping exceptions with the same messages for glitchtip

Signed-off-by: Olga Lavtar <[email protected]>

* fix: fixed the progress bar color to match the severity label colors (#331)

Signed-off-by: Olga Lavtar <[email protected]>

* feat: grouping exceptions with the same messages for glitchtip

Signed-off-by: Olga Lavtar <[email protected]>

---------

Signed-off-by: Olga Lavtar <[email protected]>
  • Loading branch information
olavtar authored Apr 16, 2024
1 parent 33192eb commit ad2bf07
Show file tree
Hide file tree
Showing 19 changed files with 253 additions and 24 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

import jakarta.ws.rs.core.Response.Status;

public class ClientDetailedException extends DetailedException {
private Status status;

public ClientDetailedException(String message) {
super(message, null);
}

public ClientDetailedException(String message, String details) {
super(message, details);
}

public ClientDetailedException(Throwable e) {
super(e.getMessage(), null);
}

public ClientDetailedException(String message, Throwable e) {
super(message, e.getMessage());
}

public ClientDetailedException(String message, String details, Status status) {
super(message, details);
this.status = status;
}

public String getStatus() {
return String.valueOf(status.getStatusCode());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

import jakarta.ws.rs.core.Response.Status;

public class CycloneDXValidationException extends ClientDetailedException {
public CycloneDXValidationException(Exception e, Status status) {
super("CycloneDX Validation error", e.getMessage(), status);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

public class DetailedException extends RuntimeException {
private final String details;

public DetailedException(String message, String details) {
super(message);
this.details = details;
}

public String getDetails() {
return details;
}

public String getStatus() {
return "422";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

public class PackageValidationException extends DetailedException {
public PackageValidationException(Exception e) {
super("Package version must not be null", e.getMessage());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

import jakarta.ws.rs.core.Response.Status;

public class SpdxParsingException extends ClientDetailedException {
public SpdxParsingException(Exception e, Status status) {
super(e.getMessage(), e.getMessage(), status);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
* limitations under the License.
*/

package com.redhat.exhort.integration.backend.sbom.spdx;
package com.redhat.exhort.config.exception;

public class SpdxProcessingException extends RuntimeException {
public class SpdxProcessingException extends ClientDetailedException {

public SpdxProcessingException(String msg) {
super(msg);
Expand All @@ -31,4 +31,8 @@ public SpdxProcessingException(Throwable e) {
public SpdxProcessingException(String msg, Throwable e) {
super(msg, e);
}

public SpdxProcessingException(String msg, String details) {
super(msg, details);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* limitations under the License.
*/

package com.redhat.exhort.integration.backend.sbom.spdx;
package com.redhat.exhort.config.exception;

import java.util.List;

Expand All @@ -25,7 +25,7 @@ public class SpdxValidationException extends SpdxProcessingException {
private final List<String> errors;

public SpdxValidationException(String expectedVersion, List<String> errors) {
super(expectedVersion + " Validation error. " + errors.toString());
super(expectedVersion + " Validation error", errors.toString());
this.errors = errors;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.redhat.exhort.config.exception;

public class UnexpectedProviderException extends DetailedException {
public UnexpectedProviderException(Exception e) {
super("Unexpected provider", e.getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import com.redhat.exhort.analytics.AnalyticsService;
import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.api.v4.AnalysisReport;
import com.redhat.exhort.config.exception.DetailedException;
import com.redhat.exhort.integration.Constants;
import com.redhat.exhort.integration.backend.sbom.SbomParser;
import com.redhat.exhort.integration.backend.sbom.SbomParserFactory;
Expand Down Expand Up @@ -113,7 +114,7 @@ public void configure() {
.handled(true)
.setBody().simple("${exception.message}");

onException(ClientErrorException.class)
onException(ClientErrorException.class, DetailedException.class)
.routeId("onExhortClientErrorException")
.useOriginalMessage()
.process(monitoringProcessor::processClientException)
Expand All @@ -127,6 +128,20 @@ public void configure() {
.setHeader(Exchange.CONTENT_ENCODING, constant("gzip"))
.end();

onException(DetailedException.class)
.routeId("onExhortDetailedException")
.useOriginalMessage()
.process(monitoringProcessor::processClientException)
.setHeader(Exchange.HTTP_RESPONSE_CODE, simple("${exception.getStatus()}"))
.setHeader(Exchange.CONTENT_TYPE, constant(MediaType.TEXT_PLAIN))
.setHeader(Constants.EXHORT_REQUEST_ID_HEADER, exchangeProperty(Constants.EXHORT_REQUEST_ID_HEADER))
.handled(true)
.setBody().simple("${exception.message}")
.choice()
.when(exchangeProperty(Constants.GZIP_RESPONSE_PROPERTY).isNotNull()).marshal().gzipDeflater()
.setHeader(Exchange.CONTENT_ENCODING, constant("gzip"))
.end();

rest()
.post("/v3/analysis")
.routeId("v3restAnalysis")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@
import com.networknt.schema.ValidationMessage;
import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.config.ObjectMapperProducer;
import com.redhat.exhort.config.exception.CycloneDXValidationException;
import com.redhat.exhort.integration.backend.sbom.SbomParser;
import com.redhat.exhort.model.DependencyTree;
import com.redhat.exhort.model.DirectDependency;

import jakarta.ws.rs.ClientErrorException;
import jakarta.ws.rs.core.Response;

public class CycloneDxParser extends SbomParser {
Expand Down Expand Up @@ -186,12 +186,10 @@ private Bom parseBom(InputStream input) {
return bom;
} catch (ParseException e) {
LOGGER.debug("CycloneDX Validation error: ", e);
throw new ClientErrorException(
"CycloneDX Validation error: " + e.getMessage(), Response.Status.BAD_REQUEST);
throw new CycloneDXValidationException(e, Response.Status.BAD_REQUEST);
} catch (IOException e) {
LOGGER.error("CycloneDX Validation error: ", e);
throw new ClientErrorException(
"CycloneDX Validation error: " + e.getMessage(), Response.Status.BAD_REQUEST);
throw new CycloneDXValidationException(e, Response.Status.BAD_REQUEST);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,14 @@
import org.spdx.storage.simple.InMemSpdxStore;

import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.config.exception.ClientDetailedException;
import com.redhat.exhort.config.exception.SpdxParsingException;
import com.redhat.exhort.config.exception.SpdxProcessingException;
import com.redhat.exhort.config.exception.SpdxValidationException;
import com.redhat.exhort.integration.backend.sbom.SbomParser;
import com.redhat.exhort.model.DependencyTree;
import com.redhat.exhort.model.DirectDependency;

import jakarta.ws.rs.ClientErrorException;
import jakarta.ws.rs.core.Response;

public class SpdxParser extends SbomParser {
Expand All @@ -58,12 +61,11 @@ protected DependencyTree buildTree(InputStream input) {
return tree;
} catch (SpdxValidationException e) {
LOGGER.info("Invalid SPDX SBOM received", e);
throw new ClientErrorException(e.getMessage(), Response.Status.BAD_REQUEST);
throw new SpdxParsingException(e, Response.Status.BAD_REQUEST);
} catch (SpdxProcessingException | InvalidSPDXAnalysisException | IOException e) {
LOGGER.warn("Unable to parse the SPDX SBOM file", e);
throw new ClientErrorException(
"Unable to parse received SPDX SBOM file: " + e.getMessage(),
Response.Status.BAD_REQUEST);
throw new ClientDetailedException(
"Unable to parse the SPDX SBOM file", e.getMessage(), Response.Status.BAD_REQUEST);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.spdx.library.model.TypedValue;

import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.config.exception.SpdxProcessingException;
import com.redhat.exhort.config.exception.SpdxValidationException;

public class SpdxWrapper {

Expand Down Expand Up @@ -76,8 +78,8 @@ public PackageRef toPackageRef(SpdxPackage spdxPackage) {
.findFirst();
if (ref.isEmpty()) {
throw new SpdxProcessingException(
"Missing Purl External Reference for Package: "
+ spdxPackage.getName().orElse("unknown"));
"Missing Purl External Reference for Package",
"Package name: " + spdxPackage.getName().orElse("unknown"));
}
return new PackageRef(ref.get().getReferenceLocator());
} catch (InvalidSPDXAnalysisException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
import com.redhat.exhort.api.v4.SourceSummary;
import com.redhat.exhort.api.v4.TransitiveDependencyReport;
import com.redhat.exhort.api.v4.UnscannedDependency;
import com.redhat.exhort.config.exception.PackageValidationException;
import com.redhat.exhort.config.exception.UnexpectedProviderException;
import com.redhat.exhort.integration.Constants;
import com.redhat.exhort.model.CvssScoreComparable.DependencyScoreComparator;
import com.redhat.exhort.model.CvssScoreComparable.TransitiveScoreComparator;
Expand Down Expand Up @@ -171,7 +173,9 @@ public void processResponseError(Exchange exchange) {
String message = prettifyHttpError(httpException);
status.message(message).code(httpException.getStatusCode());
LOGGER.warn("Unable to process request: {}", message, cause);
} else if (cause instanceof IllegalArgumentException) {
} else if (cause instanceof IllegalArgumentException
|| cause instanceof UnexpectedProviderException
|| cause instanceof PackageValidationException) {
status.message(cause.getMessage()).code(422);
LOGGER.debug("Unable to process request to: {}", getProviderName(), exception);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.camel.util.URISupport;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import com.redhat.exhort.config.exception.UnexpectedProviderException;
import com.redhat.exhort.integration.Constants;

import io.quarkus.runtime.annotations.RegisterForReflection;
Expand Down Expand Up @@ -79,7 +80,7 @@ public List<String> getProviderEndpoints(
case Constants.SNYK_PROVIDER -> "direct:snykScan";
case Constants.OSS_INDEX_PROVIDER -> "direct:ossIndexScan";
case Constants.OSV_NVD_PROVIDER -> "direct:osvNvdScan";
default -> throw new IllegalArgumentException("Unexpected provider: " + p);
default -> throw new UnexpectedProviderException(new RuntimeException(p));
})
.collect(Collectors.toList());
}
Expand Down
Loading

0 comments on commit ad2bf07

Please sign in to comment.