diff --git a/.github/workflows/docker-armv7.yml b/.github/workflows/docker-armv7.yml deleted file mode 100644 index 5983348..0000000 --- a/.github/workflows/docker-armv7.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: docker-armv7 - -on: - push: - branches: [master] - paths-ignore: - - '.github/**' - - '.vscode/**' - - 'chrome-extension/**' - - 'releases/**' - - '**/**.md' - - '**.crx' - - '**.pem' - - '.dockerignore' - - '.gitignore' - schedule: - - cron: '49 4 * * 2' - workflow_dispatch: - inputs: - push_image: - description: 'Push image to registry' - required: true - default: 'false' - type: choice - options: - - 'true' - - 'false' - image_tag: - description: 'Docker tag prefix (workflow appends -armv7)' - required: true - default: 'test' - type: string - -concurrency: - group: docker-armv7-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - steps: - - name: checkout code - uses: actions/checkout@v6 - - - name: Set hash - id: vars - run: echo "sha_short=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" - - - name: Get current date - id: date - run: echo "date=$(date +'%Y-%m-%d')" >> "$GITHUB_OUTPUT" - - - name: create-json - id: create-json - uses: jsdaniell/create-json@v1.2.3 - with: - name: "version.json" - json: '{"type": "docker", "tag": "${{secrets.DOCKERHUB_MASTER_TAG}}-armv7", "commit": "${{ steps.vars.outputs.sha_short }}", "date": "${{ steps.date.outputs.date }}"}' - dir: 'backend/' - - - name: setup platform emulator - uses: docker/setup-qemu-action@v3 - - - name: setup multi-arch docker build - uses: docker/setup-buildx-action@v3 - - - name: Set push and tag values - id: build_params - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "push=${{ github.event.inputs.push_image }}" >> "$GITHUB_OUTPUT" - echo "tags=${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{ github.event.inputs.image_tag }}-armv7,ghcr.io/${{ github.repository_owner }}/${{ secrets.DOCKERHUB_REPO }}:${{ github.event.inputs.image_tag }}-armv7" >> "$GITHUB_OUTPUT" - else - echo "push=true" >> "$GITHUB_OUTPUT" - echo "tags=${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{ secrets.DOCKERHUB_MASTER_TAG }}-armv7,${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:${{ secrets.DOCKERHUB_MASTER_TAG }}-${{ steps.date.outputs.date }}-armv7,${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_REPO }}:sha-${{ steps.vars.outputs.sha_short }}-armv7,ghcr.io/${{ github.repository_owner }}/${{ secrets.DOCKERHUB_REPO }}:${{ secrets.DOCKERHUB_MASTER_TAG }}-armv7,ghcr.io/${{ github.repository_owner }}/${{ secrets.DOCKERHUB_REPO }}:${{ secrets.DOCKERHUB_MASTER_TAG }}-${{ steps.date.outputs.date }}-armv7,ghcr.io/${{ github.repository_owner }}/${{ secrets.DOCKERHUB_REPO }}:sha-${{ steps.vars.outputs.sha_short }}-armv7" >> "$GITHUB_OUTPUT" - fi - - - name: Login to DockerHub - if: github.event_name != 'workflow_dispatch' || github.event.inputs.push_image == 'true' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Login to GitHub Container Registry - if: github.event_name != 'workflow_dispatch' || github.event.inputs.push_image == 'true' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: build & push armv7 image - uses: docker/build-push-action@v6 - with: - context: . - file: ./Dockerfile - platforms: linux/arm/v7 - push: ${{ steps.build_params.outputs.push }} - tags: ${{ steps.build_params.outputs.tags }} diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 05f9406..d6c3b00 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit, ElementRef, ViewChild, HostBinding, AfterViewInit, ApplicationRef, NgZone } from '@angular/core'; +import { Component, OnInit, ElementRef, ViewChild, HostBinding, AfterViewInit } from '@angular/core'; import {MatDialogRef} from '@angular/material/dialog'; import {PostsService} from './posts.services'; import { MatDialog } from '@angular/material/dialog'; @@ -14,7 +14,6 @@ import { UserProfileDialogComponent } from './dialogs/user-profile-dialog/user-p import { SetDefaultAdminDialogComponent } from './dialogs/set-default-admin-dialog/set-default-admin-dialog.component'; import { NotificationsComponent } from './components/notifications/notifications.component'; import { ArchiveViewerComponent } from './components/archive-viewer/archive-viewer.component'; -import { diagCount, diagEvent, getYdmDiag } from './diagnostics'; @Component({ selector: 'app-root', @@ -49,9 +48,7 @@ export class AppComponent implements OnInit, AfterViewInit { constructor(public postsService: PostsService, public snackBar: MatSnackBar, private dialog: MatDialog, public router: Router, public overlayContainer: OverlayContainer, private elementRef: ElementRef, - private appRef: ApplicationRef, private ngZone: NgZone) { - - this.installDiagnosticsProbe(); + ) { this.navigator = localStorage.getItem('player_navigator'); // runs on navigate, captures the route that navigated to the player (if needed) @@ -72,37 +69,6 @@ export class AppComponent implements OnInit, AfterViewInit { }); } - - private installDiagnosticsProbe(): void { - const diag = getYdmDiag(); - diag.flags['probeInstalled'] = true; - - const appRefAny = this.appRef as any; - if (!appRefAny.__ydmTickPatched) { - const originalTick = this.appRef.tick.bind(this.appRef); - appRefAny.__ydmTickPatched = true; - this.appRef.tick = (() => { - diagCount('appRef.tick'); - return originalTick(); - }) as typeof this.appRef.tick; - diagEvent('probe.appRef.tick.patched'); - } - - if (diag.flags['zoneSubscriptionsInstalled']) { - return; - } - - diag.flags['zoneSubscriptionsInstalled'] = true; - this.ngZone.onUnstable.subscribe(() => diagCount('ngZone.onUnstable')); - this.ngZone.onMicrotaskEmpty.subscribe(() => diagCount('ngZone.onMicrotaskEmpty')); - this.ngZone.onStable.subscribe(() => diagCount('ngZone.onStable')); - this.ngZone.onError.subscribe(err => { - diagCount('ngZone.onError'); - diagEvent('ngZone.onError', { message: err?.message ?? String(err) }, true); - }); - diagEvent('probe.zone.subscriptions.installed'); - } - ngOnInit(): void { if (localStorage.getItem('theme')) { this.setTheme(localStorage.getItem('theme')); diff --git a/src/app/diagnostics.ts b/src/app/diagnostics.ts deleted file mode 100644 index f710706..0000000 --- a/src/app/diagnostics.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { NgZone } from '@angular/core'; - -type DiagEvent = { - ts: string; - name: string; - inZone: boolean; - data?: unknown; -}; - -type DiagState = { - createdAt: string; - counters: Record; - events: DiagEvent[]; - flags: Record; - lastHttp?: { - kind: string; - method?: string; - url?: string; - inZone: boolean; - ts: string; - }; - print: () => unknown; - clear: () => void; -}; - -const MAX_EVENTS = 200; - -function newDiagState(): DiagState { - const state: DiagState = { - createdAt: new Date().toISOString(), - counters: {}, - events: [], - flags: {}, - print: () => ({ - createdAt: state.createdAt, - counters: { ...state.counters }, - lastHttp: state.lastHttp, - recentEvents: state.events.slice(-20) - }), - clear: () => { - state.counters = {}; - state.events = []; - state.lastHttp = undefined; - } - }; - - return state; -} - -export function getYdmDiag(): DiagState { - const g = globalThis as any; - if (!g.__ydmDiag) { - g.__ydmDiag = newDiagState(); - } - return g.__ydmDiag as DiagState; -} - -export function diagCount(name: string, amount = 1): number { - const diag = getYdmDiag(); - diag.counters[name] = (diag.counters[name] ?? 0) + amount; - return diag.counters[name]; -} - -export function diagEvent(name: string, data?: unknown, printToConsole = false): void { - const diag = getYdmDiag(); - const entry: DiagEvent = { - ts: new Date().toISOString(), - name, - inZone: NgZone.isInAngularZone(), - data - }; - diag.events.push(entry); - if (diag.events.length > MAX_EVENTS) { - diag.events.splice(0, diag.events.length - MAX_EVENTS); - } - - if (printToConsole) { - console.log('[YDM-DIAG]', entry.name, entry); - } -} - -export function diagHttpCallback(kind: 'next' | 'error' | 'complete', method?: string, url?: string): void { - const inZone = NgZone.isInAngularZone(); - diagCount(`http.${kind}`); - diagCount(`http.inZone.${inZone ? 'true' : 'false'}`); - - const diag = getYdmDiag(); - diag.lastHttp = { - kind, - method, - url, - inZone, - ts: new Date().toISOString() - }; -} - diff --git a/src/app/http.interceptor.ts b/src/app/http.interceptor.ts index 038767c..7b20bab 100644 --- a/src/app/http.interceptor.ts +++ b/src/app/http.interceptor.ts @@ -3,8 +3,7 @@ import { inject, NgZone } from '@angular/core'; import { MatSnackBar } from '@angular/material/snack-bar'; import { Router } from '@angular/router'; import { Observable, throwError } from 'rxjs'; -import { catchError, tap } from 'rxjs/operators'; -import { diagEvent, diagHttpCallback } from './diagnostics'; +import { catchError } from 'rxjs/operators'; function runInAngularZone(source$: Observable, ngZone: NgZone): Observable { return new Observable((subscriber) => { @@ -24,11 +23,6 @@ export const h401InterceptorFn: HttpInterceptorFn = (request, next) => { const ngZone = inject(NgZone); return runInAngularZone(next(request), ngZone).pipe( - tap({ - next: () => diagHttpCallback('next', request.method, request.urlWithParams), - error: () => diagHttpCallback('error', request.method, request.urlWithParams), - complete: () => diagHttpCallback('complete', request.method, request.urlWithParams) - }), catchError((err: HttpErrorResponse) => { if (err.status === 401) { localStorage.setItem('jwt_token', null); @@ -39,12 +33,6 @@ export const h401InterceptorFn: HttpInterceptorFn = (request, next) => { } } - diagEvent('http.401Interceptor.catchError', { - method: request.method, - url: request.urlWithParams, - status: err.status - }); - const error = err?.error?.message || err?.statusText || 'Request failed'; return throwError(error); }) diff --git a/src/app/player/player.component.ts b/src/app/player/player.component.ts index df44a06..76d4176 100644 --- a/src/app/player/player.component.ts +++ b/src/app/player/player.component.ts @@ -10,7 +10,6 @@ import { TwitchChatComponent } from 'app/components/twitch-chat/twitch-chat.comp import { VideoInfoDialogComponent } from 'app/dialogs/video-info-dialog/video-info-dialog.component'; import { saveAs } from 'file-saver'; import { filter, take } from 'rxjs/operators'; -import { diagEvent } from 'app/diagnostics'; export interface IMedia { title: string; @@ -154,15 +153,7 @@ export class PlayerComponent implements OnInit, AfterViewInit, OnDestroy { this.uids = [this.db_file['uid']]; this.type = this.db_file['isAudio'] ? 'audio' as FileType : 'video' as FileType; this.parseFileNames(); - diagEvent('player.getFile.success', { - uid: this.uid, - fileUid: this.db_file?.uid, - show_player: this.show_player, - playlistLength: this.playlist?.length ?? 0, - currentSrcSet: !!this.currentItem?.src - }, true); }, err => { - diagEvent('player.getFile.error', { uid: this.uid, err: String(err) }, true); console.error(err); this.postsService.openSnackBar($localize`Failed to get file information from the server.`, 'Dismiss'); }); diff --git a/src/app/settings/settings.component.ts b/src/app/settings/settings.component.ts index 42fccb4..fd9ab0c 100644 --- a/src/app/settings/settings.component.ts +++ b/src/app/settings/settings.component.ts @@ -15,7 +15,6 @@ import { ActivatedRoute, Router } from '@angular/router'; import { Category, DBInfoResponse } from 'api-types'; import { GenerateRssUrlComponent } from 'app/dialogs/generate-rss-url/generate-rss-url.component'; import { filter, take } from 'rxjs/operators'; -import { diagEvent } from 'app/diagnostics'; type CookiesTestResponse = { success: boolean; @@ -113,13 +112,8 @@ export class SettingsComponent implements OnInit { // sets new config as old config this.initial_config = JSON.parse(JSON.stringify(this.new_config)); this.postsService.reload_config.next(true); - diagEvent('settings.save.success', { - settingsSame: this.settingsSame(), - multiUserMode: this.new_config?.Advanced?.multi_user_mode - }, true); } }, () => { - diagEvent('settings.save.error', {}, true); console.error('Failed to save config!'); }) } diff --git a/src/main.ts b/src/main.ts index c79f956..cabf9e8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,14 +6,11 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { environment } from './environments/environment'; import { loadTranslations } from '@angular/localize'; -import { getYdmDiag } from './app/diagnostics'; if (environment.production) { enableProdMode(); } -getYdmDiag(); - const locale = localStorage.getItem('locale'); if (!locale) { localStorage.setItem('locale', 'en');