Fix returned status codes depending on scenario, provide informative logs
Extend logic of encpoints to provide more informative status codes on different scenarios (not found, bad request, etc). Update logging to write structured and informative logs
This commit is contained in:
parent
21a6a22a9e
commit
9329d76ab6
|
@ -37,7 +37,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
||||||
bool isSuccessfullyDisconnected = false;
|
bool isSuccessfullyDisconnected = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await _redisService.DeleteAsync(hiveId);
|
var result = await _redisService.DeleteAsync(GetHiveKey(hiveId));
|
||||||
isSuccessfullyDisconnected = result;
|
isSuccessfullyDisconnected = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -65,9 +65,11 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
||||||
|
|
||||||
public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
|
public async Task<HiveOperationalArea> ConnectHive(HiveModel model)
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("Trying to connect Hive: {@model}", model);
|
||||||
bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model);
|
bool result = await _redisService.SetAsync(GetHiveKey(model.HiveID), model);
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("Successfully connected Hive: {@model}", model);
|
||||||
var operationalArea = _spatialService.GetHiveOperationalArea(model);
|
var operationalArea = _spatialService.GetHiveOperationalArea(model);
|
||||||
await _messageBus.Publish(new HiveConnectedMessage
|
await _messageBus.Publish(new HiveConnectedMessage
|
||||||
{
|
{
|
||||||
|
@ -80,46 +82,41 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _messageBus.Publish(new HiveConnectedMessage
|
_logger.LogError("Failed to connect Hive: {@model}", model);
|
||||||
{
|
|
||||||
HiveID = model.HiveID,
|
|
||||||
Hive = model,
|
|
||||||
IsSuccessfullyConnected = result
|
|
||||||
});
|
|
||||||
throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}");
|
throw new HiveConnectionException($"Failed to connect hive for HiveId: {model.HiveID}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsHiveConnected(string hiveId)
|
||||||
|
{
|
||||||
|
string hiveKey = GetHiveKey(hiveId);
|
||||||
|
return await _redisService.CheckIfKeyExists(hiveKey);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<DateTime> AddTelemetry(HiveTelemetryModel model)
|
public async Task<DateTime> AddTelemetry(HiveTelemetryModel model)
|
||||||
{
|
{
|
||||||
string hiveKey = GetHiveKey(model.HiveID);
|
string hiveKey = GetHiveKey(model.HiveID);
|
||||||
bool hiveExists = await _redisService.CheckIfKeyExists(hiveKey);
|
bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
|
||||||
if (hiveExists)
|
|
||||||
{
|
{
|
||||||
bool result = await _redisService.UpdateAsync(hiveKey, (HiveModel hive) =>
|
hive.Telemetry = model;
|
||||||
{
|
});
|
||||||
hive.Telemetry = model;
|
|
||||||
});
|
|
||||||
|
|
||||||
await _messageBus.Publish(new TelemetrySentMessage
|
if (result)
|
||||||
{
|
{
|
||||||
HiveID = model.HiveID,
|
_logger.LogInformation("Telemetry updated for HiveID: {hiveId}. Updated telemetry timestamp: {timestamp}", model.HiveID, model.Timestamp);
|
||||||
Telemetry = model,
|
|
||||||
IsSuccessfullySent = result
|
|
||||||
});
|
|
||||||
return model.Timestamp;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await _messageBus.Publish(new TelemetrySentMessage
|
_logger.LogError("Failed to update Telemetry - Redis update issue. HiveID: {hiveId}, Telemetry model: {@telemetry}", model.HiveID, model);
|
||||||
{
|
|
||||||
HiveID = model.HiveID,
|
|
||||||
Telemetry = model,
|
|
||||||
IsSuccessfullySent = false
|
|
||||||
});
|
|
||||||
throw new HiveNotFoundException($"Hive not found for id: {model.HiveID}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _messageBus.Publish(new TelemetrySentMessage
|
||||||
|
{
|
||||||
|
HiveID = model.HiveID,
|
||||||
|
Telemetry = model,
|
||||||
|
IsSuccessfullySent = result
|
||||||
|
});
|
||||||
|
return model.Timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> SendHiveControlSignal(string hiveId, Location destination)
|
public async Task<string> SendHiveControlSignal(string hiveId, Location destination)
|
||||||
|
@ -127,33 +124,40 @@ namespace DevOpsProject.CommunicationControl.Logic.Services
|
||||||
var hive = await GetHiveModel(hiveId);
|
var hive = await GetHiveModel(hiveId);
|
||||||
if (hive == null)
|
if (hive == null)
|
||||||
{
|
{
|
||||||
throw new Exception($"Hive control signal error: cannot find hive with id: {hiveId}");
|
_logger.LogError("Sending Hive Control signal: Hive not found for HiveID: {hiveId}", hiveId);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSuccessfullySent = false;
|
bool isSuccessfullySent = false;
|
||||||
|
string hiveMindPath = _communicationControlConfiguration.CurrentValue.HiveMindPath;
|
||||||
|
var command = new MoveHiveMindCommand
|
||||||
|
{
|
||||||
|
CommandType = State.Move,
|
||||||
|
Location = destination,
|
||||||
|
Timestamp = DateTime.Now
|
||||||
|
};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var command = new MoveHiveMindCommand
|
var result = await _hiveHttpClient.SendHiveControlCommandAsync(hive.HiveSchema, hive.HiveIP, hive.HivePort, hiveMindPath, command);
|
||||||
{
|
|
||||||
CommandType = State.Move,
|
|
||||||
Location = destination,
|
|
||||||
Timestamp = DateTime.Now
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = await _hiveHttpClient.SendHiveControlCommandAsync(hive.HiveSchema, hive.HiveIP, hive.HivePort,
|
|
||||||
_communicationControlConfiguration.CurrentValue.HiveMindPath, command);
|
|
||||||
isSuccessfullySent = true;
|
isSuccessfullySent = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
await _messageBus.Publish(new MoveHiveMessage
|
if (isSuccessfullySent)
|
||||||
{
|
{
|
||||||
IsSuccessfullySent = isSuccessfullySent,
|
await _messageBus.Publish(new MoveHiveMessage
|
||||||
Destination = destination,
|
{
|
||||||
HiveID = hiveId
|
IsSuccessfullySent = isSuccessfullySent,
|
||||||
});
|
Destination = destination,
|
||||||
|
HiveID = hiveId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("Failed to send control command for Hive: {@hive}, path: {path}, \n Command: {@command}", hive, hiveMindPath, command);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ namespace DevOpsProject.CommunicationControl.Logic.Services.Interfaces
|
||||||
Task<HiveModel> GetHiveModel(string hiveId);
|
Task<HiveModel> GetHiveModel(string hiveId);
|
||||||
Task<List<HiveModel>> GetAllHives();
|
Task<List<HiveModel>> GetAllHives();
|
||||||
Task<HiveOperationalArea> ConnectHive(HiveModel model);
|
Task<HiveOperationalArea> ConnectHive(HiveModel model);
|
||||||
|
Task<bool> IsHiveConnected(string hiveId);
|
||||||
Task<DateTime> AddTelemetry(HiveTelemetryModel model);
|
Task<DateTime> AddTelemetry(HiveTelemetryModel model);
|
||||||
Task<string> SendHiveControlSignal(string hiveId, Location destination);
|
Task<string> SendHiveControlSignal(string hiveId, Location destination);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
||||||
// If already moving - stop movement
|
// If already moving - stop movement
|
||||||
if (HiveInMemoryState.IsMoving)
|
if (HiveInMemoryState.IsMoving)
|
||||||
{
|
{
|
||||||
|
_logger.LogWarning("Previous movement command terminated. Previous destination: {@destination}, Current Location: {@current}, new destination: {@destination}", HiveInMemoryState.Destination, HiveInMemoryState.CurrentLocation, destination);
|
||||||
StopMovement();
|
StopMovement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +40,9 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
||||||
if (_movementTimer == null)
|
if (_movementTimer == null)
|
||||||
{
|
{
|
||||||
// TODO: Recalculating position each N seconds
|
// TODO: Recalculating position each N seconds
|
||||||
_movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(3));
|
int intervalFromSeconds = 3;
|
||||||
_logger.LogInformation("Movement timer started.");
|
_movementTimer = new Timer(UpdateMovement, null, TimeSpan.Zero, TimeSpan.FromSeconds(intervalFromSeconds));
|
||||||
|
_logger.LogInformation("Movement timer started. Destination: {@destination}, recalculation interval: {interval}", destination, intervalFromSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,14 +62,13 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
||||||
|
|
||||||
if (AreLocationsEqual(currentLocation.Value, destination.Value))
|
if (AreLocationsEqual(currentLocation.Value, destination.Value))
|
||||||
{
|
{
|
||||||
|
_logger.LogInformation("Reached destination. Current location: {@currentLocation}, Destination: {@destination}", currentLocation, destination);
|
||||||
StopMovement();
|
StopMovement();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
|
Location newLocation = CalculateNextPosition(currentLocation.Value, destination.Value, 0.1f);
|
||||||
HiveInMemoryState.CurrentLocation = newLocation;
|
HiveInMemoryState.CurrentLocation = newLocation;
|
||||||
|
|
||||||
_logger.LogInformation($"Moved closer: {newLocation}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,7 +78,6 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
||||||
_movementTimer = null;
|
_movementTimer = null;
|
||||||
HiveInMemoryState.IsMoving = false;
|
HiveInMemoryState.IsMoving = false;
|
||||||
HiveInMemoryState.Destination = null;
|
HiveInMemoryState.Destination = null;
|
||||||
_logger.LogInformation("Movement stopped: Reached destination.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool AreLocationsEqual(Location loc1, Location loc2)
|
private static bool AreLocationsEqual(Location loc1, Location loc2)
|
||||||
|
|
|
@ -48,6 +48,8 @@ namespace DevOpsProject.HiveMind.Logic.Services
|
||||||
};
|
};
|
||||||
var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
|
var jsonContent = new StringContent(JsonSerializer.Serialize(request), Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
_logger.LogInformation("Attempting to connect Hive. Request: {@request}, URI: {uri}", request, uriBuilder.Uri);
|
||||||
|
|
||||||
var retryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
|
var retryPolicy = Policy.HandleResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
|
||||||
.WaitAndRetryAsync(
|
.WaitAndRetryAsync(
|
||||||
10,
|
10,
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
namespace DevOpsProject.Shared.Exceptions
|
|
||||||
{
|
|
||||||
public class HiveNotFoundException : Exception
|
|
||||||
{
|
|
||||||
public HiveNotFoundException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public HiveNotFoundException(string message)
|
|
||||||
: base(message)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public HiveNotFoundException(string message, Exception inner)
|
|
||||||
: base(message, inner)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -32,17 +32,21 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
[HttpGet("hive/{hiveId}")]
|
[HttpGet("hive/{hiveId}")]
|
||||||
public async Task<IActionResult> GetHive(string hiveId)
|
public async Task<IActionResult> GetHive(string hiveId)
|
||||||
{
|
{
|
||||||
var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
|
var hiveExists = await _communicationControlService.IsHiveConnected(hiveId);
|
||||||
|
if (!hiveExists)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Failed to get Hive for HiveID: {hiveId}", hiveId);
|
||||||
|
return NotFound($"Hive with HiveID: {hiveId} is not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
var hiveModel = await _communicationControlService.GetHiveModel(hiveId);
|
||||||
return Ok(hiveModel);
|
return Ok(hiveModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("hive")]
|
[HttpGet("hive")]
|
||||||
public async Task<IActionResult> GetHives()
|
public async Task<IActionResult> GetHives()
|
||||||
{
|
{
|
||||||
|
|
||||||
var hives = await _communicationControlService.GetAllHives();
|
var hives = await _communicationControlService.GetAllHives();
|
||||||
|
|
||||||
return Ok(hives);
|
return Ok(hives);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
if (request?.Hives == null || !request.Hives.Any())
|
if (request?.Hives == null || !request.Hives.Any())
|
||||||
return BadRequest("No hive IDs provided.");
|
return BadRequest("No hive IDs provided.");
|
||||||
|
|
||||||
|
_logger.LogInformation("Hive moving request accepted by enpdoint. Request: {@request}", request);
|
||||||
foreach (var id in request.Hives)
|
foreach (var id in request.Hives)
|
||||||
{
|
{
|
||||||
_ = Task.Run(async () =>
|
_ = Task.Run(async () =>
|
||||||
|
@ -69,7 +74,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, $"Failed to send control signal for HiveID: {id}");
|
_logger.LogError(ex, "Failed to send control signal for HiveID: {id} \n Request: {@request}", id, request);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,12 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
public class HiveController : Controller
|
public class HiveController : Controller
|
||||||
{
|
{
|
||||||
private readonly ICommunicationControlService _communicationControlService;
|
private readonly ICommunicationControlService _communicationControlService;
|
||||||
|
private readonly ILogger<HiveController> _logger;
|
||||||
|
|
||||||
public HiveController(ICommunicationControlService communicationControlService)
|
public HiveController(ICommunicationControlService communicationControlService, ILogger<HiveController> logger)
|
||||||
{
|
{
|
||||||
_communicationControlService = communicationControlService;
|
_communicationControlService = communicationControlService;
|
||||||
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("connect")]
|
[HttpPost("connect")]
|
||||||
|
@ -28,6 +30,13 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
HiveSchema = request.HiveSchema
|
HiveSchema = request.HiveSchema
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool isConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
|
||||||
|
if (isConnected)
|
||||||
|
{
|
||||||
|
_logger.LogError("Hive with HiveID: {hiveId} already connected. Request: {@request}", request.HiveID, request);
|
||||||
|
return BadRequest($"Hive with HiveID: {request.HiveID} already connected");
|
||||||
|
}
|
||||||
|
|
||||||
var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel);
|
var hiveOperationalArea = await _communicationControlService.ConnectHive(hiveModel);
|
||||||
var connectResponse = new HiveConnectResponse
|
var connectResponse = new HiveConnectResponse
|
||||||
{
|
{
|
||||||
|
@ -36,6 +45,7 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(connectResponse);
|
return Ok(connectResponse);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("telemetry")]
|
[HttpPost("telemetry")]
|
||||||
|
@ -51,13 +61,22 @@ namespace DevOpsProject.CommunicationControl.API.Controllers
|
||||||
Timestamp = DateTime.Now
|
Timestamp = DateTime.Now
|
||||||
};
|
};
|
||||||
|
|
||||||
var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
|
bool isHiveConnected = await _communicationControlService.IsHiveConnected(request.HiveID);
|
||||||
var telemetryResponse = new HiveTelemetryResponse
|
if (isHiveConnected)
|
||||||
{
|
{
|
||||||
Timestamp = telemetryUpdateTimestamp
|
var telemetryUpdateTimestamp = await _communicationControlService.AddTelemetry(hiveTelemetryModel);
|
||||||
};
|
var telemetryResponse = new HiveTelemetryResponse
|
||||||
|
{
|
||||||
|
Timestamp = telemetryUpdateTimestamp
|
||||||
|
};
|
||||||
|
|
||||||
return Ok(telemetryResponse);
|
return Ok(telemetryResponse);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Failed to write telemetry. Hive with HiveID: {hiveId} is not connected. Request: {@request}", request.HiveID, request);
|
||||||
|
return NotFound($"Failed to write telemetry. Hive with HiveID: {request.HiveID} is not connected");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,5 @@ namespace DevOpsProject.CommunicationControl.API.DI
|
||||||
|
|
||||||
return serviceCollection;
|
return serviceCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue