All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.client.jdbc.SnowflakeSQLLoggedException Maven / Gradle / Ivy

There is a newer version: 3.20.0
Show newest version
/*
 * Copyright (c) 2012-2020 Snowflake Computing Inc. All rights reserved.
 */

package net.snowflake.client.jdbc;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.api.client.util.Strings;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import net.minidev.json.JSONObject;
import net.snowflake.client.core.ObjectMapperFactory;
import net.snowflake.client.core.SFException;
import net.snowflake.client.core.SFSession;
import net.snowflake.client.jdbc.telemetry.Telemetry;
import net.snowflake.client.jdbc.telemetry.TelemetryField;
import net.snowflake.client.jdbc.telemetry.TelemetryUtil;
import net.snowflake.client.jdbc.telemetryOOB.TelemetryEvent;
import net.snowflake.client.jdbc.telemetryOOB.TelemetryService;

/**
 * @author mknister
 *     

This SnowflakeSQLLoggedException class extends the SnowflakeSQLException class to add OOB * telemetry data for sql exceptions. Not all sql exceptions require OOB telemetry logging so * the exceptions in this class should only be thrown if there is a need for logging the * exception with OOB telemetry. */ public class SnowflakeSQLLoggedException extends SnowflakeSQLException { /* OOB telemetry instance */ private TelemetryService oobInstance = TelemetryService.getInstance(); /* IB telemtry instance */ private Telemetry ibInstance = null; private static final ObjectMapper mapper = ObjectMapperFactory.getObjectMapper(); /** * Function to create a TelemetryEvent log from the JSONObject and exception and send it via OOB * telemetry * * @param value JSONnode containing relevant information specific to the exception constructor * that should be included in the telemetry data, such as sqlState or vendorCode * @param ex The exception being thrown */ private void sendOutOfBandTelemetryMessage(JSONObject value, SnowflakeSQLLoggedException ex) { TelemetryEvent.LogBuilder logBuilder = new TelemetryEvent.LogBuilder(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); String stackTrace = sw.toString(); value.put("Stacktrace", stackTrace); TelemetryEvent log = logBuilder.withName("Exception: " + ex.getClass().getSimpleName()).withValue(value).build(); oobInstance.report(log); } /** * Function to create a TelemetryClient log and send it via in-band telemetry * * @param value ObjectNode containing information specific to the exception constructor that * should be included in the telemetry log, such as SQLState or reason for the error * @param ex The exception being thrown * @return true if in-band telemetry log sent successfully or false if it did not */ private Future sendInBandTelemetryMessage( ObjectNode value, SnowflakeSQLLoggedException ex) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); ex.printStackTrace(pw); String stackTrace = sw.toString(); value.put("Stacktrace", stackTrace); value.put("Exception", ex.getClass().getSimpleName()); ibInstance.addLogToBatch(TelemetryUtil.buildJobData(value)); return ibInstance.sendBatchAsync(); } /** * Helper function to create JSONObject node for OOB telemetry log * * @param queryId * @param reason * @param SQLState * @param vendorCode * @param errorCode * @return JSONObject with data about SQLException */ private JSONObject createOOBValue( String queryId, String reason, String SQLState, int vendorCode, ErrorCode errorCode) { JSONObject oobValue = new JSONObject(); if (!Strings.isNullOrEmpty(queryId)) { oobValue.put("Query ID", queryId); } if (!Strings.isNullOrEmpty(SQLState)) { oobValue.put("SQLState", SQLState); } if (vendorCode != -1) { oobValue.put("Vendor Code", vendorCode); } if (errorCode != null) { oobValue.put("Error Code", errorCode.toString()); } if (!Strings.isNullOrEmpty(reason)) { oobValue.put("reason", reason); } return oobValue; } /** * Function to construct log data based on possible exception inputs and send data through in-band * telemetry, or oob if in-band does not work * * @param queryId query ID if exists * @param reason reason for the exception * @param SQLState SQLState * @param vendorCode vendor code * @param errorCode error code * @param session session object, which is needed to send in-band telemetry but not oob. Might be * null, in which case oob is used. */ public void sendTelemetryData( String queryId, String reason, String SQLState, int vendorCode, ErrorCode errorCode, SFSession session) { // if session is not null, try sending data using in-band telemetry if (session != null) { ibInstance = session.getTelemetryClient(); } // if in-band instance is successfully created, compile sql exception data into an in-band // telemetry log if (ibInstance != null) { ObjectNode ibValue = mapper.createObjectNode(); ibValue.put("type", TelemetryField.SQL_EXCEPTION.toString()); if (!Strings.isNullOrEmpty(queryId)) { ibValue.put("Query ID", queryId); } if (!Strings.isNullOrEmpty(SQLState)) { ibValue.put("SQLState", SQLState); } if (vendorCode != -1) { ibValue.put("Vendor Code", vendorCode); } if (errorCode != null) { ibValue.put("Error Code", errorCode.toString()); } if (!Strings.isNullOrEmpty(reason)) { ibValue.put("reason", reason); } // try to send in-band data asynchronously ExecutorService threadExecutor = Executors.newSingleThreadExecutor(); threadExecutor.submit( () -> { boolean inBandSuccess; Future sendInBand = sendInBandTelemetryMessage(ibValue, this); // record whether in band telemetry message sent with boolean value inBandSuccess try { inBandSuccess = sendInBand.get(10, TimeUnit.SECONDS); } catch (Exception e) { inBandSuccess = false; } // In-band failed so send OOB telemetry instead if (!inBandSuccess) { logger.debug( "In-band telemetry message failed to send. Sending out-of-band message instead"); JSONObject oobValue = createOOBValue(queryId, reason, SQLState, vendorCode, errorCode); sendOutOfBandTelemetryMessage(oobValue, this); } }); } // In-band is not possible so send OOB telemetry instead else { JSONObject oobValue = createOOBValue(queryId, reason, SQLState, vendorCode, errorCode); sendOutOfBandTelemetryMessage(oobValue, this); } } public SnowflakeSQLLoggedException( SFSession session, String reason, String SQLState, int vendorCode, String queryId) { super(queryId, reason, SQLState, vendorCode); sendTelemetryData(queryId, reason, SQLState, vendorCode, null, session); } public SnowflakeSQLLoggedException(SFSession session, int vendorCode, String SQLState) { super(SQLState, vendorCode); sendTelemetryData(null, null, SQLState, vendorCode, null, session); } public SnowflakeSQLLoggedException(SFSession session, String SQLState, String reason) { super(reason, SQLState); sendTelemetryData(null, reason, SQLState, -1, null, session); } public SnowflakeSQLLoggedException( SFSession session, int vendorCode, String SQLState, Object... params) { super(SQLState, vendorCode, params); String reason = errorResourceBundleManager.getLocalizedMessage(String.valueOf(vendorCode), params); sendTelemetryData(null, reason, SQLState, vendorCode, null, session); } public SnowflakeSQLLoggedException( SFSession session, ErrorCode errorCode, Throwable ex, Object... params) { super(ex, errorCode, params); // add telemetry String reason = errorResourceBundleManager.getLocalizedMessage( String.valueOf(errorCode.getMessageCode()), params); sendTelemetryData( null, reason, errorCode.getSqlState(), errorCode.getMessageCode(), errorCode, session); } public SnowflakeSQLLoggedException( SFSession session, String SQLState, int vendorCode, Throwable ex, Object... params) { super(ex, SQLState, vendorCode, params); // add telemetry String reason = errorResourceBundleManager.getLocalizedMessage(String.valueOf(vendorCode), params); sendTelemetryData(null, reason, SQLState, vendorCode, null, session); } public SnowflakeSQLLoggedException(SFSession session, ErrorCode errorCode, Object... params) { super(errorCode, params); // add telemetry String reason = errorResourceBundleManager.getLocalizedMessage( String.valueOf(errorCode.getMessageCode()), params); sendTelemetryData(null, reason, null, -1, errorCode, session); } public SnowflakeSQLLoggedException(SFSession session, SFException e) { super(e); // add telemetry sendTelemetryData(null, null, null, -1, null, session); } public SnowflakeSQLLoggedException(SFSession session, String reason) { super(reason); sendTelemetryData(null, reason, null, -1, null, session); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy