From 139f77b3c86bbf9491fe7ea9df9fd910a808db9d Mon Sep 17 00:00:00 2001 From: Kevin Guanche Darias Date: Sat, 17 Feb 2024 15:27:38 +0000 Subject: [PATCH] Complete #513 Also allow to clear all the game data when cache panic --- business/database/migrations/v0.11.0.sql | 11 ++++- .../owgejava/entity/TrackBrowser.java | 25 +++++++++++ .../repository/TrackBrowserRepository.java | 7 +++ game-frontend/CHANGELOG.md | 2 + .../owge-core/src/lib/owge-core.module.ts | 1 + .../src/lib/services/session.service.ts | 2 +- .../src/lib/services/planet.service.ts | 1 - .../src/lib/services/error-logging.service.ts | 43 +++++++++++++++++++ .../modules/owge-universe/src/public-api.ts | 1 + game-frontend/package-lock.json | 21 +++++++-- game-frontend/package.json | 5 ++- .../game-frontend/src/app/app.component.html | 3 +- .../game-frontend/src/app/app.component.scss | 7 ++- .../game-frontend/src/app/app.component.ts | 19 ++++++-- .../game-frontend/src/app/app.module.ts | 5 ++- .../game-frontend/src/assets/i18n/en.json | 1 + .../game-frontend/src/assets/i18n/es.json | 1 + .../rest/game/TrackBrowserRestService.java | 40 +++++++++++++++++ 18 files changed, 179 insertions(+), 16 deletions(-) create mode 100644 business/src/main/java/com/kevinguanchedarias/owgejava/entity/TrackBrowser.java create mode 100644 business/src/main/java/com/kevinguanchedarias/owgejava/repository/TrackBrowserRepository.java create mode 100644 game-frontend/modules/owge-universe/src/lib/services/error-logging.service.ts create mode 100644 game-rest/src/main/java/com/kevinguanchedarias/owgejava/rest/game/TrackBrowserRestService.java diff --git a/business/database/migrations/v0.11.0.sql b/business/database/migrations/v0.11.0.sql index caece6ca..0fdcb108 100644 --- a/business/database/migrations/v0.11.0.sql +++ b/business/database/migrations/v0.11.0.sql @@ -108,4 +108,13 @@ CREATE TABLE `suspicions` ) ENGINE = InnoDB; ALTER TABLE upgrades - ADD `order_number` smallint unsigned DEFAULT NULL COMMENT 'The upgrade order' AFTER id; \ No newline at end of file + ADD `order_number` smallint unsigned DEFAULT NULL COMMENT 'The upgrade order' AFTER id; + +CREATE TABLE track_browser +( + id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, + method VARCHAR(8) NOT NULL, + json_content TEXT NOT NULL, + created_at DATETIME NOT NULL, + PRIMARY KEY (id) +) ENGINE = InnoDB \ No newline at end of file diff --git a/business/src/main/java/com/kevinguanchedarias/owgejava/entity/TrackBrowser.java b/business/src/main/java/com/kevinguanchedarias/owgejava/entity/TrackBrowser.java new file mode 100644 index 00000000..827b9969 --- /dev/null +++ b/business/src/main/java/com/kevinguanchedarias/owgejava/entity/TrackBrowser.java @@ -0,0 +1,25 @@ +package com.kevinguanchedarias.owgejava.entity; + +import jakarta.persistence.*; +import lombok.*; + +import java.time.Instant; + +@Data +@Entity +@Table +@Builder +@AllArgsConstructor +@NoArgsConstructor +@EqualsAndHashCode(onlyExplicitlyIncluded = true) +public class TrackBrowser { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @EqualsAndHashCode.Include + private Long id; + + String method; + String jsonContent; + + Instant createdAt; +} diff --git a/business/src/main/java/com/kevinguanchedarias/owgejava/repository/TrackBrowserRepository.java b/business/src/main/java/com/kevinguanchedarias/owgejava/repository/TrackBrowserRepository.java new file mode 100644 index 00000000..24f8bc1e --- /dev/null +++ b/business/src/main/java/com/kevinguanchedarias/owgejava/repository/TrackBrowserRepository.java @@ -0,0 +1,7 @@ +package com.kevinguanchedarias.owgejava.repository; + +import com.kevinguanchedarias.owgejava.entity.TrackBrowser; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TrackBrowserRepository extends JpaRepository { +} diff --git a/game-frontend/CHANGELOG.md b/game-frontend/CHANGELOG.md index 40db5975..11eccb42 100644 --- a/game-frontend/CHANGELOG.md +++ b/game-frontend/CHANGELOG.md @@ -12,6 +12,8 @@ v0.11.5 (latest) * __Fix:__ [In the unit info dialog, the attackable types is not working in Neon theme #526](https://github.com/KevinGuancheDarias/owge/issues/526) * __Fix:__ Potential fix to error caused by fixing #541, also stabilize handling of duplicated units * __Fix:__ [Selected planet is not preserved after f5 #542](https://github.com/KevinGuancheDarias/owge/issues/542) +* __Improvement:__ [Add browser tracking to be able to detect frontend bugs #513](https://github.com/KevinGuancheDarias/owge/issues/513) +* __Improvement:__ Allow to clear all the game data when cache panic v0.11.4 (2024-02-08 05:39) ================== diff --git a/game-frontend/modules/owge-core/src/lib/owge-core.module.ts b/game-frontend/modules/owge-core/src/lib/owge-core.module.ts index 316df5d2..84dc30ac 100644 --- a/game-frontend/modules/owge-core/src/lib/owge-core.module.ts +++ b/game-frontend/modules/owge-core/src/lib/owge-core.module.ts @@ -28,6 +28,7 @@ import {ObsService} from './services/obs.service'; import {SecurePlanetEntryPipePipe} from './pipes/secure-entry.pipe'; import {PlanetDisplayNamePipe} from './pipes/planet-display-name.pipe'; import {SecureItemDirective} from './directives/secure-item.directive'; +import {ErrorLoggingService} from '../../../owge-universe/src/lib/services/error-logging.service'; /** * Has the shared features between modules, such as loading image diff --git a/game-frontend/modules/owge-core/src/lib/services/session.service.ts b/game-frontend/modules/owge-core/src/lib/services/session.service.ts index a493a095..7a050503 100644 --- a/game-frontend/modules/owge-core/src/lib/services/session.service.ts +++ b/game-frontend/modules/owge-core/src/lib/services/session.service.ts @@ -103,7 +103,7 @@ export class SessionService extends AbstractWebsocketApplicationHandler implemen return sessionStorage.getItem(SessionService.LOCAL_STORAGE_TOKEN_PARAM); } - public logout(): any { + public logout(): void { this._clearSessionData(); this._redirectIfNotLoggedIn(); this._logoutEmitter.emit(); diff --git a/game-frontend/modules/owge-galaxy/src/lib/services/planet.service.ts b/game-frontend/modules/owge-galaxy/src/lib/services/planet.service.ts index 7fa3980d..1870aa61 100644 --- a/game-frontend/modules/owge-galaxy/src/lib/services/planet.service.ts +++ b/game-frontend/modules/owge-galaxy/src/lib/services/planet.service.ts @@ -122,7 +122,6 @@ export class PlanetService extends AbstractWebsocketApplicationHandler { } private handleLogin(): void { - console.log('pene'); this.loginService.onLogin.subscribe(() => this.findMyPlanets().pipe(take(1)).subscribe(planets => this.defineSelectedPlanet(planets.find(planet => planet.home)) diff --git a/game-frontend/modules/owge-universe/src/lib/services/error-logging.service.ts b/game-frontend/modules/owge-universe/src/lib/services/error-logging.service.ts new file mode 100644 index 00000000..cdcf3d0d --- /dev/null +++ b/game-frontend/modules/owge-universe/src/lib/services/error-logging.service.ts @@ -0,0 +1,43 @@ +import {Injectable} from '@angular/core'; +import {UniverseGameService} from './universe-game.service'; +import {stringify} from 'flatted'; + +@Injectable({ + providedIn: 'root' +}) +export class ErrorLoggingService { + private readonly originalWarn = console.warn.bind(console); + + constructor(private universeGameService: UniverseGameService) { + window.onerror = (msg, url, lineNo, columnNo, error) => { + console.log('ups',msg,lineNo, error); + }; + ['warn','error'].forEach(level => this.intercept(level)); + } + + private intercept(method: string): void { + // eslint-disable-next-line no-console + const original = console[method].bind(console); + // eslint-disable-next-line no-console + console[method] = (...args) => { + // eslint-disable-next-line no-console + this.doReport(method, args).then(() => console.debug('Logged data ',method, args)); + original(...args); + }; + } + + private async doReport(method: string, args: unknown[]): Promise { + try { + const content = stringify(args); + if(content.length > 100) { + await this.universeGameService.requestWithAutorizationToContext( + 'game', 'post', `track-browser/${method}`, content + ).toPromise(); + } else { + this.originalWarn('Not logging due to insufficient information',content); + } + }catch (e) { + this.originalWarn('unable to track browser',e ); + } + } +} diff --git a/game-frontend/modules/owge-universe/src/public-api.ts b/game-frontend/modules/owge-universe/src/public-api.ts index 000459d2..9c1b8bc2 100644 --- a/game-frontend/modules/owge-universe/src/public-api.ts +++ b/game-frontend/modules/owge-universe/src/public-api.ts @@ -18,6 +18,7 @@ export * from './lib/pojos/resource-requirements.pojo'; export * from './lib/services/abstract-crud.service'; export * from './lib/services/active-time-special.service'; export * from './lib/services/active-time-special-rule-finder.service'; +export * from './lib/services/error-logging.service'; export * from './lib/services/image-store.service'; export * from './lib/services/mission.service'; export * from './lib/services/resource-manager.service'; diff --git a/game-frontend/package-lock.json b/game-frontend/package-lock.json index 1466c28a..09474c29 100644 --- a/game-frontend/package-lock.json +++ b/game-frontend/package-lock.json @@ -6930,10 +6930,9 @@ } }, "flatted": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", - "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", - "dev": true + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==" }, "flush-write-stream": { "version": "1.1.1", @@ -8868,6 +8867,12 @@ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -9389,6 +9394,14 @@ "flatted": "^2.0.1", "rfdc": "^1.1.4", "streamroller": "^2.2.4" + }, + "dependencies": { + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + } } }, "loglevel": { diff --git a/game-frontend/package.json b/game-frontend/package.json index 693cf0c7..b26eb536 100644 --- a/game-frontend/package.json +++ b/game-frontend/package.json @@ -9,8 +9,8 @@ "startWithNightlyBackend": "npm run createVersionFile && ng serve --proxy-config nightly.proxy.conf.json", "start": "npm run createVersionFile && npm run compileChangelog && ng serve", "startAdmin": "ng serve game-admin", - "ngServeDocker": "npm run createVersionFile && npm run compileChangelog && ng serve --host 0.0.0.0 --disable-host-check", - "ngServeDockerAdmin": "ng serve game-admin --host 0.0.0.0 --disable-host-check", + "ngServeDocker": "npm run createVersionFile && npm run compileChangelog && ng serve --host 0.0.0.0 --disable-host-check --live-reload false", + "ngServeDockerAdmin": "ng serve game-admin --host 0.0.0.0 --disable-host-check --live-reload false", "build": "npm run createVersionFile && npm run compileChangelog && ng build --prod", "buildDevLike": "npm run createVersionFile && npm run compileChangelog && ng build", "buildAdmin": "npm run createVersionFile && npm run compileChangelog && ng build game-admin --prod", @@ -44,6 +44,7 @@ "bootstrap": "^4.4.1", "core-js": "^2.4.1", "dexie": "^3.0.1", + "flatted": "^3.2.9", "karma-spec-reporter": "0.0.26", "lodash-es": "^4.17.15", "ng2-logger": "^3.0.11", diff --git a/game-frontend/projects/game-frontend/src/app/app.component.html b/game-frontend/projects/game-frontend/src/app/app.component.html index 5306eb79..73b572cb 100644 --- a/game-frontend/projects/game-frontend/src/app/app.component.html +++ b/game-frontend/projects/game-frontend/src/app/app.component.html @@ -7,7 +7,8 @@
- + +
{ @@ -106,7 +107,7 @@ export class AppComponent implements OnInit { } public clickReload() { - // window.location.reload(); + window.location.reload(); } public onDisplayTwitch(val: TwitchState): void { @@ -118,6 +119,18 @@ export class AppComponent implements OnInit { } } + async clearData() { + this.websocketService.close(); + // TODO: When updating to typescript 5.4 this should be supported so no need to ts-ignore: + // https://github.com/microsoft/TypeScript/commit/9ebe11c2d375bfb1c8fad10d705ffae09583c522 + // @ts-ignore + const dbs: any[] = await window.indexedDB.databases(); + dbs.forEach(db => window.indexedDB.deleteDatabase(db.name)); + sessionStorage.clear(); + this.sessionService.logout(); + setTimeout(() => window.location.reload(), 1000); + } + private _loadPlayer(val: TwitchState) { this.twitchPlayer = new Twitch.Player(AppComponent._TWITCH_DIV, { width: '100%', diff --git a/game-frontend/projects/game-frontend/src/app/app.module.ts b/game-frontend/projects/game-frontend/src/app/app.module.ts index c099cb73..1b4f4cf3 100644 --- a/game-frontend/projects/game-frontend/src/app/app.module.ts +++ b/game-frontend/projects/game-frontend/src/app/app.module.ts @@ -14,7 +14,7 @@ import { } from '@owge/core'; import { OwgeGalaxyModule, PlanetListService, PlanetService } from '@owge/galaxy'; import { - OwgeUniverseModule, SystemMessageService, TimeSpecialService, UniverseGameService, + ErrorLoggingService, OwgeUniverseModule, SystemMessageService, TimeSpecialService, UniverseGameService, UserStorage, WebsocketService, WsEventCacheService } from '@owge/universe'; import { OwgeWidgetsModule } from '@owge/widgets'; @@ -220,7 +220,8 @@ export class AppModule { private _userStorage: UserStorage, private _universeGameService: UniverseGameService, private _wsEventCacheService: WsEventCacheService, - private themeService: ThemeService + private themeService: ThemeService, + private errorLoggingService: ErrorLoggingService ) { ServiceLocator.injector = this._injector; themeService.useUserDefinedOrDefault(); diff --git a/game-frontend/projects/game-frontend/src/assets/i18n/en.json b/game-frontend/projects/game-frontend/src/assets/i18n/en.json index 752e67da..c1539edf 100644 --- a/game-frontend/projects/game-frontend/src/assets/i18n/en.json +++ b/game-frontend/projects/game-frontend/src/assets/i18n/en.json @@ -23,6 +23,7 @@ "NOT_CONNECTED": "Not connected, you can continue browsing, but can't run actions", "SYNC_ERROR": "Sync error, please check your Internet is stable, maybe your game account is broken, contact admin", "NOT_CONNECTED_CLICK_ERROR": "You don't have Internet, or server is down, you can't run this action", + "BTN_CLEAR_DATA": "Clear the game data", "BTN_RELOAD": "Reload the game page", "LOGIN": { "PLACEHOLDER_EMAIL": "Email or username", diff --git a/game-frontend/projects/game-frontend/src/assets/i18n/es.json b/game-frontend/projects/game-frontend/src/assets/i18n/es.json index 11e8ab25..052850c6 100644 --- a/game-frontend/projects/game-frontend/src/assets/i18n/es.json +++ b/game-frontend/projects/game-frontend/src/assets/i18n/es.json @@ -22,6 +22,7 @@ "NOT_CONNECTED": "Desconectado, puedes seguir viendo cosas, pero no se ejecutarán acciones", "SYNC_ERROR": "Error de sincronización, quizá tu Internet es débil, o tu cuenta esté rota, si tu Internet funciona, contacta con un administrador", "NOT_CONNECTED_CLICK_ERROR": "No tienes Internet, o el servidor está caído, no puedes ejecutar esta acción", + "BTN_CLEAR_DATA": "Limpiar datos del juego (cerrará sesión)", "BTN_RELOAD": "Recargar la página del juego", "LOGIN": { "PLACEHOLDER_EMAIL": "Email o usuario", diff --git a/game-rest/src/main/java/com/kevinguanchedarias/owgejava/rest/game/TrackBrowserRestService.java b/game-rest/src/main/java/com/kevinguanchedarias/owgejava/rest/game/TrackBrowserRestService.java new file mode 100644 index 00000000..dde57b5b --- /dev/null +++ b/game-rest/src/main/java/com/kevinguanchedarias/owgejava/rest/game/TrackBrowserRestService.java @@ -0,0 +1,40 @@ +package com.kevinguanchedarias.owgejava.rest.game; + +import com.kevinguanchedarias.owgejava.entity.TrackBrowser; +import com.kevinguanchedarias.owgejava.repository.TrackBrowserRepository; +import lombok.AllArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.annotation.ApplicationScope; + +import java.time.Instant; + +@RestController +@RequestMapping("game/track-browser") +@ApplicationScope +@AllArgsConstructor +public class TrackBrowserRestService { + private final TrackBrowserRepository trackBrowserRepository; + + @PostMapping("warn") + public void warn(@RequestBody String body) { + doTrack("warn", body); + } + + @PostMapping("error") + public void error(@RequestBody String body) { + doTrack("error", body); + } + + private void doTrack(String method, String content) { + trackBrowserRepository.save( + TrackBrowser.builder() + .method(method) + .jsonContent(content) + .createdAt(Instant.now()) + .build() + ); + } +}