From 559ae48a742e334fc339311911e1dd1c6de879cf Mon Sep 17 00:00:00 2001 From: andrewbengordon Date: Thu, 9 Feb 2023 13:37:03 -0700 Subject: [PATCH 01/23] Finished adding seq monitoring --- docker-compose.yml | 12 ++ src/Mars.MissionControl/Game.cs | 1 + src/Mars.Web/Controllers/GameController.cs | 181 ++++++++++++--------- src/Mars.Web/Mars.Web.csproj | 4 + src/Mars.Web/MultiGameHoster.cs | 5 +- src/Mars.Web/Program.cs | 10 ++ 6 files changed, 136 insertions(+), 77 deletions(-) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..179a166 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: "3.0" +services: + seq: + image: datalust/seq:latest + ports: + - "5341:5341" + - "80:80" + - "45341:45341" + volumes: + - /datadrive:/data + environment: + - ACCEPT_EULA=Y \ No newline at end of file diff --git a/src/Mars.MissionControl/Game.cs b/src/Mars.MissionControl/Game.cs index f45bec2..f216dd3 100644 --- a/src/Mars.MissionControl/Game.cs +++ b/src/Mars.MissionControl/Game.cs @@ -247,6 +247,7 @@ public MoveResult MovePerseverance(PlayerToken token, Direction direction) if (player.PerseveranceLocation == TargetLocation)//you win! { + players.Remove(player.Token, out _); player = player with { WinningTime = DateTime.Now - GameStartedOn }; winners.Enqueue(player); diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index d662748..0244e92 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -1,4 +1,8 @@ -namespace Mars.Web.Controllers; +using Mars.MissionControl; +using Mars.Web.Pages; +using Microsoft.AspNetCore.Mvc; + +namespace Mars.Web.Controllers; [ApiController] [Route("[controller]")] @@ -6,11 +10,13 @@ public class GameController : ControllerBase { ConcurrentDictionary games; private readonly ConcurrentDictionary tokenMap; + private readonly ILogger logger; - public GameController(MultiGameHoster multiGameHoster) + public GameController(MultiGameHoster multiGameHoster, ILogger logger) { this.games = multiGameHoster.Games; this.tokenMap = multiGameHoster.TokenMap; + this.logger = logger; } /// @@ -24,34 +30,43 @@ public GameController(MultiGameHoster multiGameHoster) [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult Join(string gameId, string name) { - if (games.TryGetValue(gameId, out GameManager? gameManager)) + using (logger.BeginScope($"GameName: {name}, GameId: {gameId}")) { - try + if (games.TryGetValue(gameId, out GameManager? gameManager)) { - var joinResult = gameManager.Game.Join(name); - tokenMap.TryAdd(joinResult.Token.Value, gameId); + try + { + var joinResult = gameManager.Game.Join(name); + tokenMap.TryAdd(joinResult.Token.Value, gameId); + using (logger.BeginScope($"UserToken: {joinResult.Token.Value}")) + { + logger.LogInformation($"New User {joinResult.Token.Value} Joined"); + } - return new JoinResponse + return new JoinResponse + { + Token = joinResult.Token.Value, + StartingColumn = joinResult.PlayerLocation.Column, + StartingRow = joinResult.PlayerLocation.Row, + Neighbors = joinResult.Neighbors.ToDto(), + LowResolutionMap = joinResult.LowResolutionMap.ToDto(), + TargetRow = joinResult.TargetLocation.Row, + TargetColumn = joinResult.TargetLocation.Column, + Orientation = joinResult.Orientation.ToString() + }; + } + catch (TooManyPlayersException) { - Token = joinResult.Token.Value, - StartingColumn = joinResult.PlayerLocation.Column, - StartingRow = joinResult.PlayerLocation.Row, - Neighbors = joinResult.Neighbors.ToDto(), - LowResolutionMap = joinResult.LowResolutionMap.ToDto(), - TargetRow = joinResult.TargetLocation.Row, - TargetColumn = joinResult.TargetLocation.Column, - Orientation = joinResult.Orientation.ToString() - }; + logger.LogError($"Too Many Players"); + return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); + } } - catch (TooManyPlayersException) + else { - return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); + logger.LogError("Bad Game ID"); + return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); } } - else - { - return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); - } } [HttpGet("[action]")] @@ -68,7 +83,7 @@ public ActionResult Status(string token) } } } - + logger.LogError("Unrecognized token"); return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } @@ -82,42 +97,49 @@ public ActionResult Status(string token) [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult MovePerseverance(string token, Direction direction) { - if (tokenMap.TryGetValue(token, out string? gameId)) + using (logger.BeginScope($"UserToken: {token}")) { - if (games.TryGetValue(gameId, out var gameManager)) + if (tokenMap.TryGetValue(token, out string? gameId)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + if (games.TryGetValue(gameId, out var gameManager)) { - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + { + logger.LogError("Unrecognized token"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogWarning("Unable to move Perserverance, invalid game state."); + return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); + } - try - { - var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); - return new MoveResponse + try { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - BatteryLevel = moveResult.BatteryLevel, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - Orientation = moveResult.Orientation.ToString() - }; - } - catch (Exception ex) - { - return Problem("Unable to move", statusCode: 400, title: ex.Message); + var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); + logger.LogInformation($"User {token} moved Perseverance {direction}. Move Result: {moveResult.Message}"); + return new MoveResponse + { + Row = moveResult.Location.Row, + Column = moveResult.Location.Column, + BatteryLevel = moveResult.BatteryLevel, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + Orientation = moveResult.Orientation.ToString() + }; + } + catch (Exception ex) + { + logger.LogWarning("Unable to move Perserverance"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); + } } } + logger.LogError("Unrecognized token on move request"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } - - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } /// @@ -131,40 +153,47 @@ public ActionResult MovePerseverance(string token, Direction direc [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult MoveIngenuity(string token, int destinationRow, int destinationColumn) { - if (tokenMap.TryGetValue(token, out string? gameId)) + using (logger.BeginScope($"UserToken: {token}")) { - if (games.TryGetValue(gameId, out var gameManager)) + if (tokenMap.TryGetValue(token, out string? gameId)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + if (games.TryGetValue(gameId, out var gameManager)) { - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + { + logger.LogError("Unrecognized token on move request"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogWarning("Unable to move Ingenuity"); + return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); + } - try - { - var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); - return new IngenuityMoveResponse + try { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - BatteryLevel = moveResult.BatteryLevel - }; - } - catch (Exception ex) - { - return Problem("Unable to move", statusCode: 400, title: ex.Message); + var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); + logger.LogInformation($"User {token} moved Ingenuity"); + return new IngenuityMoveResponse + { + Row = moveResult.Location.Row, + Column = moveResult.Location.Column, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + BatteryLevel = moveResult.BatteryLevel + }; + } + catch (Exception ex) + { + logger.LogWarning("Unable to move Ingenuity"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); + } } } + logger.LogError("Unrecognized token on move request"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } - - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } } diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 8910179..385f8dd 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -17,6 +17,10 @@ + + + + diff --git a/src/Mars.Web/MultiGameHoster.cs b/src/Mars.Web/MultiGameHoster.cs index 55653db..5e041fd 100644 --- a/src/Mars.Web/MultiGameHoster.cs +++ b/src/Mars.Web/MultiGameHoster.cs @@ -4,9 +4,10 @@ public class MultiGameHoster { - public MultiGameHoster(IMapProvider mapProvider) + public MultiGameHoster(IMapProvider mapProvider, ILogger logger) { ParsedMaps = new List(mapProvider.LoadMaps()); + this.logger = logger; } public void RaiseOldGamesPurged() => OldGamesPurged?.Invoke(this, EventArgs.Empty); @@ -18,6 +19,7 @@ public MultiGameHoster(IMapProvider mapProvider) private string nextGame = "a"; private object lockObject = new(); private readonly IWebHostEnvironment hostEnvironment; + private readonly ILogger logger; public string MakeNewGame() { @@ -27,6 +29,7 @@ public string MakeNewGame() Games.TryAdd(gameId, new GameManager(ParsedMaps)); nextGame = IncrementGameId(nextGame); + logger.LogInformation($"New Game Created: {gameId}"); return gameId; } } diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 8c16589..bc5ea4e 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -1,10 +1,20 @@ using Mars.Web; using Microsoft.OpenApi.Models; +using Serilog; +using Serilog.Exceptions; using System.Reflection; using System.Text.Json.Serialization; using System.Threading.RateLimiting; var builder = WebApplication.CreateBuilder(args); + +builder.Host.UseSerilog((c, l) => +{ + l.WriteTo.Console() + .Enrich.WithExceptionDetails() + .WriteTo.Seq("http://localhost:80"); +}); + builder.Services.AddApplicationInsightsTelemetry(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); From 21f621db1904b2a9ab33969d2337f6def8f0f40b Mon Sep 17 00:00:00 2001 From: Bridger Thompson Date: Mon, 13 Feb 2023 10:45:29 -0700 Subject: [PATCH 02/23] api logging --- src/Mars.Web/Controllers/GameController.cs | 63 ++++++++++++++-------- 1 file changed, 40 insertions(+), 23 deletions(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index d662748..892e6a5 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -6,12 +6,14 @@ public class GameController : ControllerBase { ConcurrentDictionary games; private readonly ConcurrentDictionary tokenMap; + private readonly ILogger logger; - public GameController(MultiGameHoster multiGameHoster) + public GameController(MultiGameHoster multiGameHoster, ILogger logger) { this.games = multiGameHoster.Games; this.tokenMap = multiGameHoster.TokenMap; - } + this.logger = logger; + } /// /// Join an existing game. You can join in the 'Joining' state, or in the 'Playing' state. @@ -30,8 +32,9 @@ public ActionResult Join(string gameId, string name) { var joinResult = gameManager.Game.Join(name); tokenMap.TryAdd(joinResult.Token.Value, gameId); + logger.LogInformation($"Player {name} joined game {gameId}"); - return new JoinResponse + return new JoinResponse { Token = joinResult.Token.Value, StartingColumn = joinResult.PlayerLocation.Column, @@ -44,13 +47,15 @@ public ActionResult Join(string gameId, string name) }; } catch (TooManyPlayersException) - { - return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); + { + logger.LogError($"Player {name} failed to join game {gameId}. Too many players"); + return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); } } else - { - return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); + { + logger.LogError($"Player {name} failed to join game {gameId}. Game id not found"); + return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); } } @@ -69,7 +74,7 @@ public ActionResult Status(string token) } } - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + return BadToken(token); } /// @@ -89,13 +94,13 @@ public ActionResult MovePerseverance(string token, Direction direc PlayerToken? playerToken; if (!gameManager.Game.TryTranslateToken(token, out playerToken)) { - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + return BadToken(token); } if (gameManager.Game.GameState != GameState.Playing) { - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + return CantMove(ex.Message); + } try { @@ -112,13 +117,13 @@ public ActionResult MovePerseverance(string token, Direction direc } catch (Exception ex) { - return Problem("Unable to move", statusCode: 400, title: ex.Message); - } + return CantMove(ex.Message); + } } } - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + return BadToken(token); + } /// /// Move the Ingenuity helicopter. @@ -138,13 +143,13 @@ public ActionResult MoveIngenuity(string token, int desti PlayerToken? playerToken; if (!gameManager.Game.TryTranslateToken(token, out playerToken)) { - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + return BadToken(token); + } if (gameManager.Game.GameState != GameState.Playing) { - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + return CantMove("Game not in the Playing state"); + } try { @@ -160,11 +165,23 @@ public ActionResult MoveIngenuity(string token, int desti } catch (Exception ex) { - return Problem("Unable to move", statusCode: 400, title: ex.Message); - } + return CantMove(ex.Message); + } } } - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + return BadToken(token); + } + + public ObjectResult BadToken(string token) + { + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } + + public ObjectResult CantMove(string message) + { + logger.LogError($"Could not move: {message}"); + return Problem("Unable to move", statusCode: 400, title: message); + } } From 64c5b9e21a0803871f97bdc3b5e71f70ed22abee Mon Sep 17 00:00:00 2001 From: garv5014 Date: Mon, 13 Feb 2023 10:49:05 -0700 Subject: [PATCH 03/23] porblem details --- src/Mars.Web/Mars.Web.csproj | 1 + src/Mars.Web/Program.cs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 8910179..915de6a 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 8c16589..f8e0421 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Text.Json.Serialization; using System.Threading.RateLimiting; +using Hellang.Middleware.ProblemDetails; var builder = WebApplication.CreateBuilder(args); builder.Services.AddApplicationInsightsTelemetry(); @@ -13,6 +14,13 @@ options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); }); builder.Services.AddEndpointsApiExplorer(); + +builder.Services.AddProblemDetails(opts => +{ + opts.IncludeExceptionDetails = (ctx, ex) => false; +} +); + builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Mars Rover", Version = "v1" }); From cdaa8eb2e573b08d1422c1d4e38220e53ea1a1f7 Mon Sep 17 00:00:00 2001 From: garv5014 Date: Mon, 13 Feb 2023 12:38:23 -0700 Subject: [PATCH 04/23] added scopes to a few areas --- src/Mars.Web/Controllers/GameController.cs | 167 +++++++++++---------- src/Mars.Web/Mars.Web.csproj | 5 +- src/Mars.Web/Program.cs | 11 ++ src/Mars.Web/appsettings.json | 35 +++-- 4 files changed, 125 insertions(+), 93 deletions(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index 892e6a5..5f35bf7 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -6,14 +6,14 @@ public class GameController : ControllerBase { ConcurrentDictionary games; private readonly ConcurrentDictionary tokenMap; - private readonly ILogger logger; + private readonly ILogger logger; - public GameController(MultiGameHoster multiGameHoster, ILogger logger) + public GameController(MultiGameHoster multiGameHoster, ILogger logger) { this.games = multiGameHoster.Games; this.tokenMap = multiGameHoster.TokenMap; - this.logger = logger; - } + this.logger = logger; + } /// /// Join an existing game. You can join in the 'Joining' state, or in the 'Playing' state. @@ -30,11 +30,14 @@ public ActionResult Join(string gameId, string name) { try { + var joinResult = gameManager.Game.Join(name); tokenMap.TryAdd(joinResult.Token.Value, gameId); - logger.LogInformation($"Player {name} joined game {gameId}"); - - return new JoinResponse + using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) + { + logger.LogInformation($"Player {name} joined game {gameId}"); + } + return new JoinResponse { Token = joinResult.Token.Value, StartingColumn = joinResult.PlayerLocation.Column, @@ -47,15 +50,15 @@ public ActionResult Join(string gameId, string name) }; } catch (TooManyPlayersException) - { - logger.LogError($"Player {name} failed to join game {gameId}. Too many players"); - return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); + { + logger.LogError($"Player {name} failed to join game {gameId}. Too many players"); + return Problem("Cannot join game, too many players.", statusCode: 400, title: "Too many players"); } } else - { - logger.LogError($"Player {name} failed to join game {gameId}. Game id not found"); - return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); + { + logger.LogError($"Player {name} failed to join game {gameId}. Game id not found"); + return Problem("Unrecognized game id.", statusCode: 400, title: "Bad Game ID"); } } @@ -73,8 +76,11 @@ public ActionResult Status(string token) } } } - - return BadToken(token); + using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) + { + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } } /// @@ -89,41 +95,48 @@ public ActionResult MovePerseverance(string token, Direction direc { if (tokenMap.TryGetValue(token, out string? gameId)) { - if (games.TryGetValue(gameId, out var gameManager)) + using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + if (games.TryGetValue(gameId, out var gameManager)) { - return BadToken(token); - } + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + { + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - return CantMove(ex.Message); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogError($"Could not move: Game not in Playing state."); + return Problem("Unable to move", statusCode: 400, title: "Game not in Playing state."); + } - try - { - var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); - return new MoveResponse + try { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - BatteryLevel = moveResult.BatteryLevel, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - Orientation = moveResult.Orientation.ToString() - }; + var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); + return new MoveResponse + { + Row = moveResult.Location.Row, + Column = moveResult.Location.Column, + BatteryLevel = moveResult.BatteryLevel, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + Orientation = moveResult.Orientation.ToString() + }; + } + catch (Exception ex) + { + logger.LogError($"Could not move: {ex.Message}"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); + } } - catch (Exception ex) - { - return CantMove(ex.Message); - } + } } - - return BadToken(token); - } + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } /// /// Move the Ingenuity helicopter. @@ -138,50 +151,44 @@ public ActionResult MoveIngenuity(string token, int desti { if (tokenMap.TryGetValue(token, out string? gameId)) { - if (games.TryGetValue(gameId, out var gameManager)) + using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + if (games.TryGetValue(gameId, out var gameManager)) { - return BadToken(token); - } + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) + { + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - return CantMove("Game not in the Playing state"); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogError($"Could not move: Game not in Playing state."); + return Problem("Unable to move", statusCode: 400, title: "Game not in Playing state."); + } - try - { - var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); - return new IngenuityMoveResponse + try { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - BatteryLevel = moveResult.BatteryLevel - }; + var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); + return new IngenuityMoveResponse + { + Row = moveResult.Location.Row, + Column = moveResult.Location.Column, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + BatteryLevel = moveResult.BatteryLevel + }; + } + catch (Exception ex) + { + logger.LogError($"Could not move: {ex.Message}"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); + } } - catch (Exception ex) - { - return CantMove(ex.Message); - } } } - - return BadToken(token); - } - - public ObjectResult BadToken(string token) - { - logger.LogError($"Unrecogized token {token}"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } - - public ObjectResult CantMove(string message) - { - logger.LogError($"Could not move: {message}"); - return Problem("Unable to move", statusCode: 400, title: message); - } + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } } diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 915de6a..407f955 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -16,8 +16,11 @@ - + + + + diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index f8e0421..1298c7a 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -4,6 +4,8 @@ using System.Text.Json.Serialization; using System.Threading.RateLimiting; using Hellang.Middleware.ProblemDetails; +using Serilog; +using Serilog.Exceptions; var builder = WebApplication.CreateBuilder(args); builder.Services.AddApplicationInsightsTelemetry(); @@ -15,6 +17,15 @@ }); builder.Services.AddEndpointsApiExplorer(); +builder.Host.UseSerilog( (context, loggerConfig) => + { + loggerConfig.WriteTo.Console() + .Enrich.WithExceptionDetails() + .WriteTo.Seq("http://localhost:5340"); + } + + ); + builder.Services.AddProblemDetails(opts => { opts.IncludeExceptionDetails = (ctx, ex) => false; diff --git a/src/Mars.Web/appsettings.json b/src/Mars.Web/appsettings.json index 735cde4..1b3be71 100644 --- a/src/Mars.Web/appsettings.json +++ b/src/Mars.Web/appsettings.json @@ -1,12 +1,23 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - } - }, - "AllowedHosts": "*", - "GAME_PASSWORD": "password", - "CleanupFrequencyMinutes": "60", - "ApiLimitPerSecond": "10" -} +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + }, + "Console": { + "FormatterName": "json", + "FormatterOptions": { + "SingleLine": true, + "IncludeScopes": true, + "UseUtcTimestamp": true, + "TimestampFormat": "HH:mm:ss", + "JsonWriterOptions": { "Indented": true + } + } + } + }, + "AllowedHosts": "*", + "GAME_PASSWORD": "password", + "CleanupFrequencyMinutes": "60", + "ApiLimitPerSecond": "10" +} From 1c98353aa9e19b6f3af39e235e14cbf7e96bbda3 Mon Sep 17 00:00:00 2001 From: "Breanna.nesbit" Date: Mon, 13 Feb 2023 17:35:23 -0700 Subject: [PATCH 05/23] Breanna's and Aubrey's logs --- src/Mars.MissionControl/Game.cs | 17 +++++++++++++++-- src/Mars.MissionControl/Helpers.cs | 10 ++++++++-- .../Mars.MissionControl.csproj | 4 ++++ src/Mars.Web/GameManager.cs | 12 +++++++++--- src/Mars.Web/Mars.Web.csproj | 3 +++ src/Mars.Web/MultiGameHoster.cs | 7 +++++-- src/Mars.Web/Program.cs | 15 +++++++++++++++ 7 files changed, 59 insertions(+), 9 deletions(-) diff --git a/src/Mars.MissionControl/Game.cs b/src/Mars.MissionControl/Game.cs index 7cc7abe..e426295 100644 --- a/src/Mars.MissionControl/Game.cs +++ b/src/Mars.MissionControl/Game.cs @@ -1,9 +1,10 @@ -using System.Collections.ObjectModel; +using Microsoft.Extensions.Logging; +using System.Collections.ObjectModel; namespace Mars.MissionControl; public class Game : IDisposable { - public Game(GameStartOptions startOptions) + public Game(GameStartOptions startOptions, ILogger logger) { GameState = GameState.Joining; Board = new Board(startOptions.Map); @@ -13,8 +14,12 @@ public Game(GameStartOptions startOptions) IngenuityVisibilityRadius = startOptions.IngenuityVisibilityRadius; StartingBatteryLevel = startOptions.StartingBatteryLevel; IngenuityStartingBatteryLevel = Board.Width * 2 + Board.Height * 2; + this.logger= logger; + } + + public int MapNumber => Board.MapNumber; public Location TargetLocation { get; private set; } @@ -49,11 +54,13 @@ public JoinResult Join(string playerName) { if (GameState != GameState.Joining && GameState != GameState.Playing) { + logger.LogError("Game wasn't detected"); throw new InvalidGameStateException(); } var player = new Player(playerName); var startingLocation = Board.PlaceNewPlayer(player); + logger.LogInformation("New player came into existance and started at location ({x}, {y}) ", startingLocation.X, startingLocation.Y); player = player with { BatteryLevel = StartingBatteryLevel, @@ -65,6 +72,7 @@ public JoinResult Join(string playerName) if (!players.TryAdd(player.Token, player) || !playerTokenCache.TryAdd(player.Token.Value, player.Token)) { + logger.LogError($"Player {player.Token.Value} couldn't be added"); throw new Exception("Unable to add new player...that token already exists?!"); } @@ -90,6 +98,8 @@ private static Orientation getRandomOrientation() public GameState GameState { get; set; } public Board Board { get; private set; } private Timer? rechargeTimer; + private readonly ILogger logger; + public DateTime GameStartedOn { get; private set; } public void PlayGame() => PlayGame(new GamePlayOptions()); @@ -169,6 +179,7 @@ public IngenuityMoveResult MoveIngenuity(PlayerToken token, Location destination } raiseStateChange(); + logger.LogInformation("player: {name} moved helicopter correctly and moved to location: {loc}", player.Name, player.IngenuityLocation); return new IngenuityMoveResult( player.IngenuityLocation, @@ -176,6 +187,7 @@ public IngenuityMoveResult MoveIngenuity(PlayerToken token, Location destination Board.GetNeighbors(player.IngenuityLocation, IngenuityVisibilityRadius), message ?? throw new Exception("Game message not set?!") ); + } public MoveResult MovePerseverance(PlayerToken token, Direction direction) @@ -253,6 +265,7 @@ public MoveResult MovePerseverance(PlayerToken token, Direction direction) } raiseStateChange(); + logger.LogInformation("player: {0} moved rover correctly", player.Name); return new MoveResult( player.PerseveranceLocation, diff --git a/src/Mars.MissionControl/Helpers.cs b/src/Mars.MissionControl/Helpers.cs index 98c1072..7c4dc8d 100644 --- a/src/Mars.MissionControl/Helpers.cs +++ b/src/Mars.MissionControl/Helpers.cs @@ -1,9 +1,14 @@ -namespace Mars.MissionControl; +using Microsoft.Extensions.Logging; +using System.Runtime.CompilerServices; + +namespace Mars.MissionControl; public static class Helpers { + private static ILogger logger; public static Map CreateMap(int height, int width) { + var cells = new List(); for (int x = 0; x < width; x++) { @@ -30,11 +35,12 @@ public static Game CreateGame(int height, int width) public static Game CreateGame(Map map) { + var startOptions = new GameStartOptions { Map = map }; - var game = new Game(startOptions); + var game = new Game(startOptions, logger); return game; } diff --git a/src/Mars.MissionControl/Mars.MissionControl.csproj b/src/Mars.MissionControl/Mars.MissionControl.csproj index a1ed5b3..f4b2e01 100644 --- a/src/Mars.MissionControl/Mars.MissionControl.csproj +++ b/src/Mars.MissionControl/Mars.MissionControl.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/src/Mars.Web/GameManager.cs b/src/Mars.Web/GameManager.cs index 6c13148..f49fb00 100644 --- a/src/Mars.Web/GameManager.cs +++ b/src/Mars.Web/GameManager.cs @@ -4,7 +4,9 @@ namespace Mars.Web; public class GameManager { - public GameManager(List maps) + private readonly ILogger logger; + + public GameManager(List maps, ILogger logger) { CreatedOn = DateTime.Now; GameStartOptions = new GameStartOptions @@ -12,7 +14,7 @@ public GameManager(List maps) Map = maps[0], }; this.Maps = maps; - + this.logger = logger; StartNewGame(GameStartOptions); } public IReadOnlyList Maps { get; } @@ -50,12 +52,16 @@ public void StartNewGame(GameStartOptions startOptions) if (Game != null) { Game.GameStateChanged -= Game_GameStateChanged; + var playoptions = Game.GamePlayOptions; Game.Dispose(); + logger.LogWarning("Game ending {0}", playoptions); + } NewGameStarted?.Invoke(this, new EventArgs()); - Game = new Game(startOptions); + Game = new Game(startOptions, logger); + logger.LogInformation("New game created"); GameStateChanged?.Invoke(this, EventArgs.Empty); //subscribe to new event diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 8910179..fc67c6f 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -17,6 +17,9 @@ + + + diff --git a/src/Mars.Web/MultiGameHoster.cs b/src/Mars.Web/MultiGameHoster.cs index 4a124e8..f4c226c 100644 --- a/src/Mars.Web/MultiGameHoster.cs +++ b/src/Mars.Web/MultiGameHoster.cs @@ -4,9 +4,10 @@ public class MultiGameHoster { - public MultiGameHoster(IMapProvider mapProvider) + public MultiGameHoster(IMapProvider mapProvider, ILogger log) { ParsedMaps = new List(mapProvider.LoadMaps()); + this.log = log; } public void RaiseOldGamesPurged() => OldGamesPurged?.Invoke(this, EventArgs.Empty); @@ -18,13 +19,15 @@ public MultiGameHoster(IMapProvider mapProvider) private string nextGame = "a"; private object lockObject = new(); private readonly IWebHostEnvironment hostEnvironment; + private readonly ILogger log; public string MakeNewGame() { + lock (lockObject) { var gameId = nextGame; - Games.TryAdd(gameId, new GameManager(ParsedMaps)); + Games.TryAdd(gameId, new GameManager(ParsedMaps, log)); nextGame = IncrementGameId(nextGame); return gameId; diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 8c16589..bddeb67 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -1,9 +1,13 @@ using Mars.Web; using Microsoft.OpenApi.Models; +using Serilog; +using Serilog.Exceptions; using System.Reflection; +using System.Runtime.InteropServices; using System.Text.Json.Serialization; using System.Threading.RateLimiting; + var builder = WebApplication.CreateBuilder(args); builder.Services.AddApplicationInsightsTelemetry(); builder.Services.AddRazorPages(); @@ -20,6 +24,17 @@ c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); }); + +builder.Host.UseSerilog((context, loggerConfig) => +{ + loggerConfig.WriteTo.Console() + .Enrich.WithExceptionDetails() + .WriteTo.Seq("http://localhost:5341"); +}); + + + + builder.Services.AddSingleton(); builder.Services.AddSingleton(); From 3a2d5158083e0da4cebf82b7a4cee9d1830ceabb Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Tue, 14 Feb 2023 10:32:23 -0700 Subject: [PATCH 06/23] add docker support --- src/.dockerignore | 25 +++++++++++++++ src/Mars.Web/Dockerfile | 24 ++++++++++++++ src/Mars.Web/Mars.Web.csproj | 2 ++ src/Mars.Web/Properties/launchSettings.json | 35 +++++++++++++-------- 4 files changed, 73 insertions(+), 13 deletions(-) create mode 100644 src/.dockerignore create mode 100644 src/Mars.Web/Dockerfile diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Mars.Web/Dockerfile b/src/Mars.Web/Dockerfile new file mode 100644 index 0000000..04e40d9 --- /dev/null +++ b/src/Mars.Web/Dockerfile @@ -0,0 +1,24 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /src +COPY ["Mars.Web/Mars.Web.csproj", "Mars.Web/"] +COPY ["Mars.MissionControl/Mars.MissionControl.csproj", "Mars.MissionControl/"] +COPY ["Mars.Web.Types/Mars.Web.Types.csproj", "Mars.Web.Types/"] +RUN dotnet restore "Mars.Web/Mars.Web.csproj" +COPY . . +WORKDIR "/src/Mars.Web" +RUN dotnet build "Mars.Web.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Mars.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Mars.Web.dll"] \ No newline at end of file diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 8910179..2931021 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -6,6 +6,7 @@ enable 1c3d0055-a8d7-4fc1-a151-6dbc7e1b1d38 True + Linux @@ -17,6 +18,7 @@ + diff --git a/src/Mars.Web/Properties/launchSettings.json b/src/Mars.Web/Properties/launchSettings.json index 29d99f9..9f091b1 100644 --- a/src/Mars.Web/Properties/launchSettings.json +++ b/src/Mars.Web/Properties/launchSettings.json @@ -1,28 +1,22 @@ { - "iisSettings": { - "iisExpress": { - "applicationUrl": "http://localhost:26097", - "sslPort": 44335 - } - }, "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5110" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7287;http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7287;http://localhost:5110" }, "IIS Express": { "commandName": "IISExpress", @@ -30,6 +24,21 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "publishAllPorts": true, + "useSSL": true + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:26097", + "sslPort": 44335 } } -} +} \ No newline at end of file From ffe9f2cb6b9a06f962ce1fa48273185de2521f43 Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Tue, 14 Feb 2023 10:38:48 -0700 Subject: [PATCH 07/23] add docker compose --- src/Mars.Web/Mars.Web.csproj | 1 + src/MarsRover.sln | 6 ++++++ src/docker-compose.dcproj | 18 ++++++++++++++++++ src/docker-compose.override.yml | 13 +++++++++++++ src/docker-compose.yml | 19 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/docker-compose.dcproj create mode 100644 src/docker-compose.override.yml create mode 100644 src/docker-compose.yml diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 2931021..89f4619 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -7,6 +7,7 @@ 1c3d0055-a8d7-4fc1-a151-6dbc7e1b1d38 True Linux + ..\docker-compose.dcproj diff --git a/src/MarsRover.sln b/src/MarsRover.sln index b76f6cf..950cd82 100644 --- a/src/MarsRover.sln +++ b/src/MarsRover.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Tests", "Mars.Web. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Types", "Mars.Web.Types\Mars.Web.Types.csproj", "{A92385B4-ADF1-4201-970E-915A57426B5D}" EndProject +Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{A037F803-1212-4594-AA2D-3967B97CC735}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {A92385B4-ADF1-4201-970E-915A57426B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {A037F803-1212-4594-AA2D-3967B97CC735}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A037F803-1212-4594-AA2D-3967B97CC735}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A037F803-1212-4594-AA2D-3967B97CC735}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A037F803-1212-4594-AA2D-3967B97CC735}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/docker-compose.dcproj b/src/docker-compose.dcproj new file mode 100644 index 0000000..478a8fa --- /dev/null +++ b/src/docker-compose.dcproj @@ -0,0 +1,18 @@ + + + + 2.1 + Linux + a037f803-1212-4594-aa2d-3967b97cc735 + LaunchBrowser + {Scheme}://localhost:{ServicePort} + mars.web + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml new file mode 100644 index 0000000..e5856f2 --- /dev/null +++ b/src/docker-compose.override.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + mars.web: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:443;http://+:80 + ports: + - "80" + - "443" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/src/docker-compose.yml b/src/docker-compose.yml new file mode 100644 index 0000000..a91955b --- /dev/null +++ b/src/docker-compose.yml @@ -0,0 +1,19 @@ +version: '3.4' + +services: + mars.web: + image: ${DOCKER_REGISTRY-}marsweb + build: + context: . + dockerfile: Mars.Web/Dockerfile + + seq: + image: datalust/seq:latest + ports: + - "5341:5341" + - "80:80" + - "45341:45341" + volumes: + - /datadrive:/data + environment: + - ACCEPT_EULA=Y \ No newline at end of file From 7552cc364cddd5d983c2103706006745cc877fbf Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Tue, 14 Feb 2023 10:42:19 -0700 Subject: [PATCH 08/23] add container name, change ports --- src/docker-compose.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/docker-compose.yml b/src/docker-compose.yml index a91955b..24fd943 100644 --- a/src/docker-compose.yml +++ b/src/docker-compose.yml @@ -8,10 +8,12 @@ services: dockerfile: Mars.Web/Dockerfile seq: + container_name: seq image: datalust/seq:latest ports: - - "5341:5341" - - "80:80" + # Host Port : Container Port + - "8888:5341" + - "8085:80" - "45341:45341" volumes: - /datadrive:/data From fefaf0d560f444c7d12610ef6327b27462e755f8 Mon Sep 17 00:00:00 2001 From: andrewbengordon Date: Tue, 14 Feb 2023 12:09:42 -0700 Subject: [PATCH 09/23] Fixed API controller, added docker support --- src/.dockerignore | 25 ++++ src/Mars.Web/Controllers/GameController.cs | 144 +++++++++----------- src/Mars.Web/Dockerfile | 24 ++++ src/Mars.Web/Mars.Web.csproj | 3 + src/Mars.Web/Program.cs | 2 +- src/Mars.Web/Properties/launchSettings.json | 35 +++-- src/MarsRover.sln | 6 + src/docker-compose.dcproj | 18 +++ src/docker-compose.override.yml | 13 ++ src/docker-compose.yml | 17 +++ 10 files changed, 197 insertions(+), 90 deletions(-) create mode 100644 src/.dockerignore create mode 100644 src/Mars.Web/Dockerfile create mode 100644 src/docker-compose.dcproj create mode 100644 src/docker-compose.override.yml create mode 100644 src/docker-compose.yml diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index 1f2b5da..cbcda13 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -46,12 +46,12 @@ public ActionResult Join(string gameId, string name) return new JoinResponse { Token = joinResult.Token.Value, - StartingColumn = joinResult.PlayerLocation.Column, - StartingRow = joinResult.PlayerLocation.Row, + StartingX = joinResult.PlayerLocation.X, + StartingY = joinResult.PlayerLocation.Y, Neighbors = joinResult.Neighbors.ToDto(), LowResolutionMap = joinResult.LowResolutionMap.ToDto(), - TargetRow = joinResult.TargetLocation.Row, - TargetColumn = joinResult.TargetLocation.Column, + TargetX = joinResult.TargetLocation.X, + TargetY = joinResult.TargetLocation.Y, Orientation = joinResult.Orientation.ToString() }; } @@ -74,20 +74,18 @@ public ActionResult Join(string gameId, string name) [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult Status(string token) { - if (tokenMap.TryGetValue(token, out string? gameId) && + using (logger.BeginScope($"UserToken: {token}")) + { + if (tokenMap.TryGetValue(token, out string? gameId) && games.TryGetValue(gameId, out var gameManager) && gameManager.Game.TryTranslateToken(token, out _)) - { - if (games.TryGetValue(gameId, out var gameManager)) { - if (gameManager.Game.TryTranslateToken(token, out _)) - { - return new StatusResponse { Status = gameManager.Game.GameState.ToString() }; - } + logger.LogInformation("Getting game status"); + return new StatusResponse { Status = gameManager.Game.GameState.ToString() }; } + logger.LogError("Unrecognized token"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } - logger.LogError("Unrecognized token"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } /// @@ -99,49 +97,46 @@ public ActionResult Status(string token) [HttpGet("[action]")] [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(PerseveranceMoveResponse))] [ProducesResponseType(StatusCodes.Status400BadRequest)] - public ActionResult MovePerseverance(string token, Direction direction) + public ActionResult MovePerseverance(string token, Direction direction) { using (logger.BeginScope($"UserToken: {token}")) { - if (tokenMap.TryGetValue(token, out string? gameId)) + if (tokenMap.TryGetValue(token, out string? gameId) && games.TryGetValue(gameId, out var gameManager)) { - if (games.TryGetValue(gameId, out var gameManager)) + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) - { - logger.LogError("Unrecognized token"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + logger.LogError("Unrecognized token"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - logger.LogWarning("Unable to move Perserverance, invalid game state."); - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogWarning("Unable to move Perserverance, invalid game state."); + return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); + } - try - { - var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); - logger.LogInformation($"User {token} moved Perseverance {direction}. Move Result: {moveResult.Message}"); - return new MoveResponse - { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - BatteryLevel = moveResult.BatteryLevel, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - Orientation = moveResult.Orientation.ToString() - }; - } - catch (Exception ex) + try + { + var moveResult = gameManager.Game.MovePerseverance(playerToken!, direction); + logger.LogInformation($"User {token} moved Perseverance {direction}. Move Result: {moveResult.Message}"); + return new PerseveranceMoveResponse { - logger.LogWarning("Unable to move Perserverance"); - return Problem("Unable to move", statusCode: 400, title: ex.Message); - } + X = moveResult.Location.X, + Y = moveResult.Location.Y, + BatteryLevel = moveResult.BatteryLevel, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + Orientation = moveResult.Orientation.ToString() + }; + } + catch (Exception ex) + { + logger.LogWarning("Unable to move Perserverance"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); } } - logger.LogError("Unrecognized token on move request"); + logger.LogError("Unrecognized token"); return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } } @@ -160,41 +155,38 @@ public ActionResult MoveIngenuity(string token, int desti { using (logger.BeginScope($"UserToken: {token}")) { - if (tokenMap.TryGetValue(token, out string? gameId)) + if (tokenMap.TryGetValue(token, out string? gameId) && games.TryGetValue(gameId, out var gameManager)) { - if (games.TryGetValue(gameId, out var gameManager)) + PlayerToken? playerToken; + if (!gameManager.Game.TryTranslateToken(token, out playerToken)) { - PlayerToken? playerToken; - if (!gameManager.Game.TryTranslateToken(token, out playerToken)) - { - logger.LogError("Unrecognized token on move request"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); - } + logger.LogError("Unrecognized token on move request"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); + } - if (gameManager.Game.GameState != GameState.Playing) - { - logger.LogWarning("Unable to move Ingenuity"); - return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); - } + if (gameManager.Game.GameState != GameState.Playing) + { + logger.LogWarning("Unable to move Ingenuity, invalid game state"); + return Problem("Unable to move, invalid game state.", statusCode: 400, title: "Game not in the Playing state."); + } - try - { - var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); - logger.LogInformation($"User {token} moved Ingenuity"); - return new IngenuityMoveResponse - { - Row = moveResult.Location.Row, - Column = moveResult.Location.Column, - Neighbors = moveResult.Neighbors.ToDto(), - Message = moveResult.Message, - BatteryLevel = moveResult.BatteryLevel - }; - } - catch (Exception ex) + try + { + var moveResult = gameManager.Game.MoveIngenuity(playerToken!, new Location(destinationRow, destinationColumn)); + logger.LogInformation($"User {token} moved Ingenuity"); + return new IngenuityMoveResponse { - logger.LogWarning("Unable to move Ingenuity"); - return Problem("Unable to move", statusCode: 400, title: ex.Message); - } + X = moveResult.Location.X, + Y = moveResult.Location.Y, + Neighbors = moveResult.Neighbors.ToDto(), + Message = moveResult.Message, + BatteryLevel = moveResult.BatteryLevel + }; + } + catch (Exception ex) + { + logger.LogWarning("Unable to move Ingenuity"); + return Problem("Unable to move", statusCode: 400, title: ex.Message); } } logger.LogError("Unrecognized token on move request"); diff --git a/src/Mars.Web/Dockerfile b/src/Mars.Web/Dockerfile new file mode 100644 index 0000000..04e40d9 --- /dev/null +++ b/src/Mars.Web/Dockerfile @@ -0,0 +1,24 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /src +COPY ["Mars.Web/Mars.Web.csproj", "Mars.Web/"] +COPY ["Mars.MissionControl/Mars.MissionControl.csproj", "Mars.MissionControl/"] +COPY ["Mars.Web.Types/Mars.Web.Types.csproj", "Mars.Web.Types/"] +RUN dotnet restore "Mars.Web/Mars.Web.csproj" +COPY . . +WORKDIR "/src/Mars.Web" +RUN dotnet build "Mars.Web.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Mars.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Mars.Web.dll"] \ No newline at end of file diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 385f8dd..98afa6f 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -6,6 +6,8 @@ enable 1c3d0055-a8d7-4fc1-a151-6dbc7e1b1d38 True + Linux + ..\docker-compose.dcproj @@ -17,6 +19,7 @@ + diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index bc5ea4e..14502a8 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -12,7 +12,7 @@ { l.WriteTo.Console() .Enrich.WithExceptionDetails() - .WriteTo.Seq("http://localhost:80"); + .WriteTo.Seq("http://seq"); }); builder.Services.AddApplicationInsightsTelemetry(); diff --git a/src/Mars.Web/Properties/launchSettings.json b/src/Mars.Web/Properties/launchSettings.json index 29d99f9..9f091b1 100644 --- a/src/Mars.Web/Properties/launchSettings.json +++ b/src/Mars.Web/Properties/launchSettings.json @@ -1,28 +1,22 @@ { - "iisSettings": { - "iisExpress": { - "applicationUrl": "http://localhost:26097", - "sslPort": 44335 - } - }, "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5110" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7287;http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7287;http://localhost:5110" }, "IIS Express": { "commandName": "IISExpress", @@ -30,6 +24,21 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "publishAllPorts": true, + "useSSL": true + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:26097", + "sslPort": 44335 } } -} +} \ No newline at end of file diff --git a/src/MarsRover.sln b/src/MarsRover.sln index b76f6cf..5327fbe 100644 --- a/src/MarsRover.sln +++ b/src/MarsRover.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Tests", "Mars.Web. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Types", "Mars.Web.Types\Mars.Web.Types.csproj", "{A92385B4-ADF1-4201-970E-915A57426B5D}" EndProject +Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{21739252-74F5-4694-879C-C832B3BD68FF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {A92385B4-ADF1-4201-970E-915A57426B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {21739252-74F5-4694-879C-C832B3BD68FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21739252-74F5-4694-879C-C832B3BD68FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21739252-74F5-4694-879C-C832B3BD68FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21739252-74F5-4694-879C-C832B3BD68FF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/docker-compose.dcproj b/src/docker-compose.dcproj new file mode 100644 index 0000000..24775e1 --- /dev/null +++ b/src/docker-compose.dcproj @@ -0,0 +1,18 @@ + + + + 2.1 + Linux + 21739252-74f5-4694-879c-c832b3bd68ff + LaunchBrowser + {Scheme}://localhost:{ServicePort} + mars.web + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml new file mode 100644 index 0000000..e5856f2 --- /dev/null +++ b/src/docker-compose.override.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + mars.web: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:443;http://+:80 + ports: + - "80" + - "443" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/src/docker-compose.yml b/src/docker-compose.yml new file mode 100644 index 0000000..064c5dc --- /dev/null +++ b/src/docker-compose.yml @@ -0,0 +1,17 @@ +version: '3.4' + +services: + mars.web: + image: ${DOCKER_REGISTRY-}marsweb + build: + context: . + dockerfile: Mars.Web/Dockerfile + + seq: + image: datalust/seq:latest + ports: + - "8888:80" + volumes: + - /datadrive:/data + environment: + - ACCEPT_EULA=Y \ No newline at end of file From bef5245c53384766256e568da6482c45296e9676 Mon Sep 17 00:00:00 2001 From: garv5014 Date: Wed, 15 Feb 2023 11:37:46 -0700 Subject: [PATCH 10/23] added docker support --- src/.dockerignore | 25 +++++++++++ src/Mars.Web/Dockerfile | 24 +++++++++++ src/Mars.Web/Mars.Web.csproj | 3 ++ src/Mars.Web/Program.cs | 16 +++---- src/Mars.Web/Properties/launchSettings.json | 35 +++++++++------ src/Mars.Web/appsettings.json | 47 +++++++++++---------- src/MarsRover.sln | 6 +++ src/docker-compose.dcproj | 18 ++++++++ src/docker-compose.override.yml | 13 ++++++ src/docker-compose.yml | 18 ++++++++ 10 files changed, 160 insertions(+), 45 deletions(-) create mode 100644 src/.dockerignore create mode 100644 src/Mars.Web/Dockerfile create mode 100644 src/docker-compose.dcproj create mode 100644 src/docker-compose.override.yml create mode 100644 src/docker-compose.yml diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Mars.Web/Dockerfile b/src/Mars.Web/Dockerfile new file mode 100644 index 0000000..04e40d9 --- /dev/null +++ b/src/Mars.Web/Dockerfile @@ -0,0 +1,24 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /src +COPY ["Mars.Web/Mars.Web.csproj", "Mars.Web/"] +COPY ["Mars.MissionControl/Mars.MissionControl.csproj", "Mars.MissionControl/"] +COPY ["Mars.Web.Types/Mars.Web.Types.csproj", "Mars.Web.Types/"] +RUN dotnet restore "Mars.Web/Mars.Web.csproj" +COPY . . +WORKDIR "/src/Mars.Web" +RUN dotnet build "Mars.Web.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Mars.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Mars.Web.dll"] \ No newline at end of file diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 407f955..e20e01d 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -6,6 +6,8 @@ enable 1c3d0055-a8d7-4fc1-a151-6dbc7e1b1d38 True + Linux + ..\docker-compose.dcproj @@ -18,6 +20,7 @@ + diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 1298c7a..d3fa617 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -17,16 +17,14 @@ }); builder.Services.AddEndpointsApiExplorer(); -builder.Host.UseSerilog( (context, loggerConfig) => - { - loggerConfig.WriteTo.Console() - .Enrich.WithExceptionDetails() - .WriteTo.Seq("http://localhost:5340"); - } - - ); +builder.Host.UseSerilog((context, loggerConfig) => +{ + loggerConfig.WriteTo.Console() + .Enrich.WithExceptionDetails() + .WriteTo.Seq("http://seq"); +}); -builder.Services.AddProblemDetails(opts => +builder.Services.AddProblemDetails(opts => { opts.IncludeExceptionDetails = (ctx, ex) => false; } diff --git a/src/Mars.Web/Properties/launchSettings.json b/src/Mars.Web/Properties/launchSettings.json index 29d99f9..9f091b1 100644 --- a/src/Mars.Web/Properties/launchSettings.json +++ b/src/Mars.Web/Properties/launchSettings.json @@ -1,28 +1,22 @@ { - "iisSettings": { - "iisExpress": { - "applicationUrl": "http://localhost:26097", - "sslPort": 44335 - } - }, "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5110" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7287;http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7287;http://localhost:5110" }, "IIS Express": { "commandName": "IISExpress", @@ -30,6 +24,21 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "publishAllPorts": true, + "useSSL": true + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:26097", + "sslPort": 44335 } } -} +} \ No newline at end of file diff --git a/src/Mars.Web/appsettings.json b/src/Mars.Web/appsettings.json index 1b3be71..5db8342 100644 --- a/src/Mars.Web/appsettings.json +++ b/src/Mars.Web/appsettings.json @@ -1,23 +1,24 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft.AspNetCore": "Warning" - }, - "Console": { - "FormatterName": "json", - "FormatterOptions": { - "SingleLine": true, - "IncludeScopes": true, - "UseUtcTimestamp": true, - "TimestampFormat": "HH:mm:ss", - "JsonWriterOptions": { "Indented": true - } - } - } - }, - "AllowedHosts": "*", - "GAME_PASSWORD": "password", - "CleanupFrequencyMinutes": "60", - "ApiLimitPerSecond": "10" -} +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + }, + "Console": { + "FormatterName": "json", + "FormatterOptions": { + "SingleLine": true, + "IncludeScopes": true, + "UseUtcTimestamp": true, + "TimestampFormat": "HH:mm:ss", + "JsonWriterOptions": { + "Indented": true + } + } + } + }, + "AllowedHosts": "*", + "GAME_PASSWORD": "password", + "CleanupFrequencyMinutes": "60", + "ApiLimitPerSecond": "10" +} diff --git a/src/MarsRover.sln b/src/MarsRover.sln index b76f6cf..31dcdbb 100644 --- a/src/MarsRover.sln +++ b/src/MarsRover.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Tests", "Mars.Web. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Types", "Mars.Web.Types\Mars.Web.Types.csproj", "{A92385B4-ADF1-4201-970E-915A57426B5D}" EndProject +Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{196B3946-5D88-42B2-9DD7-48217B960394}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {A92385B4-ADF1-4201-970E-915A57426B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {196B3946-5D88-42B2-9DD7-48217B960394}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {196B3946-5D88-42B2-9DD7-48217B960394}.Debug|Any CPU.Build.0 = Debug|Any CPU + {196B3946-5D88-42B2-9DD7-48217B960394}.Release|Any CPU.ActiveCfg = Release|Any CPU + {196B3946-5D88-42B2-9DD7-48217B960394}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/docker-compose.dcproj b/src/docker-compose.dcproj new file mode 100644 index 0000000..90b5a34 --- /dev/null +++ b/src/docker-compose.dcproj @@ -0,0 +1,18 @@ + + + + 2.1 + Linux + 196b3946-5d88-42b2-9dd7-48217b960394 + LaunchBrowser + {Scheme}://localhost:{ServicePort} + mars.web + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml new file mode 100644 index 0000000..e5856f2 --- /dev/null +++ b/src/docker-compose.override.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + mars.web: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:443;http://+:80 + ports: + - "80" + - "443" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/src/docker-compose.yml b/src/docker-compose.yml new file mode 100644 index 0000000..d252ac1 --- /dev/null +++ b/src/docker-compose.yml @@ -0,0 +1,18 @@ +version: '3.4' + +services: + mars.web: + image: ${DOCKER_REGISTRY-}marsweb + build: + context: . + dockerfile: Mars.Web/Dockerfile + + seq: + image: datalust/seq:latest + container_name: seq + ports: + - "8888:80" + volumes: + - /datadrive:/data + environment: + - ACCEPT_EULA=Y \ No newline at end of file From 8872ab958b381e2b07a85e1958c1022041049987 Mon Sep 17 00:00:00 2001 From: garv5014 Date: Wed, 15 Feb 2023 12:36:33 -0700 Subject: [PATCH 11/23] adjusted the using scopes --- src/Mars.Web/Controllers/GameController.cs | 36 ++++++++++++---------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index 5f35bf7..51f9341 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -33,7 +33,7 @@ public ActionResult Join(string gameId, string name) var joinResult = gameManager.Game.Join(name); tokenMap.TryAdd(joinResult.Token.Value, gameId); - using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) + using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) { logger.LogInformation($"Player {name} joined game {gameId}"); } @@ -66,18 +66,19 @@ public ActionResult Join(string gameId, string name) [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult Status(string token) { - if (tokenMap.TryGetValue(token, out string? gameId)) + var tokenHasGame = tokenMap.TryGetValue(token, out string? gameId); + using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) { - if (games.TryGetValue(gameId, out var gameManager)) + if (tokenHasGame) { - if (gameManager.Game.TryTranslateToken(token, out _)) + if (games.TryGetValue(gameId, out var gameManager)) { - return new StatusResponse { Status = gameManager.Game.GameState.ToString() }; + if (gameManager.Game.TryTranslateToken(token, out _)) + { + return new StatusResponse { Status = gameManager.Game.GameState.ToString() }; + } } } - } - using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) - { logger.LogError($"Unrecogized token {token}"); return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } @@ -93,9 +94,11 @@ public ActionResult Status(string token) [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult MovePerseverance(string token, Direction direction) { - if (tokenMap.TryGetValue(token, out string? gameId)) + var tokenHasGame = tokenMap.TryGetValue(token, out string? gameId); + + using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) { - using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) + if (tokenHasGame) { if (games.TryGetValue(gameId, out var gameManager)) { @@ -133,9 +136,9 @@ public ActionResult MovePerseverance(string token, Direction direc } } + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } - logger.LogError($"Unrecogized token {token}"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } /// @@ -149,9 +152,10 @@ public ActionResult MovePerseverance(string token, Direction direc [ProducesResponseType(StatusCodes.Status400BadRequest)] public ActionResult MoveIngenuity(string token, int destinationRow, int destinationColumn) { - if (tokenMap.TryGetValue(token, out string? gameId)) + var tokenHasGame = tokenMap.TryGetValue(token, out string? gameId); + using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) { - using (logger.BeginScope("User: {ScopeUser} GameId: {ScopeGameId} ", token, gameId)) + if (tokenHasGame) { if (games.TryGetValue(gameId, out var gameManager)) { @@ -187,8 +191,8 @@ public ActionResult MoveIngenuity(string token, int desti } } } + logger.LogError($"Unrecogized token {token}"); + return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } - logger.LogError($"Unrecogized token {token}"); - return Problem("Unrecognized token", statusCode: 400, title: "Bad Token"); } } From 7e581021eb87f9250dbcd68ccd4641a6dd37a549 Mon Sep 17 00:00:00 2001 From: garv5014 Date: Wed, 15 Feb 2023 12:45:01 -0700 Subject: [PATCH 12/23] adjusted the using scopes --- src/Mars.Web/Controllers/GameController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index 51f9341..16a665c 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -32,9 +32,9 @@ public ActionResult Join(string gameId, string name) { var joinResult = gameManager.Game.Join(name); - tokenMap.TryAdd(joinResult.Token.Value, gameId); using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) { + tokenMap.TryAdd(joinResult.Token.Value, gameId); logger.LogInformation($"Player {name} joined game {gameId}"); } return new JoinResponse From d3c1f179a01f7456f2ae2b48d80d29a7e01e5b38 Mon Sep 17 00:00:00 2001 From: Breanna Nesbit Date: Wed, 15 Feb 2023 20:17:27 -0700 Subject: [PATCH 13/23] added docker compose/container --- src/.dockerignore | 25 +++++++++++++++ src/Mars.Web/Dockerfile | 24 ++++++++++++++ src/Mars.Web/Mars.Web.csproj | 3 ++ src/Mars.Web/Properties/launchSettings.json | 35 +++++++++++++-------- src/MarsRover.sln | 6 ++++ src/docker-compose.dcproj | 18 +++++++++++ src/docker-compose.override.yml | 13 ++++++++ src/docker-compose.yml | 20 ++++++++++++ 8 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 src/.dockerignore create mode 100644 src/Mars.Web/Dockerfile create mode 100644 src/docker-compose.dcproj create mode 100644 src/docker-compose.override.yml create mode 100644 src/docker-compose.yml diff --git a/src/.dockerignore b/src/.dockerignore new file mode 100644 index 0000000..3729ff0 --- /dev/null +++ b/src/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +LICENSE +README.md \ No newline at end of file diff --git a/src/Mars.Web/Dockerfile b/src/Mars.Web/Dockerfile new file mode 100644 index 0000000..04e40d9 --- /dev/null +++ b/src/Mars.Web/Dockerfile @@ -0,0 +1,24 @@ +#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. + +FROM mcr.microsoft.com/dotnet/aspnet:7.0 AS base +WORKDIR /app +EXPOSE 80 +EXPOSE 443 + +FROM mcr.microsoft.com/dotnet/sdk:7.0 AS build +WORKDIR /src +COPY ["Mars.Web/Mars.Web.csproj", "Mars.Web/"] +COPY ["Mars.MissionControl/Mars.MissionControl.csproj", "Mars.MissionControl/"] +COPY ["Mars.Web.Types/Mars.Web.Types.csproj", "Mars.Web.Types/"] +RUN dotnet restore "Mars.Web/Mars.Web.csproj" +COPY . . +WORKDIR "/src/Mars.Web" +RUN dotnet build "Mars.Web.csproj" -c Release -o /app/build + +FROM build AS publish +RUN dotnet publish "Mars.Web.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "Mars.Web.dll"] \ No newline at end of file diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index fc67c6f..d1591f5 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -6,6 +6,8 @@ enable 1c3d0055-a8d7-4fc1-a151-6dbc7e1b1d38 True + Linux + ..\docker-compose.dcproj @@ -17,6 +19,7 @@ + diff --git a/src/Mars.Web/Properties/launchSettings.json b/src/Mars.Web/Properties/launchSettings.json index 29d99f9..9f091b1 100644 --- a/src/Mars.Web/Properties/launchSettings.json +++ b/src/Mars.Web/Properties/launchSettings.json @@ -1,28 +1,22 @@ { - "iisSettings": { - "iisExpress": { - "applicationUrl": "http://localhost:26097", - "sslPort": 44335 - } - }, "profiles": { "http": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "http://localhost:5110" }, "https": { "commandName": "Project", - "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7287;http://localhost:5110", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "dotnetRunMessages": true, + "applicationUrl": "https://localhost:7287;http://localhost:5110" }, "IIS Express": { "commandName": "IISExpress", @@ -30,6 +24,21 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } + }, + "Docker": { + "commandName": "Docker", + "launchBrowser": true, + "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", + "publishAllPorts": true, + "useSSL": true + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:26097", + "sslPort": 44335 } } -} +} \ No newline at end of file diff --git a/src/MarsRover.sln b/src/MarsRover.sln index b76f6cf..503f471 100644 --- a/src/MarsRover.sln +++ b/src/MarsRover.sln @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Tests", "Mars.Web. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mars.Web.Types", "Mars.Web.Types\Mars.Web.Types.csproj", "{A92385B4-ADF1-4201-970E-915A57426B5D}" EndProject +Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-compose.dcproj", "{687118E8-8269-4BA9-93B1-CDCA4A310CC1}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -39,6 +41,10 @@ Global {A92385B4-ADF1-4201-970E-915A57426B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A92385B4-ADF1-4201-970E-915A57426B5D}.Release|Any CPU.Build.0 = Release|Any CPU + {687118E8-8269-4BA9-93B1-CDCA4A310CC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {687118E8-8269-4BA9-93B1-CDCA4A310CC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {687118E8-8269-4BA9-93B1-CDCA4A310CC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {687118E8-8269-4BA9-93B1-CDCA4A310CC1}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/docker-compose.dcproj b/src/docker-compose.dcproj new file mode 100644 index 0000000..3aa38d0 --- /dev/null +++ b/src/docker-compose.dcproj @@ -0,0 +1,18 @@ + + + + 2.1 + Linux + 687118e8-8269-4ba9-93b1-cdca4a310cc1 + LaunchBrowser + {Scheme}://localhost:{ServicePort} + mars.web + + + + docker-compose.yml + + + + + \ No newline at end of file diff --git a/src/docker-compose.override.yml b/src/docker-compose.override.yml new file mode 100644 index 0000000..e5856f2 --- /dev/null +++ b/src/docker-compose.override.yml @@ -0,0 +1,13 @@ +version: '3.4' + +services: + mars.web: + environment: + - ASPNETCORE_ENVIRONMENT=Development + - ASPNETCORE_URLS=https://+:443;http://+:80 + ports: + - "80" + - "443" + volumes: + - ${APPDATA}/Microsoft/UserSecrets:/root/.microsoft/usersecrets:ro + - ${APPDATA}/ASP.NET/Https:/root/.aspnet/https:ro \ No newline at end of file diff --git a/src/docker-compose.yml b/src/docker-compose.yml new file mode 100644 index 0000000..818a468 --- /dev/null +++ b/src/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3.4' + +services: + mars.web: + image: ${DOCKER_REGISTRY-}marsweb + build: + context: . + dockerfile: Mars.Web/Dockerfile + + seq: + container_name: seq + image: datalust/seq:latest + ports: + - "8888:5341" + - "8075:80" + - "45341:45341" + volumes: + - /datadrive:/data + environment: + - ACCEPT_EUL=Y \ No newline at end of file From 862f587317737897f4174c003a31ef0557518cac Mon Sep 17 00:00:00 2001 From: Caleb Wightman Date: Wed, 15 Feb 2023 22:51:17 -0700 Subject: [PATCH 14/23] added loggin for winning --- src/Mars.MissionControl/Game.cs | 14 +++++++++----- src/Mars.MissionControl/Mars.MissionControl.csproj | 4 ++++ src/Mars.Web/GameManager.cs | 12 +++++++----- src/Mars.Web/MultiGameHoster.cs | 12 +++++++----- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/Mars.MissionControl/Game.cs b/src/Mars.MissionControl/Game.cs index 27c359f..e0877e9 100644 --- a/src/Mars.MissionControl/Game.cs +++ b/src/Mars.MissionControl/Game.cs @@ -1,9 +1,10 @@ -using System.Collections.ObjectModel; +using Microsoft.Extensions.Logging; +using System.Collections.ObjectModel; namespace Mars.MissionControl; public class Game : IDisposable { - public Game(GameStartOptions startOptions) + public Game(GameStartOptions startOptions, ILoggerFactory loggerFactory = null) { GameState = GameState.Joining; Board = new Board(startOptions.Map); @@ -12,7 +13,8 @@ public Game(GameStartOptions startOptions) PerseveranceVisibilityRadius = startOptions.PerseveranceVisibilityRadius; IngenuityVisibilityRadius = startOptions.IngenuityVisibilityRadius; StartingBatteryLevel = startOptions.StartingBatteryLevel; - IngenuityStartingBatteryLevel = Board.Width * 2 + Board.Height * 2; + IngenuityStartingBatteryLevel = Board.Width * 2 + Board.Height * 2; + this.logger = loggerFactory.CreateLogger(); } public int MapNumber => Board.MapNumber; @@ -40,7 +42,9 @@ public Game(GameStartOptions startOptions) #region State Changed public event EventHandler? GameStateChanged; public DateTime lastStateChange; - public TimeSpan stateChangeFrequency;// = TimeSpan.FromSeconds(1); + public TimeSpan stateChangeFrequency;// = TimeSpan.FromSeconds(1); + private readonly ILogger logger; + private void raiseStateChange() { if (lastStateChange + stateChangeFrequency < DateTime.Now) @@ -242,7 +246,7 @@ public MoveResult MovePerseverance(PlayerToken token, Direction direction) if (player.PerseveranceLocation == TargetLocation)//you win! { - + logger.LogInformation("Player {0} has won!", player.Name); players.Remove(player.Token, out _); player = player with { WinningTime = DateTime.Now - GameStartedOn }; winners.Enqueue(player); diff --git a/src/Mars.MissionControl/Mars.MissionControl.csproj b/src/Mars.MissionControl/Mars.MissionControl.csproj index a1ed5b3..1ab1a63 100644 --- a/src/Mars.MissionControl/Mars.MissionControl.csproj +++ b/src/Mars.MissionControl/Mars.MissionControl.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/src/Mars.Web/GameManager.cs b/src/Mars.Web/GameManager.cs index 6c13148..fa3c0a5 100644 --- a/src/Mars.Web/GameManager.cs +++ b/src/Mars.Web/GameManager.cs @@ -3,16 +3,18 @@ namespace Mars.Web; public class GameManager -{ - public GameManager(List maps) +{ + private readonly ILoggerFactory logger; + + public GameManager(List maps, ILoggerFactory logger = null) { CreatedOn = DateTime.Now; GameStartOptions = new GameStartOptions { Map = maps[0], }; - this.Maps = maps; - + this.Maps = maps; + this.logger = logger; StartNewGame(GameStartOptions); } public IReadOnlyList Maps { get; } @@ -55,7 +57,7 @@ public void StartNewGame(GameStartOptions startOptions) NewGameStarted?.Invoke(this, new EventArgs()); - Game = new Game(startOptions); + Game = new Game(startOptions, logger); GameStateChanged?.Invoke(this, EventArgs.Empty); //subscribe to new event diff --git a/src/Mars.Web/MultiGameHoster.cs b/src/Mars.Web/MultiGameHoster.cs index 610be05..fb419c3 100644 --- a/src/Mars.Web/MultiGameHoster.cs +++ b/src/Mars.Web/MultiGameHoster.cs @@ -4,10 +4,11 @@ public class MultiGameHoster { - public MultiGameHoster(IMapProvider mapProvider, ILogger logger) + public MultiGameHoster(IMapProvider mapProvider, ILogger logger, ILoggerFactory loggerFactory) { ParsedMaps = new List(mapProvider.LoadMaps()); - this.logger = logger; + this.logger = logger; + this.loggerFactory = loggerFactory; } public void RaiseOldGamesPurged() => OldGamesPurged?.Invoke(this, EventArgs.Empty); @@ -19,14 +20,15 @@ public MultiGameHoster(IMapProvider mapProvider, ILogger logger private string nextGame = "a"; private object lockObject = new(); private readonly IWebHostEnvironment hostEnvironment; - private readonly ILogger logger; - + private readonly ILogger logger; + private readonly ILoggerFactory loggerFactory; + public string MakeNewGame() { lock (lockObject) { var gameId = nextGame; - Games.TryAdd(gameId, new GameManager(ParsedMaps)); + Games.TryAdd(gameId, new GameManager(ParsedMaps, loggerFactory)); nextGame = IncrementGameId(nextGame); logger.LogInformation($"New Game Created: {gameId}"); From ed01c4bb72d3d6e8d3afdd9e1a45e0c7596566c4 Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Tue, 21 Feb 2023 10:59:28 -0700 Subject: [PATCH 15/23] update github actions to run dotnet test MarsRover.sln --- .github/workflows/deploy-main-branch.yaml | 2 +- .github/workflows/deploy-pull-request.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-main-branch.yaml b/.github/workflows/deploy-main-branch.yaml index d2c8dad..8538323 100644 --- a/.github/workflows/deploy-main-branch.yaml +++ b/.github/workflows/deploy-main-branch.yaml @@ -31,7 +31,7 @@ jobs: - name: Run Tests working-directory: src - run: dotnet test + run: dotnet test MarsRover.sln - name: dotnet publish working-directory: src/Mars.Web diff --git a/.github/workflows/deploy-pull-request.yaml b/.github/workflows/deploy-pull-request.yaml index 2b0c231..198a3a8 100644 --- a/.github/workflows/deploy-pull-request.yaml +++ b/.github/workflows/deploy-pull-request.yaml @@ -33,7 +33,7 @@ jobs: - name: Run Tests working-directory: src - run: dotnet test + run: dotnet test MarsRover.sln - name: dotnet publish working-directory: src/Mars.Web From d08a28a55af687126584ad32109e87abcaa0252d Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 15:23:09 -0700 Subject: [PATCH 16/23] add jaeger/distributed tracing --- src/Mars.Web/Controllers/GameController.cs | 11 +++++++---- src/Mars.Web/Mars.Web.csproj | 3 +++ src/Mars.Web/Program.cs | 21 +++++++++++++++++---- src/docker-compose.yml | 21 ++++++++++++++++++++- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index 6545e19..be765c8 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -1,9 +1,12 @@ -using Mars.MissionControl; -using Mars.Web.Pages; -using Microsoft.AspNetCore.Mvc; +using System.Diagnostics; namespace Mars.Web.Controllers; +public static class GameActivitySource +{ + public static ActivitySource Instance { get; } = new ActivitySource("Mars.Web", "1.0"); +} + [ApiController] [Route("[controller]")] public class GameController : ControllerBase @@ -34,7 +37,7 @@ public ActionResult Join(string gameId, string name) { try { - + using var activity = GameActivitySource.Instance.StartActivity("Join Game"); var joinResult = gameManager.Game.Join(name); using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) { diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index d3bcd5f..16fb7ba 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -21,6 +21,9 @@ + + + diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 423186a..253bbda 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -1,17 +1,30 @@ +using Hellang.Middleware.ProblemDetails; using Mars.Web; +using Mars.Web.Controllers; using Microsoft.OpenApi.Models; +using OpenTelemetry; +using OpenTelemetry.Resources; +using OpenTelemetry.Trace; using Serilog; using Serilog.Exceptions; using System.Reflection; -using System.Runtime.InteropServices; using System.Text.Json.Serialization; using System.Threading.RateLimiting; -using Hellang.Middleware.ProblemDetails; -using Serilog; -using Serilog.Exceptions; var builder = WebApplication.CreateBuilder(args); +using var traceProvider = Sdk.CreateTracerProviderBuilder() + .SetResourceBuilder(ResourceBuilder.CreateDefault().AddService("Mars.Web")) + .AddSource(GameActivitySource.Instance.Name) + .AddJaegerExporter(o => + { + o.Protocol = OpenTelemetry.Exporter.JaegerExportProtocol.HttpBinaryThrift; + o.Endpoint = new Uri("http://jaeger:14268/api/traces"); + }) + .AddHttpClientInstrumentation() + .AddAspNetCoreInstrumentation() + .Build(); + builder.Host.UseSerilog((c, l) => { l.WriteTo.Console() diff --git a/src/docker-compose.yml b/src/docker-compose.yml index 1bbee0e..53459be 100644 --- a/src/docker-compose.yml +++ b/src/docker-compose.yml @@ -8,6 +8,8 @@ services: dockerfile: Mars.Web/Dockerfile environment: - SeqServer=http://seq + networks: + - jaegernet seq: container_name: seq @@ -17,4 +19,21 @@ services: volumes: - /datadrive:/data environment: - - ACCEPT_EULA=Y \ No newline at end of file + - ACCEPT_EULA=Y + + jaeger: + container_name: jaeger + image: jaegertracing/all-in-one:latest + ports: + - "16686:16686" + - "14268:14268" + environment: + - COLLECTOR_OTLP_ENABLED=true + - LOG_LEVEL=debug + networks: + - jaegernet + depends_on: + - mars.web + +networks: + jaegernet: \ No newline at end of file From 4269609db113cda4595b96fa8ce1aa3b77e5b15b Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 15:29:26 -0700 Subject: [PATCH 17/23] stop running codeql --- .github/workflows/{codeql.yml => codeql.yml.bogus} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{codeql.yml => codeql.yml.bogus} (100%) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml.bogus similarity index 100% rename from .github/workflows/codeql.yml rename to .github/workflows/codeql.yml.bogus From 1cf21c82ff930ce5a66a0499ba5d36e82b304f73 Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 15:31:38 -0700 Subject: [PATCH 18/23] only use serilog once --- src/Mars.Web/Program.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Mars.Web/Program.cs b/src/Mars.Web/Program.cs index 253bbda..dd23052 100644 --- a/src/Mars.Web/Program.cs +++ b/src/Mars.Web/Program.cs @@ -25,13 +25,6 @@ .AddAspNetCoreInstrumentation() .Build(); -builder.Host.UseSerilog((c, l) => -{ - l.WriteTo.Console() - .Enrich.WithExceptionDetails() - .WriteTo.Seq("http://seq"); -}); - builder.Services.AddApplicationInsightsTelemetry(); builder.Services.AddRazorPages(); builder.Services.AddServerSideBlazor(); From 12d9ddb5e2e5fd07fd63745a554aee3c5435f42d Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 15:52:37 -0700 Subject: [PATCH 19/23] add extra app insights collection --- src/Mars.Web/Mars.Web.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Mars.Web/Mars.Web.csproj b/src/Mars.Web/Mars.Web.csproj index 16fb7ba..90e2efe 100644 --- a/src/Mars.Web/Mars.Web.csproj +++ b/src/Mars.Web/Mars.Web.csproj @@ -19,7 +19,11 @@ + + + + From d7e4c4ed415fb3bb821b7aeb85ce372d4a3e5b40 Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 16:17:05 -0700 Subject: [PATCH 20/23] see logs in app insights? --- src/Mars.Web/Controllers/GameController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mars.Web/Controllers/GameController.cs b/src/Mars.Web/Controllers/GameController.cs index be765c8..1bd0a81 100644 --- a/src/Mars.Web/Controllers/GameController.cs +++ b/src/Mars.Web/Controllers/GameController.cs @@ -42,7 +42,7 @@ public ActionResult Join(string gameId, string name) using (logger.BeginScope("ScopeUserToken: {ScopeUser} GameId: {ScopeGameId} ", joinResult.Token.Value, gameId)) { tokenMap.TryAdd(joinResult.Token.Value, gameId); - logger.LogInformation("Player {name} joined game {gameId}", name, gameId); + logger.LogWarning("Player {name} joined game {gameId}", name, gameId); } return new JoinResponse { From 3235bf2265da1153a74a7437511067db6065e80c Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Thu, 23 Feb 2023 16:36:09 -0700 Subject: [PATCH 21/23] try changing config there --- src/Mars.Web/appsettings.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Mars.Web/appsettings.json b/src/Mars.Web/appsettings.json index 636bf8a..bac4d64 100644 --- a/src/Mars.Web/appsettings.json +++ b/src/Mars.Web/appsettings.json @@ -4,6 +4,11 @@ "Default": "Information", "Microsoft.AspNetCore": "Warning" }, + "ApplicationInsights": { + "LogLevel": { + "Default": "Information" + } + }, "Console": { "FormatterName": "json", "FormatterOptions": { From 14b9947bb4543539696a7c2c9de39b5ce7e45a7f Mon Sep 17 00:00:00 2001 From: Jonathan Allen Date: Fri, 24 Feb 2023 19:02:08 -0700 Subject: [PATCH 22/23] update readme with ideas presented after February contest --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 8e5c8f8..cded9a8 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,21 @@ Object: Get your rover to the destination before everyone else! - Winners are determined by the amount of time elapsed from when the game state becomes 'Playing' to when your rover makes it to the target. - Tip: Make sure you use the high-resolution information you get back from Perseverance and Ingenuity about their surrounding cells to help improve your planning of how you will get to the target. +## Proposed Changes for the March 2022 Competition + +- Change spawning locations + - circle spawn (equidistant from target) + - fair spawn (possibly different distances but equal best-path to target) + - weighted spawn +- Edge wrapping +- Unpassable barriers / cliffs (require pathfinding) +- Weather/storms changes difficulty values (so your previous map becomes invalidated, requiring constant scanning and re-evaluation) +- closing ring, as time passes boot players outside of a certain radius +- Multiple waypoints +- Unbounded battery (you can charge beyond your initial battery level) +- Change scoring: most efficient wins (battery used / time taken), within 60 seconds of first to target +- Return battery level on join + ## API Documentation There is an [API Playground](https://snow-rover.azurewebsites.net/swagger/index.html) where you can see exactly what endpoints exist on the server, what arguments need to be passed in, and what type of data you get back. Feel free to use that to help you get familiar with how to interact with the server. While you *can* play the game using nothing more than the API Playground, or a commandline with `curl` in bash or `Invoke-RestMethod` in PowerShell (or even from a few different browser tabs), you will have the best success by writing a program to automate your server interactions. From 6b9335ddf6e3c1c59ffc8848865054c88979e8a5 Mon Sep 17 00:00:00 2001 From: J Allen <42281341+snow-jallen@users.noreply.github.com> Date: Tue, 28 Feb 2023 07:45:46 -0700 Subject: [PATCH 23/23] Update README.md --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cded9a8..df5b910 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,11 @@ # 2023 Snow College Coding Competition: Mars Rover -Object: Get your rover to the destination before everyone else! +> **Next competition date:** Friday, March 31st 2023 @ 4PM +> **Final competition date:** Friday, April 21st 2023 @ 4PM +> Location: [Snow College Science Building, Room GRSC 124](https://goo.gl/maps/zKw4X9gioeNCKutZ9) + +***Object: Get your rover to the destination(s) before everyone else!*** ## Summary of Game Mechanics @@ -36,10 +40,10 @@ Object: Get your rover to the destination before everyone else! - Unpassable barriers / cliffs (require pathfinding) - Weather/storms changes difficulty values (so your previous map becomes invalidated, requiring constant scanning and re-evaluation) - closing ring, as time passes boot players outside of a certain radius -- Multiple waypoints -- Unbounded battery (you can charge beyond your initial battery level) -- Change scoring: most efficient wins (battery used / time taken), within 60 seconds of first to target -- Return battery level on join +- ***Multiple waypoints*** +- ***Unbounded battery (you can charge beyond your initial battery level)*** +- ***Change scoring: most efficient wins (battery used / time taken), within 60 seconds of first to target*** +- ***Return battery level on join*** ## API Documentation