mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-04-22 07:16:39 +00:00
less logs
This commit is contained in:
@@ -85,8 +85,6 @@ if (!migrator.RunMigrations())
|
||||
var storageConfig = app.Configuration.GetSection("StorageConfig").Get<StorageConfig>() ?? new StorageConfig();
|
||||
Directory.CreateDirectory(storageConfig.TilesDirectory);
|
||||
Directory.CreateDirectory(storageConfig.ReadyDirectory);
|
||||
logger.LogInformation("Storage directories created: Tiles={TilesDir}, Ready={ReadyDir}",
|
||||
storageConfig.TilesDirectory, storageConfig.ReadyDirectory);
|
||||
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
@@ -125,9 +123,6 @@ async Task<IResult> GetTileByLatLon([FromQuery] double Latitude, [FromQuery] dou
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Getting tile at ({Lat}, {Lon}) with zoom level {Zoom}",
|
||||
Latitude, Longitude, ZoomLevel);
|
||||
|
||||
var downloadedTile = await downloader.DownloadSingleTileAsync(
|
||||
Latitude,
|
||||
Longitude,
|
||||
@@ -152,7 +147,6 @@ async Task<IResult> GetTileByLatLon([FromQuery] double Latitude, [FromQuery] dou
|
||||
};
|
||||
|
||||
await tileRepository.InsertAsync(tileEntity);
|
||||
logger.LogInformation("Tile saved to database with ID: {Id}", tileEntity.Id);
|
||||
|
||||
var response = new DownloadTileResponse
|
||||
{
|
||||
@@ -198,9 +192,6 @@ async Task<IResult> RequestRegion([FromBody] RequestRegionRequest request, IRegi
|
||||
return Results.BadRequest(new { error = "Size must be between 100 and 10000 meters" });
|
||||
}
|
||||
|
||||
logger.LogInformation("Region request received: ID={Id}, Lat={Lat}, Lon={Lon}, Size={Size}m, Zoom={Zoom}, Stitch={Stitch}",
|
||||
request.Id, request.Latitude, request.Longitude, request.SizeMeters, request.ZoomLevel, request.StitchTiles);
|
||||
|
||||
var status = await regionService.RequestRegionAsync(
|
||||
request.Id,
|
||||
request.Latitude,
|
||||
@@ -242,36 +233,6 @@ async Task<IResult> CreateRoute([FromBody] CreateRouteRequest request, IRouteSer
|
||||
{
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Route creation request: ID={Id}, Name={Name}, Points={PointCount}, RegionSize={RegionSize}m, Zoom={Zoom}, RequestMaps={RequestMaps}",
|
||||
request.Id, request.Name, request.Points.Count, request.RegionSizeMeters, request.ZoomLevel, request.RequestMaps);
|
||||
|
||||
if (request.Points.Count > 0)
|
||||
{
|
||||
var firstPoint = request.Points[0];
|
||||
logger.LogInformation("First point: Lat={Lat}, Lon={Lon}", firstPoint.Latitude, firstPoint.Longitude);
|
||||
}
|
||||
|
||||
if (request.Geofences != null)
|
||||
{
|
||||
logger.LogInformation("Geofences object received: Polygons count = {Count}", request.Geofences.Polygons?.Count ?? 0);
|
||||
|
||||
if (request.Geofences.Polygons != null)
|
||||
{
|
||||
for (int i = 0; i < request.Geofences.Polygons.Count; i++)
|
||||
{
|
||||
var polygon = request.Geofences.Polygons[i];
|
||||
logger.LogInformation("Geofence {Index}: NorthWest = {NW}, SouthEast = {SE}",
|
||||
i,
|
||||
polygon.NorthWest is not null ? $"({polygon.NorthWest.Lat}, {polygon.NorthWest.Lon})" : "null",
|
||||
polygon.SouthEast is not null ? $"({polygon.SouthEast.Lat}, {polygon.SouthEast.Lon})" : "null");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.LogInformation("No geofences provided (Geofences is null)");
|
||||
}
|
||||
|
||||
var route = await routeService.CreateRouteAsync(request);
|
||||
return Results.Ok(route);
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
"Serilog": {
|
||||
"Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ],
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Default": "Warning",
|
||||
"Override": {
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"SatelliteProvider.Services.RegionRequestQueue": "Debug",
|
||||
"SatelliteProvider.Services.GoogleMapsDownloaderV2": "Debug"
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"WriteTo": [
|
||||
|
||||
@@ -97,9 +97,6 @@ public class GoogleMapsDownloaderV2
|
||||
var geoPoint = new GeoPoint(latitude, longitude);
|
||||
var (tileX, tileY) = GeoUtils.WorldToTilePos(geoPoint, zoomLevel);
|
||||
|
||||
_logger.LogInformation("Downloading single tile at ({Lat}, {Lon}), zoom {Zoom}, tile coordinates ({X}, {Y})",
|
||||
latitude, longitude, zoomLevel, tileX, tileY);
|
||||
|
||||
var sessionToken = await GetSessionToken();
|
||||
var server = 0;
|
||||
var url = string.Format(TILE_URL_TEMPLATE, server, tileX, tileY, zoomLevel, sessionToken);
|
||||
@@ -134,8 +131,6 @@ public class GoogleMapsDownloaderV2
|
||||
var tileCenter = GeoUtils.TileToWorldPos(tileX, tileY, zoomLevel);
|
||||
var tileSizeMeters = CalculateTileSizeInMeters(zoomLevel, tileCenter.Lat);
|
||||
|
||||
_logger.LogInformation("Downloaded tile to {FilePath}, size: {Size:F2} meters", filePath, tileSizeMeters);
|
||||
|
||||
return new DownloadedTileInfoV2(
|
||||
tileX,
|
||||
tileY,
|
||||
@@ -249,10 +244,6 @@ public class GoogleMapsDownloaderV2
|
||||
var (xMin, yMin) = GeoUtils.WorldToTilePos(new GeoPoint(latMax, lonMin), zoomLevel);
|
||||
var (xMax, yMax) = GeoUtils.WorldToTilePos(new GeoPoint(latMin, lonMax), zoomLevel);
|
||||
|
||||
_logger.LogInformation("Checking tiles for region: center=({Lat}, {Lon}), radius={Radius}m, zoom={Zoom}",
|
||||
centerGeoPoint.Lat, centerGeoPoint.Lon, radiusM, zoomLevel);
|
||||
_logger.LogInformation("Tile range: X=[{XMin}, {XMax}], Y=[{YMin}, {YMax}]", xMin, xMax, yMin, yMax);
|
||||
|
||||
var tilesToDownload = new List<(int x, int y, GeoPoint center, double tileSizeMeters)>();
|
||||
int skippedCount = 0;
|
||||
|
||||
@@ -262,12 +253,6 @@ public class GoogleMapsDownloaderV2
|
||||
{
|
||||
var tileCenter = GeoUtils.TileToWorldPos(x, y, zoomLevel);
|
||||
|
||||
if ((x == xMin && y == yMin) || (x == xMax && y == yMax))
|
||||
{
|
||||
_logger.LogInformation("GoogleMapsDownloader - Tile ({X}, {Y}) center calculated: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
x, y, tileCenter.Lat, tileCenter.Lon);
|
||||
}
|
||||
|
||||
var existingTile = existingTiles.FirstOrDefault(t =>
|
||||
Math.Abs(t.Latitude - tileCenter.Lat) < 0.0001 &&
|
||||
Math.Abs(t.Longitude - tileCenter.Lon) < 0.0001 &&
|
||||
@@ -284,18 +269,12 @@ public class GoogleMapsDownloaderV2
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Need to download {Count} tiles (skipped {Skipped} existing), using {MaxConcurrent} parallel downloads",
|
||||
tilesToDownload.Count, skippedCount, _processingConfig.MaxConcurrentDownloads);
|
||||
|
||||
if (tilesToDownload.Count == 0)
|
||||
{
|
||||
_logger.LogInformation("All tiles already exist, returning empty list");
|
||||
return new List<DownloadedTileInfoV2>();
|
||||
}
|
||||
|
||||
_logger.LogInformation("Getting initial session token before starting {Count} downloads", tilesToDownload.Count);
|
||||
var sessionToken = await GetSessionToken();
|
||||
_logger.LogInformation("Session token obtained, starting parallel downloads");
|
||||
|
||||
var downloadTasks = new List<Task<DownloadedTileInfoV2?>>();
|
||||
int sessionTokenUsageCount = 0;
|
||||
@@ -306,10 +285,8 @@ public class GoogleMapsDownloaderV2
|
||||
|
||||
if (sessionTokenUsageCount >= _processingConfig.SessionTokenReuseCount)
|
||||
{
|
||||
_logger.LogInformation("Session token usage limit reached ({Count}), requesting new token", sessionTokenUsageCount);
|
||||
sessionToken = await GetSessionToken();
|
||||
sessionTokenUsageCount = 0;
|
||||
_logger.LogInformation("New session token obtained, continuing downloads");
|
||||
}
|
||||
|
||||
var currentToken = sessionToken;
|
||||
@@ -330,15 +307,10 @@ public class GoogleMapsDownloaderV2
|
||||
downloadTasks.Add(downloadTask);
|
||||
}
|
||||
|
||||
_logger.LogInformation("All {Count} download tasks created, waiting for completion", downloadTasks.Count);
|
||||
var results = await Task.WhenAll(downloadTasks);
|
||||
_logger.LogInformation("Task.WhenAll completed, processing results");
|
||||
|
||||
var downloadedTiles = results.Where(r => r != null).Cast<DownloadedTileInfoV2>().ToList();
|
||||
|
||||
_logger.LogInformation("Parallel download completed: {Downloaded} tiles downloaded, {Skipped} skipped, {Failed} failed",
|
||||
downloadedTiles.Count, skippedCount, tilesToDownload.Count - downloadedTiles.Count);
|
||||
|
||||
return downloadedTiles;
|
||||
}
|
||||
|
||||
@@ -418,12 +390,6 @@ public class GoogleMapsDownloaderV2
|
||||
|
||||
await File.WriteAllBytesAsync(filePath, imageBytes, token);
|
||||
|
||||
if ((tileIndex + 1) % 10 == 0 || tileIndex == 0 || tileIndex == totalTiles - 1)
|
||||
{
|
||||
_logger.LogInformation("Progress: {Current}/{Total} tiles downloaded - tile ({X}, {Y})",
|
||||
tileIndex + 1, totalTiles, x, y);
|
||||
}
|
||||
|
||||
return new DownloadedTileInfoV2(
|
||||
x, y, zoomLevel, tileCenter.Lat, tileCenter.Lon, filePath, tileSizeMeters);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,6 @@ public class RegionService : IRegionService
|
||||
|
||||
public async Task<RegionStatus> RequestRegionAsync(Guid id, double latitude, double longitude, double sizeMeters, int zoomLevel, bool stitchTiles = false)
|
||||
{
|
||||
_logger.LogInformation("RegionService - Requesting region {RegionId}: Lat={Lat:F12}, Lon={Lon:F12}, Size={Size}m, Zoom={Zoom}",
|
||||
id, latitude, longitude, sizeMeters, zoomLevel);
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var region = new RegionEntity
|
||||
{
|
||||
@@ -69,8 +66,6 @@ public class RegionService : IRegionService
|
||||
|
||||
await _queue.EnqueueAsync(request);
|
||||
|
||||
_logger.LogInformation("Region {RegionId} queued for processing", id);
|
||||
|
||||
return MapToStatus(region);
|
||||
}
|
||||
|
||||
@@ -82,7 +77,6 @@ public class RegionService : IRegionService
|
||||
|
||||
public async Task ProcessRegionAsync(Guid id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.LogInformation("Processing region {RegionId} - START", id);
|
||||
var startTime = DateTime.UtcNow;
|
||||
|
||||
var region = await _regionRepository.GetByIdAsync(id);
|
||||
@@ -92,12 +86,10 @@ public class RegionService : IRegionService
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Region {RegionId}: Updating status to 'processing' (was: {OldStatus})", id, region.Status);
|
||||
region.Status = "processing";
|
||||
region.UpdatedAt = DateTime.UtcNow;
|
||||
await _regionRepository.UpdateAsync(region);
|
||||
|
||||
_logger.LogInformation("Region {RegionId}: Creating timeout CTS (5 minutes)", id);
|
||||
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
|
||||
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
|
||||
|
||||
@@ -108,35 +100,25 @@ public class RegionService : IRegionService
|
||||
|
||||
try
|
||||
{
|
||||
_logger.LogInformation("Region {RegionId}: Step 1 - Starting download for location ({Lat}, {Lon}) size {Size}m zoom {Zoom}",
|
||||
id, region.Latitude, region.Longitude, region.SizeMeters, region.ZoomLevel);
|
||||
|
||||
var processingStartTime = DateTime.UtcNow;
|
||||
|
||||
_logger.LogInformation("Region {RegionId}: Step 2 - Checking for existing tiles", id);
|
||||
var tilesBeforeDownload = await _tileService.GetTilesByRegionAsync(
|
||||
region.Latitude,
|
||||
region.Longitude,
|
||||
region.SizeMeters,
|
||||
region.ZoomLevel);
|
||||
var existingTileIds = new HashSet<Guid>(tilesBeforeDownload.Select(t => t.Id));
|
||||
_logger.LogInformation("Region {RegionId}: Step 3 - Found {Count} existing tiles", id, existingTileIds.Count);
|
||||
|
||||
_logger.LogInformation("Region {RegionId}: Step 4 - Calling DownloadAndStoreTilesAsync", id);
|
||||
tiles = await _tileService.DownloadAndStoreTilesAsync(
|
||||
region.Latitude,
|
||||
region.Longitude,
|
||||
region.SizeMeters,
|
||||
region.ZoomLevel,
|
||||
linkedCts.Token);
|
||||
_logger.LogInformation("Region {RegionId}: Step 5 - DownloadAndStoreTilesAsync completed with {Count} tiles", id, tiles.Count);
|
||||
|
||||
tilesDownloaded = tiles.Count(t => !existingTileIds.Contains(t.Id));
|
||||
tilesReused = tiles.Count(t => existingTileIds.Contains(t.Id));
|
||||
|
||||
_logger.LogInformation("Region {RegionId}: Step 6 - Downloaded {Downloaded} new tiles, Reused {Reused} existing tiles",
|
||||
id, tilesDownloaded, tilesReused);
|
||||
|
||||
var readyDir = _storageConfig.ReadyDirectory;
|
||||
Directory.CreateDirectory(readyDir);
|
||||
|
||||
@@ -149,13 +131,8 @@ public class RegionService : IRegionService
|
||||
if (region.StitchTiles)
|
||||
{
|
||||
stitchedImagePath = Path.Combine(readyDir, $"region_{id}_stitched.jpg");
|
||||
_logger.LogInformation("Stitching tiles for region {RegionId}", id);
|
||||
await StitchTilesAsync(tiles, region.Latitude, region.Longitude, region.ZoomLevel, stitchedImagePath, linkedCts.Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("Skipping tile stitching for region {RegionId}", id);
|
||||
}
|
||||
|
||||
await GenerateSummaryFileAsync(summaryPath, id, region, tiles, tilesDownloaded, tilesReused, stitchedImagePath, processingStartTime, linkedCts.Token, errorMessage);
|
||||
|
||||
@@ -166,9 +143,6 @@ public class RegionService : IRegionService
|
||||
region.TilesReused = tilesReused;
|
||||
region.UpdatedAt = DateTime.UtcNow;
|
||||
await _regionRepository.UpdateAsync(region);
|
||||
|
||||
var duration = (DateTime.UtcNow - startTime).TotalSeconds;
|
||||
_logger.LogInformation("Region {RegionId} processing completed in {Duration:F2}s", id, duration);
|
||||
}
|
||||
catch (TaskCanceledException ex) when (timeoutCts.IsCancellationRequested)
|
||||
{
|
||||
@@ -293,9 +267,6 @@ public class RegionService : IRegionService
|
||||
var imageWidth = gridWidth * tileSizePixels;
|
||||
var imageHeight = gridHeight * tileSizePixels;
|
||||
|
||||
_logger.LogInformation("Stitching {Count} tiles into {Width}x{Height} image (grid: {GridWidth}x{GridHeight})",
|
||||
tiles.Count, imageWidth, imageHeight, gridWidth, gridHeight);
|
||||
|
||||
using var stitchedImage = new Image<Rgb24>(imageWidth, imageHeight);
|
||||
|
||||
foreach (var (x, y, filePath) in tileCoords)
|
||||
@@ -323,9 +294,6 @@ public class RegionService : IRegionService
|
||||
var crossX = (int)Math.Round((centerTileX - minX) * tileSizePixels + centerTilePixelX);
|
||||
var crossY = (int)Math.Round((centerTileY - minY) * tileSizePixels + centerTilePixelY);
|
||||
|
||||
_logger.LogInformation("Drawing red cross at pixel position ({X}, {Y}) for coordinates ({Lat}, {Lon})",
|
||||
crossX, crossY, centerLatitude, centerLongitude);
|
||||
|
||||
var red = new Rgb24(255, 0, 0);
|
||||
stitchedImage.Mutate(ctx =>
|
||||
{
|
||||
@@ -347,7 +315,6 @@ public class RegionService : IRegionService
|
||||
});
|
||||
|
||||
await stitchedImage.SaveAsJpegAsync(outputPath, cancellationToken);
|
||||
_logger.LogInformation("Stitched image saved to {OutputPath}", outputPath);
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
@@ -356,12 +323,6 @@ public class RegionService : IRegionService
|
||||
{
|
||||
var orderedTiles = tiles.OrderByDescending(t => t.Latitude).ThenBy(t => t.Longitude).ToList();
|
||||
|
||||
if (orderedTiles.Any())
|
||||
{
|
||||
_logger.LogInformation("RegionService - Writing CSV with {Count} tiles. First tile: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
orderedTiles.Count, orderedTiles[0].Latitude, orderedTiles[0].Longitude);
|
||||
}
|
||||
|
||||
using var writer = new StreamWriter(filePath);
|
||||
await writer.WriteLineAsync("latitude,longitude,file_path");
|
||||
|
||||
|
||||
@@ -59,12 +59,6 @@ public class RouteProcessingService : BackgroundService
|
||||
{
|
||||
var pendingRoutes = await GetRoutesWithPendingMapsAsync();
|
||||
|
||||
if (pendingRoutes.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Processing {Count} route(s) with pending maps: {RouteIds}",
|
||||
pendingRoutes.Count, string.Join(", ", pendingRoutes.Select(r => r.Id)));
|
||||
}
|
||||
|
||||
foreach (var route in pendingRoutes)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
@@ -96,21 +90,11 @@ public class RouteProcessingService : BackgroundService
|
||||
return;
|
||||
}
|
||||
|
||||
if (!route.RequestMaps)
|
||||
if (!route.RequestMaps || route.MapsReady)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: RequestMaps=false, skipping processing", routeId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (route.MapsReady)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: MapsReady=true, skipping processing", routeId);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Starting processing check - RequestMaps={RequestMaps}, MapsReady={MapsReady}",
|
||||
routeId, route.RequestMaps, route.MapsReady);
|
||||
|
||||
var routePointsList = (await _routeRepository.GetRoutePointsAsync(routeId)).ToList();
|
||||
var regionIdsList = (await _routeRepository.GetRegionIdsByRouteAsync(routeId)).ToList();
|
||||
var geofenceRegionIdsList = (await _routeRepository.GetGeofenceRegionIdsByRouteAsync(routeId)).ToList();
|
||||
@@ -119,23 +103,13 @@ public class RouteProcessingService : BackgroundService
|
||||
|
||||
if (regionIdsList.Count == 0 && routePointsList.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: No route point regions linked yet. Will create regions for {PointCount} route points", routeId, routePointsList.Count);
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var regionService = scope.ServiceProvider.GetRequiredService<Common.Interfaces.IRegionService>();
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Starting parallel region processing for {PointCount} points",
|
||||
routeId, routePointsList.Count);
|
||||
|
||||
var queuedRegionIds = new List<Guid>();
|
||||
|
||||
foreach (var point in routePointsList)
|
||||
{
|
||||
var regionId = Guid.NewGuid();
|
||||
|
||||
_logger.LogInformation("RouteProcessingService - Creating region {RegionId} for route {RouteId} at point: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
regionId, routeId, point.Latitude, point.Longitude);
|
||||
|
||||
await regionService.RequestRegionAsync(
|
||||
regionId,
|
||||
point.Latitude,
|
||||
@@ -145,11 +119,8 @@ public class RouteProcessingService : BackgroundService
|
||||
stitchTiles: false);
|
||||
|
||||
await _routeRepository.LinkRouteToRegionAsync(routeId, regionId);
|
||||
queuedRegionIds.Add(regionId);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Queued all {Count} regions for parallel processing. Region IDs: {RegionIds}",
|
||||
routeId, queuedRegionIds.Count, string.Join(", ", queuedRegionIds.Take(5)) + (queuedRegionIds.Count > 5 ? "..." : ""));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -170,27 +141,16 @@ public class RouteProcessingService : BackgroundService
|
||||
var completedRoutePointRegions = completedRegions.Where(r => !geofenceRegionIdsList.Contains(r.Id)).ToList();
|
||||
var completedGeofenceRegions = completedRegions.Where(r => geofenceRegionIdsList.Contains(r.Id)).ToList();
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Region counts - Total allRegionIds={AllCount}, regionIdsList={RoutePointCount}, geofenceRegionIdsList={GeofenceCount}",
|
||||
routeId, allRegionIds.Count, regionIdsList.Count, geofenceRegionIdsList.Count);
|
||||
_logger.LogInformation("Route {RouteId}: Status breakdown - Completed={Completed} (RoutePoint={CompletedRP}, Geofence={CompletedGF}), Failed={Failed}, Processing={Processing}",
|
||||
routeId, completedRegions.Count, completedRoutePointRegions.Count, completedGeofenceRegions.Count, failedRegions.Count, processingRegions.Count);
|
||||
|
||||
var hasRoutePointRegions = regionIdsList.Count > 0;
|
||||
var hasEnoughRoutePointRegions = !hasRoutePointRegions || completedRoutePointRegions.Count >= routePointsList.Count;
|
||||
var hasAllGeofenceRegions = geofenceRegionIdsList.Count == 0 || completedGeofenceRegions.Count >= geofenceRegionIdsList.Count;
|
||||
var hasEnoughCompleted = hasEnoughRoutePointRegions && hasAllGeofenceRegions;
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Condition checks - hasRoutePointRegions={HasRP}, hasEnoughRoutePointRegions={HasEnoughRP} (need {NeedRP}), hasAllGeofenceRegions={HasAllGF} (need {NeedGF}), hasEnoughCompleted={HasEnough}",
|
||||
routeId, hasRoutePointRegions, hasEnoughRoutePointRegions, routePointsList.Count, hasAllGeofenceRegions, geofenceRegionIdsList.Count, hasEnoughCompleted);
|
||||
|
||||
var activeRegions = completedRegions.Count + processingRegions.Count;
|
||||
var shouldRetryFailed = failedRegions.Count > 0 && !hasEnoughCompleted && activeRegions < allRegionIds.Count;
|
||||
|
||||
if (hasEnoughCompleted)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: Have {RoutePointCompleted}/{RoutePointRequired} route point regions and {GeofenceCompleted}/{GeofenceRequired} geofence regions completed. Generating final maps. Ignoring {Processing} processing and {Failed} failed regions.",
|
||||
routeId, completedRoutePointRegions.Count, routePointsList.Count, completedGeofenceRegions.Count, geofenceRegionIdsList.Count, processingRegions.Count, failedRegions.Count);
|
||||
|
||||
var orderedRouteRegions = MatchRegionsToRoutePoints(routePointsList, completedRoutePointRegions, routeId);
|
||||
var routeRegionIds = orderedRouteRegions.Select(r => r.Id).ToList();
|
||||
var allRegionIdsForStitching = routeRegionIds.Concat(completedGeofenceRegions.Select(r => r.Id)).Distinct();
|
||||
@@ -202,17 +162,12 @@ public class RouteProcessingService : BackgroundService
|
||||
|
||||
if (shouldRetryFailed)
|
||||
{
|
||||
_logger.LogWarning("Route {RouteId}: {FailedCount} region(s) failed: {FailedRegions}. Active regions: {ActiveCount}/{RequiredCount}. Attempting to retry with new regions.",
|
||||
routeId, failedRegions.Count, string.Join(", ", failedRegions.Select(r => r.Id)), activeRegions, routePointsList.Count);
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var regionService = scope.ServiceProvider.GetRequiredService<Common.Interfaces.IRegionService>();
|
||||
|
||||
foreach (var failedRegion in failedRegions)
|
||||
{
|
||||
var newRegionId = Guid.NewGuid();
|
||||
_logger.LogInformation("Route {RouteId}: Retrying failed region {OldRegionId} with new region {NewRegionId}",
|
||||
routeId, failedRegion.Id, newRegionId);
|
||||
|
||||
await regionService.RequestRegionAsync(
|
||||
newRegionId,
|
||||
@@ -225,15 +180,12 @@ public class RouteProcessingService : BackgroundService
|
||||
await _routeRepository.LinkRouteToRegionAsync(routeId, newRegionId);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Queued {Count} retry regions", routeId, failedRegions.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
var anyProcessing = processingRegions.Count > 0;
|
||||
if (anyProcessing)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: Progress - {RoutePointCompleted}/{RoutePointRequired} route point regions, {GeofenceCompleted}/{GeofenceRequired} geofence regions completed, {Processing} still processing, {Failed} failed (will retry if needed)",
|
||||
routeId, completedRoutePointRegions.Count, routePointsList.Count, completedGeofenceRegions.Count, geofenceRegionIdsList.Count, processingRegions.Count, failedRegions.Count);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,11 +219,6 @@ public class RouteProcessingService : BackgroundService
|
||||
continue;
|
||||
}
|
||||
|
||||
var isGeofence = geofenceRegionIds.Contains(regionId);
|
||||
_logger.LogInformation("Route {RouteId}: Processing region {RegionId} ({Type}) - Lat={Lat}, Lon={Lon}, Size={Size}m, CSV={CsvPath}",
|
||||
routeId, regionId, isGeofence ? "GEOFENCE" : "RoutePoint",
|
||||
region.Latitude, region.Longitude, region.SizeMeters, region.CsvFilePath);
|
||||
|
||||
var csvLines = await File.ReadAllLinesAsync(region.CsvFilePath, cancellationToken);
|
||||
|
||||
var lineNumber = 0;
|
||||
@@ -283,22 +230,14 @@ public class RouteProcessingService : BackgroundService
|
||||
|
||||
if (!double.TryParse(parts[0], out var lat))
|
||||
{
|
||||
_logger.LogWarning("Route {RouteId} - Failed to parse latitude from CSV line {LineNumber}: {Line}", routeId, lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
if (!double.TryParse(parts[1], out var lon))
|
||||
{
|
||||
_logger.LogWarning("Route {RouteId} - Failed to parse longitude from CSV line {LineNumber}: {Line}", routeId, lineNumber, line);
|
||||
continue;
|
||||
}
|
||||
var filePath = parts[2];
|
||||
|
||||
if (lineNumber <= 3)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId} - Reading tile from region {RegionId} CSV: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
routeId, regionId, lat, lon);
|
||||
}
|
||||
|
||||
totalTilesFromRegions++;
|
||||
var key = $"{lat:F6}_{lon:F6}";
|
||||
|
||||
@@ -318,9 +257,6 @@ public class RouteProcessingService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Collected {UniqueCount} unique tiles ({DuplicateCount} duplicates from {TotalCount} total)",
|
||||
routeId, allTiles.Count, duplicateTiles, totalTilesFromRegions);
|
||||
|
||||
var csvPath = Path.Combine(readyDir, $"route_{routeId}_ready.csv");
|
||||
await GenerateRouteCsvAsync(csvPath, allTiles.Values, cancellationToken);
|
||||
|
||||
@@ -363,8 +299,6 @@ public class RouteProcessingService : BackgroundService
|
||||
if (minX.HasValue && minY.HasValue && maxX.HasValue && maxY.HasValue)
|
||||
{
|
||||
geofencePolygonBounds.Add((minX.Value, minY.Value, maxX.Value, maxY.Value));
|
||||
_logger.LogInformation("Route {RouteId}: Polygon {PolygonIndex} tile bounds: X=[{MinX}..{MaxX}], Y=[{MinY}..{MaxY}]",
|
||||
routeId, polygonIndex, minX.Value, maxX.Value, minY.Value, maxY.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,11 +426,6 @@ public class RouteProcessingService : BackgroundService
|
||||
var imageWidth = gridWidth * tileSizePixels;
|
||||
var imageHeight = gridHeight * tileSizePixels;
|
||||
|
||||
_logger.LogInformation("Stitching route map: {Width}x{Height} pixels (grid: {GridWidth}x{GridHeight} tiles)",
|
||||
imageWidth, imageHeight, gridWidth, gridHeight);
|
||||
_logger.LogInformation("Bounding box: top={MinY}, left={MinX}, bottom={MaxY}, right={MaxX}",
|
||||
minY, minX, maxY, maxX);
|
||||
|
||||
using var stitchedImage = new Image<Rgb24>(imageWidth, imageHeight);
|
||||
stitchedImage.Mutate(ctx => ctx.BackgroundColor(Color.Black));
|
||||
|
||||
@@ -507,14 +436,6 @@ public class RouteProcessingService : BackgroundService
|
||||
.ThenBy(t => t.TileX)
|
||||
.ToList();
|
||||
|
||||
_logger.LogInformation("Unique tiles to place: {Count}", uniqueTileCoords.Count);
|
||||
_logger.LogInformation("Sample tiles (first 5):");
|
||||
foreach (var sample in uniqueTileCoords.Take(5))
|
||||
{
|
||||
_logger.LogInformation(" Tile ({TileX}, {TileY}) from ({Lat:F6}, {Lon:F6})",
|
||||
sample.TileX, sample.TileY, sample.Latitude, sample.Longitude);
|
||||
}
|
||||
|
||||
int placedTiles = 0;
|
||||
int missingTiles = 0;
|
||||
|
||||
@@ -529,20 +450,8 @@ public class RouteProcessingService : BackgroundService
|
||||
{
|
||||
using var tileImage = await Image.LoadAsync<Rgb24>(tile.FilePath, cancellationToken);
|
||||
|
||||
if (tileImage.Width != tileSizePixels || tileImage.Height != tileSizePixels)
|
||||
{
|
||||
_logger.LogWarning("Tile {FilePath} has wrong size {Width}x{Height}, expected {ExpectedWidth}x{ExpectedHeight}",
|
||||
tile.FilePath, tileImage.Width, tileImage.Height, tileSizePixels, tileSizePixels);
|
||||
}
|
||||
|
||||
stitchedImage.Mutate(ctx => ctx.DrawImage(tileImage, new Point(destX, destY), 1f));
|
||||
placedTiles++;
|
||||
|
||||
if (placedTiles <= 3)
|
||||
{
|
||||
_logger.LogInformation("Placed tile {Count}: ({TileX},{TileY}) at pixel ({DestX},{DestY})",
|
||||
placedTiles, tile.TileX, tile.TileY, destX, destY);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -559,24 +468,15 @@ public class RouteProcessingService : BackgroundService
|
||||
|
||||
if (geofencePolygonBounds.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Drawing {Count} geofence polygon borders on image {Width}x{Height} (grid: minX={MinX}, minY={MinY})",
|
||||
geofencePolygonBounds.Count, imageWidth, imageHeight, minX, minY);
|
||||
|
||||
for (int i = 0; i < geofencePolygonBounds.Count; i++)
|
||||
{
|
||||
var (geoMinX, geoMinY, geoMaxX, geoMaxY) = geofencePolygonBounds[i];
|
||||
|
||||
_logger.LogInformation("Polygon {Index}: Tile range - X=[{MinX}..{MaxX}], Y=[{MinY}..{MaxY}]",
|
||||
i, geoMinX, geoMaxX, geoMinY, geoMaxY);
|
||||
|
||||
var x1 = (geoMinX - minX) * tileSizePixels;
|
||||
var y1 = (geoMinY - minY + 1) * tileSizePixels;
|
||||
var x2 = (geoMaxX - minX + 2) * tileSizePixels - 1;
|
||||
var y2 = (geoMaxY - minY + 1) * tileSizePixels - 1;
|
||||
|
||||
_logger.LogInformation("Polygon {Index}: Pixel coords before clipping - ({X1},{Y1}) to ({X2},{Y2})",
|
||||
i, x1, y1, x2, y2);
|
||||
|
||||
x1 = Math.Max(0, Math.Min(x1, imageWidth - 1));
|
||||
y1 = Math.Max(0, Math.Min(y1, imageHeight - 1));
|
||||
x2 = Math.Max(0, Math.Min(x2, imageWidth - 1));
|
||||
@@ -584,23 +484,11 @@ public class RouteProcessingService : BackgroundService
|
||||
|
||||
if (x1 >= 0 && y1 >= 0 && x2 < imageWidth && y2 < imageHeight && x2 > x1 && y2 > y1)
|
||||
{
|
||||
_logger.LogInformation("Polygon {Index}: Drawing border at pixel coords ({X1},{Y1}) to ({X2},{Y2})",
|
||||
i, x1, y1, x2, y2);
|
||||
|
||||
DrawRectangleBorder(stitchedImage, x1, y1, x2, y2, new Rgb24(255, 255, 0));
|
||||
|
||||
_logger.LogInformation("Polygon {Index}: Successfully drew geofence border", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Polygon {Index}: Border out of bounds or invalid - ({X1},{Y1}) to ({X2},{Y2}), image size: {Width}x{Height}",
|
||||
i, x1, y1, x2, y2, imageWidth, imageHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Drawing {Count} route point crosses on map", routePoints.Count);
|
||||
|
||||
foreach (var point in routePoints)
|
||||
{
|
||||
var geoPoint = new Common.DTO.GeoPoint { Lat = point.Latitude, Lon = point.Longitude };
|
||||
@@ -615,19 +503,7 @@ public class RouteProcessingService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Finished drawing route point crosses");
|
||||
|
||||
await stitchedImage.SaveAsJpegAsync(outputPath, cancellationToken);
|
||||
|
||||
var totalPossibleTiles = gridWidth * gridHeight;
|
||||
var uncoveredTiles = totalPossibleTiles - placedTiles - missingTiles;
|
||||
|
||||
_logger.LogInformation("Route map stitched: {OutputPath}", outputPath);
|
||||
_logger.LogInformation(" Tiles placed: {PlacedTiles}", placedTiles);
|
||||
_logger.LogInformation(" Tiles missing (file issues): {MissingTiles}", missingTiles);
|
||||
_logger.LogInformation(" Uncovered area (black): {UncoveredTiles} tiles", uncoveredTiles);
|
||||
_logger.LogInformation(" Total canvas: {TotalTiles} tiles ({GridWidth}x{GridHeight})",
|
||||
totalPossibleTiles, gridWidth, gridHeight);
|
||||
}
|
||||
|
||||
private List<DataAccess.Models.RegionEntity> MatchRegionsToRoutePoints(
|
||||
@@ -648,16 +524,6 @@ public class RouteProcessingService : BackgroundService
|
||||
{
|
||||
orderedRegions.Add(matchedRegion);
|
||||
availableRegions.Remove(matchedRegion);
|
||||
|
||||
var distance = CalculateDistance(point.Latitude, point.Longitude, matchedRegion.Latitude, matchedRegion.Longitude);
|
||||
_logger.LogInformation("Route {RouteId}: Matched route point Seq={Seq} ({Lat:F6},{Lon:F6}) to region {RegionId} ({RegLat:F6},{RegLon:F6}), distance={Distance:F2}m",
|
||||
routeId, point.SequenceNumber, point.Latitude, point.Longitude,
|
||||
matchedRegion.Id, matchedRegion.Latitude, matchedRegion.Longitude, distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("Route {RouteId}: No region found for route point Seq={Seq} ({Lat:F6},{Lon:F6})",
|
||||
routeId, point.SequenceNumber, point.Latitude, point.Longitude);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,12 +41,6 @@ public class RouteService : IRouteService
|
||||
throw new ArgumentException("Route name is required");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Creating route {RouteId} with {PointCount} original points and {GeofenceCount} geofences",
|
||||
request.Id, request.Points.Count, request.Geofences?.Polygons?.Count ?? 0);
|
||||
|
||||
_logger.LogInformation("Route {RouteId} - Input coordinates: First point ({Lat}, {Lon}), Last point ({LastLat}, {LastLon})",
|
||||
request.Id, request.Points[0].Latitude, request.Points[0].Longitude,
|
||||
request.Points[^1].Latitude, request.Points[^1].Longitude);
|
||||
|
||||
var allPoints = new List<RoutePointDto>();
|
||||
var totalDistance = 0.0;
|
||||
@@ -81,12 +75,6 @@ public class RouteService : IRouteService
|
||||
DistanceFromPrevious = distanceFromPrevious
|
||||
};
|
||||
|
||||
if (segmentIndex == 0 || segmentIndex == request.Points.Count - 1)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId} - Creating {PointType} point: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
request.Id, pointType, routePointDto.Latitude, routePointDto.Longitude);
|
||||
}
|
||||
|
||||
allPoints.Add(routePointDto);
|
||||
|
||||
if (!isEnd)
|
||||
@@ -97,9 +85,6 @@ public class RouteService : IRouteService
|
||||
|
||||
var intermediatePoints = GeoUtils.CalculateIntermediatePoints(startGeo, endGeo, MAX_POINT_SPACING_METERS);
|
||||
|
||||
_logger.LogInformation("Segment {SegmentIndex}: Adding {Count} intermediate points",
|
||||
segmentIndex, intermediatePoints.Count);
|
||||
|
||||
foreach (var intermediateGeo in intermediatePoints)
|
||||
{
|
||||
var lastAddedPoint = allPoints[^1];
|
||||
@@ -121,9 +106,6 @@ public class RouteService : IRouteService
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Total {TotalPoints} points (original + intermediate), distance {Distance:F2}m",
|
||||
request.Id, allPoints.Count, totalDistance);
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var routeEntity = new RouteEntity
|
||||
{
|
||||
@@ -155,17 +137,10 @@ public class RouteService : IRouteService
|
||||
CreatedAt = now
|
||||
}).ToList();
|
||||
|
||||
_logger.LogInformation("Route {RouteId} - Saving {Count} route points to DB. First: Lat={Lat:F12}, Lon={Lon:F12}, Last: Lat={LastLat:F12}, Lon={LastLon:F12}",
|
||||
request.Id, pointEntities.Count, pointEntities[0].Latitude, pointEntities[0].Longitude,
|
||||
pointEntities[^1].Latitude, pointEntities[^1].Longitude);
|
||||
|
||||
await _routeRepository.InsertRoutePointsAsync(pointEntities);
|
||||
|
||||
if (request.Geofences?.Polygons != null && request.Geofences.Polygons.Count > 0)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: Processing {GeofenceCount} geofence polygons",
|
||||
request.Id, request.Geofences.Polygons.Count);
|
||||
|
||||
for (int polygonIndex = 0; polygonIndex < request.Geofences.Polygons.Count; polygonIndex++)
|
||||
{
|
||||
var polygon = request.Geofences.Polygons[polygonIndex];
|
||||
@@ -196,16 +171,10 @@ public class RouteService : IRouteService
|
||||
|
||||
var geofenceRegions = CreateGeofenceRegionGrid(polygon.NorthWest, polygon.SouthEast, request.RegionSizeMeters);
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Polygon {PolygonIndex} - Created grid of {Count} regions to cover geofence area",
|
||||
request.Id, polygonIndex, geofenceRegions.Count);
|
||||
|
||||
foreach (var geofencePoint in geofenceRegions)
|
||||
{
|
||||
var geofenceRegionId = Guid.NewGuid();
|
||||
|
||||
_logger.LogInformation("Route {RouteId}: Polygon {PolygonIndex} - Requesting geofence region {RegionId} at ({Lat}, {Lon}) with size {Size}m",
|
||||
request.Id, polygonIndex, geofenceRegionId, geofencePoint.Lat, geofencePoint.Lon, request.RegionSizeMeters);
|
||||
|
||||
await _regionService.RequestRegionAsync(
|
||||
geofenceRegionId,
|
||||
geofencePoint.Lat,
|
||||
@@ -219,14 +188,6 @@ public class RouteService : IRouteService
|
||||
}
|
||||
}
|
||||
|
||||
if (request.RequestMaps)
|
||||
{
|
||||
_logger.LogInformation("Route {RouteId}: Maps requested. Regions will be processed sequentially by background service.",
|
||||
request.Id);
|
||||
}
|
||||
|
||||
_logger.LogInformation("Route {RouteId} created successfully", request.Id);
|
||||
|
||||
return new RouteResponse
|
||||
{
|
||||
Id = routeEntity.Id,
|
||||
|
||||
@@ -34,20 +34,7 @@ public class TileService : ITileService
|
||||
var existingTiles = await _tileRepository.GetTilesByRegionAsync(latitude, longitude, sizeMeters, zoomLevel);
|
||||
var existingTilesList = existingTiles.Where(t => t.Version == currentVersion).ToList();
|
||||
|
||||
_logger.LogInformation("Found {Count} existing tiles for region (version {Version})", existingTilesList.Count, currentVersion);
|
||||
|
||||
if (existingTilesList.Any())
|
||||
{
|
||||
_logger.LogInformation("Existing tiles in DB:");
|
||||
foreach (var et in existingTilesList)
|
||||
{
|
||||
_logger.LogInformation(" DB Tile: Lat={Lat:F12}, Lon={Lon:F12}, Zoom={Zoom}", et.Latitude, et.Longitude, et.ZoomLevel);
|
||||
}
|
||||
}
|
||||
|
||||
var centerPoint = new GeoPoint(latitude, longitude);
|
||||
_logger.LogInformation("TileService - Downloading tiles for center: Lat={Lat:F12}, Lon={Lon:F12}, Radius={Radius}m, Zoom={Zoom}",
|
||||
latitude, longitude, sizeMeters / 2, zoomLevel);
|
||||
|
||||
var downloadedTiles = await _downloader.GetTilesWithMetadataAsync(
|
||||
centerPoint,
|
||||
@@ -56,8 +43,6 @@ public class TileService : ITileService
|
||||
existingTilesList,
|
||||
cancellationToken);
|
||||
|
||||
_logger.LogInformation("Downloaded {Count} new tiles from Google", downloadedTiles.Count);
|
||||
|
||||
var result = new List<TileMetadata>();
|
||||
int reusedCount = existingTilesList.Count;
|
||||
int downloadedCount = downloadedTiles.Count;
|
||||
@@ -71,9 +56,6 @@ public class TileService : ITileService
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
_logger.LogInformation("TileService - Preparing to save tile: CenterLat={CenterLat:F12}, CenterLon={CenterLon:F12} from downloader",
|
||||
downloadedTile.CenterLatitude, downloadedTile.CenterLongitude);
|
||||
|
||||
var tileEntity = new TileEntity
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
@@ -90,16 +72,10 @@ public class TileService : ITileService
|
||||
UpdatedAt = now
|
||||
};
|
||||
|
||||
_logger.LogInformation("TileService - TileEntity before DB insert: Lat={Lat:F12}, Lon={Lon:F12}",
|
||||
tileEntity.Latitude, tileEntity.Longitude);
|
||||
|
||||
await _tileRepository.InsertAsync(tileEntity);
|
||||
_logger.LogInformation("Saved new tile {Id} at ({Lat:F12}, {Lon:F12}) version {Version}", tileEntity.Id, tileEntity.Latitude, tileEntity.Longitude, currentVersion);
|
||||
result.Add(MapToMetadata(tileEntity));
|
||||
}
|
||||
|
||||
_logger.LogInformation("Tile processing summary: {Reused} reused, {Downloaded} new", reusedCount, downloadedCount);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user