Remove zone diagnostics and retire ARMv7 workflow

pull/1163/head
voc0der 2 months ago
parent d4a91ba18e
commit 15cddec357

@ -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 }}

@ -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'));

@ -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<string, number>;
events: DiagEvent[];
flags: Record<string, boolean>;
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()
};
}

@ -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<T>(source$: Observable<T>, ngZone: NgZone): Observable<T> {
return new Observable<T>((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);
})

@ -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');
});

@ -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!');
})
}

@ -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');

Loading…
Cancel
Save