Throw exception on connection failure to be captured by frontend (#2190)

This commit is contained in:
Cheena Malhotra
2023-08-23 18:28:47 -07:00
committed by GitHub
parent 2502e23f43
commit 4e5a7ebe97
7 changed files with 182 additions and 177 deletions

View File

@@ -158,29 +158,12 @@ namespace Microsoft.SqlTools.Hosting.Protocol
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error($"{requestType.MethodName} : {GetErrorMessage(ex, true)}"); Logger.Error($"{requestType.MethodName} : {ex.GetFullErrorMessage(true)}");
await requestContext.SendError(GetErrorMessage(ex)); await requestContext.SendError(ex.GetFullErrorMessage());
} }
}); });
} }
private string GetErrorMessage(Exception e, bool includeStackTrace = false)
{
List<string> errors = new List<string>();
while (e != null)
{
errors.Add(e.Message);
if (includeStackTrace)
{
errors.Add(e.StackTrace);
}
e = e.InnerException;
}
return errors.Count > 0 ? string.Join(includeStackTrace ? Environment.NewLine : " ---> ", errors) : string.Empty;
}
public void SetEventHandler<TParams>( public void SetEventHandler<TParams>(
EventType<TParams> eventType, EventType<TParams> eventType,
Func<TParams, EventContext, Task> eventHandler) Func<TParams, EventContext, Task> eventHandler)

View File

@@ -4,6 +4,7 @@
// //
using System; using System;
using System.Collections.Generic;
namespace Microsoft.SqlTools.Utility namespace Microsoft.SqlTools.Utility
{ {
@@ -77,5 +78,22 @@ namespace Microsoft.SqlTools.Utility
return false; return false;
} }
public static string GetFullErrorMessage(this Exception e, bool includeStackTrace = false)
{
List<string> errors = new List<string>();
while (e != null)
{
errors.Add(e.Message);
if (includeStackTrace)
{
errors.Add(e.StackTrace);
}
e = e.InnerException;
}
return errors.Count > 0 ? string.Join(includeStackTrace ? Environment.NewLine : " ---> ", errors) : string.Empty;
}
} }
} }

View File

@@ -20,6 +20,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection;
using Microsoft.SqlTools.ServiceLayer.Hosting; using Microsoft.SqlTools.ServiceLayer.Hosting;
using Microsoft.SqlTools.ServiceLayer.Management; using Microsoft.SqlTools.ServiceLayer.Management;
using Microsoft.SqlTools.ServiceLayer.Utility; using Microsoft.SqlTools.ServiceLayer.Utility;
using Microsoft.SqlTools.Utility;
namespace Microsoft.SqlTools.ServiceLayer.Agent namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
@@ -153,25 +154,40 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
parameters.OwnerUri, parameters.OwnerUri,
out connInfo); out connInfo);
if (connInfo != null) try
{ {
var serverConnection = ConnectionService.OpenServerConnection(connInfo); if (connInfo != null)
var fetcher = new JobFetcher(serverConnection);
var filter = new JobActivityFilter();
var jobs = fetcher.FetchJobs(filter);
var agentJobs = new List<AgentJobInfo>();
if (jobs != null)
{ {
foreach (var job in jobs.Values) var serverConnection = ConnectionService.OpenServerConnection(connInfo);
var fetcher = new JobFetcher(serverConnection);
var filter = new JobActivityFilter();
var jobs = fetcher.FetchJobs(filter);
var agentJobs = new List<AgentJobInfo>();
if (jobs != null)
{ {
agentJobs.Add(AgentUtilities.ConvertToAgentJobInfo(job)); foreach (var job in jobs.Values)
{
agentJobs.Add(AgentUtilities.ConvertToAgentJobInfo(job));
}
} }
result.Success = true;
result.Jobs = agentJobs.ToArray();
serverConnection.SqlConnectionObject.Close();
} }
result.Success = true; await requestContext.SendResult(result);
result.Jobs = agentJobs.ToArray(); }
serverConnection.SqlConnectionObject.Close(); catch (Exception ex)
{
result.Success = false;
result.ErrorMessage = ex.Message;
Exception exception = ex.InnerException;
while (exception != null)
{
result.ErrorMessage += Environment.NewLine + "\t" + exception.Message;
exception = exception.InnerException;
}
await requestContext.SendResult(result);
} }
await requestContext.SendResult(result);
} }
/// <summary> /// <summary>
@@ -180,69 +196,84 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
internal async Task HandleJobHistoryRequest(AgentJobHistoryParams parameters, RequestContext<AgentJobHistoryResult> requestContext) internal async Task HandleJobHistoryRequest(AgentJobHistoryParams parameters, RequestContext<AgentJobHistoryResult> requestContext)
{ {
var result = new AgentJobHistoryResult(); var result = new AgentJobHistoryResult();
ConnectionInfo connInfo; try
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo != null)
{ {
CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true); ConnectionInfo connInfo;
var jobServer = dataContainer.Server.JobServer; ConnectionServiceInstance.TryFindConnection(
var jobs = jobServer.Jobs; parameters.OwnerUri,
Tuple<SqlConnectionInfo, DataTable, ServerConnection> tuple = CreateSqlConnection(connInfo, parameters.JobId); out connInfo);
SqlConnectionInfo sqlConnInfo = tuple.Item1; if (connInfo != null)
DataTable dt = tuple.Item2;
ServerConnection connection = tuple.Item3;
// Send Steps, Alerts and Schedules with job history in background
// Add steps to the job if any
JobStepCollection steps = jobs[parameters.JobName].JobSteps;
var jobSteps = new List<AgentJobStepInfo>();
foreach (JobStep step in steps)
{ {
jobSteps.Add(AgentUtilities.ConvertToAgentJobStepInfo(step, parameters.JobId, parameters.JobName)); CDataContainer dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
} var jobServer = dataContainer.Server.JobServer;
result.Steps = jobSteps.ToArray(); var jobs = jobServer.Jobs;
Tuple<SqlConnectionInfo, DataTable, ServerConnection> tuple = CreateSqlConnection(connInfo, parameters.JobId);
SqlConnectionInfo sqlConnInfo = tuple.Item1;
DataTable dt = tuple.Item2;
ServerConnection connection = tuple.Item3;
// Add schedules to the job if any // Send Steps, Alerts and Schedules with job history in background
JobScheduleCollection schedules = jobs[parameters.JobName].JobSchedules; // Add steps to the job if any
var jobSchedules = new List<AgentScheduleInfo>(); JobStepCollection steps = jobs[parameters.JobName].JobSteps;
foreach (JobSchedule schedule in schedules) var jobSteps = new List<AgentJobStepInfo>();
{ foreach (JobStep step in steps)
jobSchedules.Add(AgentUtilities.ConvertToAgentScheduleInfo(schedule));
}
result.Schedules = jobSchedules.ToArray();
// Alerts
AlertCollection alerts = jobServer.Alerts;
var jobAlerts = new List<Alert>();
foreach (Alert alert in alerts)
{
if (alert.JobName == parameters.JobName)
{ {
jobAlerts.Add(alert); jobSteps.Add(AgentUtilities.ConvertToAgentJobStepInfo(step, parameters.JobId, parameters.JobName));
} }
result.Steps = jobSteps.ToArray();
// Add schedules to the job if any
JobScheduleCollection schedules = jobs[parameters.JobName].JobSchedules;
var jobSchedules = new List<AgentScheduleInfo>();
foreach (JobSchedule schedule in schedules)
{
jobSchedules.Add(AgentUtilities.ConvertToAgentScheduleInfo(schedule));
}
result.Schedules = jobSchedules.ToArray();
// Alerts
AlertCollection alerts = jobServer.Alerts;
var jobAlerts = new List<Alert>();
foreach (Alert alert in alerts)
{
if (alert.JobName == parameters.JobName)
{
jobAlerts.Add(alert);
}
}
result.Alerts = AgentUtilities.ConvertToAgentAlertInfo(jobAlerts);
// Add histories
int count = dt.Rows.Count;
List<AgentJobHistoryInfo> jobHistories = new List<AgentJobHistoryInfo>();
if (count > 0)
{
var job = dt.Rows[0];
Guid jobId = (Guid)job[AgentUtilities.UrnJobId];
int runStatus = Convert.ToInt32(job[AgentUtilities.UrnRunStatus], System.Globalization.CultureInfo.InvariantCulture);
var t = new LogSourceJobHistory(parameters.JobName, sqlConnInfo, null, runStatus, jobId, null);
var tlog = t as ILogSource;
tlog.Initialize();
var logEntries = t.LogEntries;
// Finally add the job histories
jobHistories = AgentUtilities.ConvertToAgentJobHistoryInfo(logEntries, job, steps);
result.Histories = jobHistories.ToArray();
result.Success = true;
tlog.CloseReader();
}
await requestContext.SendResult(result);
} }
result.Alerts = AgentUtilities.ConvertToAgentAlertInfo(jobAlerts); }
catch (Exception ex)
// Add histories {
int count = dt.Rows.Count; result.Success = false;
List<AgentJobHistoryInfo> jobHistories = new List<AgentJobHistoryInfo>(); result.ErrorMessage = ex.Message;
if (count > 0) Exception exception = ex.InnerException;
while (exception != null)
{ {
var job = dt.Rows[0]; result.ErrorMessage += Environment.NewLine + "\t" + exception.Message;
Guid jobId = (Guid)job[AgentUtilities.UrnJobId]; exception = exception.InnerException;
int runStatus = Convert.ToInt32(job[AgentUtilities.UrnRunStatus], System.Globalization.CultureInfo.InvariantCulture);
var t = new LogSourceJobHistory(parameters.JobName, sqlConnInfo, null, runStatus, jobId, null);
var tlog = t as ILogSource;
tlog.Initialize();
var logEntries = t.LogEntries;
// Finally add the job histories
jobHistories = AgentUtilities.ConvertToAgentJobHistoryInfo(logEntries, job, steps);
result.Histories = jobHistories.ToArray();
result.Success = true;
tlog.CloseReader();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1201,7 +1232,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1230,7 +1261,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1251,7 +1282,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
@@ -1273,7 +1304,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
@@ -1298,7 +1329,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1320,7 +1351,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1343,8 +1374,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1369,8 +1399,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1395,8 +1424,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }
@@ -1420,8 +1448,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
catch (Exception e) catch (Exception e)
{ {
result.Success = false; result.Success = false;
result.ErrorMessage = e.ToString(); result.ErrorMessage = e.GetFullErrorMessage();
} }
await requestContext.SendResult(result); await requestContext.SendResult(result);
} }

View File

@@ -1878,6 +1878,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
/// <param name="connInfo">The connection info to connect with</param> /// <param name="connInfo">The connection info to connect with</param>
/// <param name="featureName">A plaintext string that will be included in the application name for the connection</param> /// <param name="featureName">A plaintext string that will be included in the application name for the connection</param>
/// <returns>A SqlConnection created with the given connection info</returns> /// <returns>A SqlConnection created with the given connection info</returns>
/// <exception cref="Exception">When an error occurs.</exception>
public static SqlConnection OpenSqlConnection(ConnectionInfo connInfo, string featureName = null) public static SqlConnection OpenSqlConnection(ConnectionInfo connInfo, string featureName = null)
{ {
try try
@@ -1927,9 +1928,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
"Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}", "Failed opening a SqlConnection: error:{0} inner:{1} stacktrace:{2}",
ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace); ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace);
Logger.Error(error); Logger.Error(error);
throw;
} }
return null;
} }
/// <summary> /// <summary>

View File

@@ -124,9 +124,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
&& entry.Key != "groupId" && entry.Key != "password" && entry.Key != "connectionName") && entry.Key != "groupId" && entry.Key != "password" && entry.Key != "connectionName")
{ {
// Boolean values are explicitly labeled true or false instead of undefined. // Boolean values are explicitly labeled true or false instead of undefined.
if (entry.Value is bool) if (entry.Value is bool v)
{ {
if ((bool)entry.Value) if (v)
{ {
key += "_" + entry.Key + ":true"; key += "_" + entry.Key + ":true";
} }

View File

@@ -80,9 +80,9 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
public async Task HandleModelImportRequest(ImportModelRequestParams parameters, RequestContext<ImportModelResponseParams> requestContext) public async Task HandleModelImportRequest(ImportModelRequestParams parameters, RequestContext<ImportModelResponseParams> requestContext)
{ {
Logger.Verbose("HandleModelImportRequest"); Logger.Verbose("HandleModelImportRequest");
ImportModelResponseParams response = new ImportModelResponseParams ImportModelResponseParams response = new ImportModelResponseParams
{ {
}; };
await HandleRequest(parameters, response, requestContext, (dbConnection, parameters, response) => await HandleRequest(parameters, response, requestContext, (dbConnection, parameters, response) =>
{ {
@@ -205,8 +205,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
} }
private async Task HandleRequest<T, TResponse>( private async Task HandleRequest<T, TResponse>(
T parameters, T parameters,
TResponse response, TResponse response,
RequestContext<TResponse> requestContext, RequestContext<TResponse> requestContext,
Func<IDbConnection, T, TResponse, TResponse> operation) where T : ModelRequestBase where TResponse : ModelResponseBase Func<IDbConnection, T, TResponse, TResponse> operation) where T : ModelRequestBase where TResponse : ModelResponseBase
{ {
@@ -232,6 +232,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ModelManagement
catch (Exception e) catch (Exception e)
{ {
// Exception related to run task will be captured here // Exception related to run task will be captured here
Logger.Error(e);
await requestContext.SendError(e); await requestContext.SendError(e);
} }
} }

View File

@@ -66,30 +66,22 @@ namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations
public async Task HandleServerConfigViewRequest(ServerConfigViewRequestParams parameters, RequestContext<ServerConfigViewResponseParams> requestContext) public async Task HandleServerConfigViewRequest(ServerConfigViewRequestParams parameters, RequestContext<ServerConfigViewResponseParams> requestContext)
{ {
Logger.Verbose("HandleServerConfigViewRequest"); Logger.Verbose("HandleServerConfigViewRequest");
try ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo == null)
{ {
ConnectionInfo connInfo; await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
if (connInfo == null)
{
await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
}
else
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
ServerConfigProperty serverConfig = GetConfig(serverConnection, parameters.ConfigNumber);
await requestContext.SendResult(new ServerConfigViewResponseParams
{
ConfigProperty = serverConfig
});
}
} }
catch (Exception e) else
{ {
// Exception related to run task will be captured here var serverConnection = ConnectionService.OpenServerConnection(connInfo);
await requestContext.SendError(e); ServerConfigProperty serverConfig = GetConfig(serverConnection, parameters.ConfigNumber);
await requestContext.SendResult(new ServerConfigViewResponseParams
{
ConfigProperty = serverConfig
});
} }
} }
@@ -102,32 +94,24 @@ namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations
public async Task HandleServerConfigUpdateRequest(ServerConfigUpdateRequestParams parameters, RequestContext<ServerConfigUpdateResponseParams> requestContext) public async Task HandleServerConfigUpdateRequest(ServerConfigUpdateRequestParams parameters, RequestContext<ServerConfigUpdateResponseParams> requestContext)
{ {
Logger.Verbose("HandleServerConfigUpdateRequest"); Logger.Verbose("HandleServerConfigUpdateRequest");
try ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
ServerConfigUpdateResponseParams response = new ServerConfigUpdateResponseParams
{ {
ConnectionInfo connInfo; };
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
ServerConfigUpdateResponseParams response = new ServerConfigUpdateResponseParams
{
};
if (connInfo == null) if (connInfo == null)
{
await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
}
else
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
UpdateConfig(serverConnection, parameters.ConfigNumber, parameters.ConfigValue);
response.ConfigProperty = GetConfig(serverConnection, parameters.ConfigNumber);
await requestContext.SendResult(response);
}
}
catch (Exception e)
{ {
// Exception related to run task will be captured here await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
await requestContext.SendError(e); }
else
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
UpdateConfig(serverConnection, parameters.ConfigNumber, parameters.ConfigValue);
response.ConfigProperty = GetConfig(serverConnection, parameters.ConfigNumber);
await requestContext.SendResult(response);
} }
} }
@@ -139,31 +123,23 @@ namespace Microsoft.SqlTools.ServiceLayer.ServerConfigurations
public async Task HandleServerConfigListRequest(ServerConfigListRequestParams parameters, RequestContext<ServerConfigListResponseParams> requestContext) public async Task HandleServerConfigListRequest(ServerConfigListRequestParams parameters, RequestContext<ServerConfigListResponseParams> requestContext)
{ {
Logger.Verbose("HandleServerConfigListRequest"); Logger.Verbose("HandleServerConfigListRequest");
try ConnectionInfo connInfo;
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
ServerConfigListResponseParams response = new ServerConfigListResponseParams
{ {
ConnectionInfo connInfo; };
ConnectionServiceInstance.TryFindConnection(
parameters.OwnerUri,
out connInfo);
ServerConfigListResponseParams response = new ServerConfigListResponseParams
{
};
if (connInfo == null) if (connInfo == null)
{
await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
}
else
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
response.ConfigProperties = GetConfigs(serverConnection);
await requestContext.SendResult(response);
}
}
catch (Exception e)
{ {
// Exception related to run task will be captured here await requestContext.SendError(new Exception(SR.ProfilerConnectionNotFound));
await requestContext.SendError(e); }
else
{
var serverConnection = ConnectionService.OpenServerConnection(connInfo);
response.ConfigProperties = GetConfigs(serverConnection);
await requestContext.SendResult(response);
} }
} }