diff options
author | Chocobozzz <me@florianbigard.com> | 2022-07-15 15:30:14 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2022-07-18 11:37:18 +0200 |
commit | 42b40636991b97fe818007fab19091764fc5db73 (patch) | |
tree | db431787c06ce898d22e91ff771f795219274fc6 | |
parent | 654d4ede7fa4d0faa71e49bcfab6b65a686397b2 (diff) | |
download | PeerTube-42b40636991b97fe818007fab19091764fc5db73.tar.gz PeerTube-42b40636991b97fe818007fab19091764fc5db73.tar.zst PeerTube-42b40636991b97fe818007fab19091764fc5db73.zip |
Add ability for client to create server logs
97 files changed, 828 insertions, 261 deletions
diff --git a/client/src/app/+admin/overview/users/user-list/user-list.component.ts b/client/src/app/+admin/overview/users/user-list/user-list.component.ts index 3e1a5f6b8..99987fdff 100644 --- a/client/src/app/+admin/overview/users/user-list/user-list.component.ts +++ b/client/src/app/+admin/overview/users/user-list/user-list.component.ts | |||
@@ -2,11 +2,12 @@ import { SortMeta } from 'primeng/api' | |||
2 | import { Component, OnInit, ViewChild } from '@angular/core' | 2 | import { Component, OnInit, ViewChild } from '@angular/core' |
3 | import { ActivatedRoute, Router } from '@angular/router' | 3 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { AuthService, ConfirmService, LocalStorageService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' | 4 | import { AuthService, ConfirmService, LocalStorageService, Notifier, RestPagination, RestTable, ServerService } from '@app/core' |
5 | import { prepareIcu, getAPIHost } from '@app/helpers' | 5 | import { getAPIHost, prepareIcu } from '@app/helpers' |
6 | import { AdvancedInputFilter } from '@app/shared/shared-forms' | 6 | import { AdvancedInputFilter } from '@app/shared/shared-forms' |
7 | import { Actor, DropdownAction } from '@app/shared/shared-main' | 7 | import { Actor, DropdownAction } from '@app/shared/shared-main' |
8 | import { AccountMutedStatus, BlocklistService, UserBanModalComponent, UserModerationDisplayType } from '@app/shared/shared-moderation' | 8 | import { AccountMutedStatus, BlocklistService, UserBanModalComponent, UserModerationDisplayType } from '@app/shared/shared-moderation' |
9 | import { UserAdminService } from '@app/shared/shared-users' | 9 | import { UserAdminService } from '@app/shared/shared-users' |
10 | import { logger } from '@root-helpers/logger' | ||
10 | import { User, UserRole } from '@shared/models' | 11 | import { User, UserRole } from '@shared/models' |
11 | 12 | ||
12 | type UserForList = User & { | 13 | type UserForList = User & { |
@@ -149,7 +150,7 @@ export class UserListComponent extends RestTable implements OnInit { | |||
149 | this.selectedColumns = JSON.parse(result) | 150 | this.selectedColumns = JSON.parse(result) |
150 | return | 151 | return |
151 | } catch (err) { | 152 | } catch (err) { |
152 | console.error('Cannot load selected columns.', err) | 153 | logger.error('Cannot load selected columns.', err) |
153 | } | 154 | } |
154 | } | 155 | } |
155 | 156 | ||
diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts index d39c2ea1c..b02c054a2 100644 --- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts +++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts | |||
@@ -4,6 +4,7 @@ import { Component, OnInit } from '@angular/core' | |||
4 | import { ActivatedRoute, Router } from '@angular/router' | 4 | import { ActivatedRoute, Router } from '@angular/router' |
5 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' | 5 | import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' |
6 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' | 6 | import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' |
7 | import { logger } from '@root-helpers/logger' | ||
7 | import { PeerTubePluginIndex, PluginType } from '@shared/models' | 8 | import { PeerTubePluginIndex, PluginType } from '@shared/models' |
8 | 9 | ||
9 | @Component({ | 10 | @Component({ |
@@ -94,7 +95,7 @@ export class PluginSearchComponent implements OnInit { | |||
94 | }, | 95 | }, |
95 | 96 | ||
96 | error: err => { | 97 | error: err => { |
97 | console.error(err) | 98 | logger.error(err) |
98 | 99 | ||
99 | const message = $localize`The plugin index is not available. Please retry later.` | 100 | const message = $localize`The plugin index is not available. Please retry later.` |
100 | this.notifier.error(message) | 101 | this.notifier.error(message) |
diff --git a/client/src/app/+admin/system/logs/log-row.model.ts b/client/src/app/+admin/system/logs/log-row.model.ts index 615778210..e83c7b064 100644 --- a/client/src/app/+admin/system/logs/log-row.model.ts +++ b/client/src/app/+admin/system/logs/log-row.model.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import { LogLevel } from '@shared/models' | ||
2 | import omit from 'lodash-es/omit' | 1 | import omit from 'lodash-es/omit' |
2 | import { logger } from '@root-helpers/logger' | ||
3 | import { ServerLogLevel } from '@shared/models' | ||
3 | 4 | ||
4 | export class LogRow { | 5 | export class LogRow { |
5 | date: Date | 6 | date: Date |
6 | localeDate: string | 7 | localeDate: string |
7 | level: LogLevel | 8 | level: ServerLogLevel |
8 | message: string | 9 | message: string |
9 | meta: string | 10 | meta: string |
10 | 11 | ||
@@ -33,7 +34,7 @@ export class LogRow { | |||
33 | this.meta = JSON.stringify(message, null, 2) | 34 | this.meta = JSON.stringify(message, null, 2) |
34 | this.message = '' | 35 | this.message = '' |
35 | } catch (err) { | 36 | } catch (err) { |
36 | console.error('Cannot parse audit message.', err) | 37 | logger.error('Cannot parse audit message.', err) |
37 | } | 38 | } |
38 | } | 39 | } |
39 | } | 40 | } |
diff --git a/client/src/app/+admin/system/logs/logs.component.ts b/client/src/app/+admin/system/logs/logs.component.ts index 06237522a..939e710d7 100644 --- a/client/src/app/+admin/system/logs/logs.component.ts +++ b/client/src/app/+admin/system/logs/logs.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, OnInit, ViewChild } from '@angular/core' |
2 | import { LocalStorageService, Notifier } from '@app/core' | 2 | import { LocalStorageService, Notifier } from '@app/core' |
3 | import { LogLevel } from '@shared/models' | 3 | import { ServerLogLevel } from '@shared/models' |
4 | import { LogRow } from './log-row.model' | 4 | import { LogRow } from './log-row.model' |
5 | import { LogsService } from './logs.service' | 5 | import { LogsService } from './logs.service' |
6 | 6 | ||
@@ -17,11 +17,11 @@ export class LogsComponent implements OnInit { | |||
17 | 17 | ||
18 | logs: LogRow[] = [] | 18 | logs: LogRow[] = [] |
19 | timeChoices: { id: string, label: string, dateFormat: string }[] = [] | 19 | timeChoices: { id: string, label: string, dateFormat: string }[] = [] |
20 | levelChoices: { id: LogLevel, label: string }[] = [] | 20 | levelChoices: { id: ServerLogLevel, label: string }[] = [] |
21 | logTypeChoices: { id: 'audit' | 'standard', label: string }[] = [] | 21 | logTypeChoices: { id: 'audit' | 'standard', label: string }[] = [] |
22 | 22 | ||
23 | startDate: string | 23 | startDate: string |
24 | level: LogLevel | 24 | level: ServerLogLevel |
25 | logType: 'audit' | 'standard' | 25 | logType: 'audit' | 'standard' |
26 | tagsOneOf: string[] = [] | 26 | tagsOneOf: string[] = [] |
27 | 27 | ||
diff --git a/client/src/app/+admin/system/logs/logs.service.ts b/client/src/app/+admin/system/logs/logs.service.ts index ea7e08b9b..933a074a8 100644 --- a/client/src/app/+admin/system/logs/logs.service.ts +++ b/client/src/app/+admin/system/logs/logs.service.ts | |||
@@ -3,7 +3,7 @@ import { catchError, map } from 'rxjs/operators' | |||
3 | import { HttpClient, HttpParams } from '@angular/common/http' | 3 | import { HttpClient, HttpParams } from '@angular/common/http' |
4 | import { Injectable } from '@angular/core' | 4 | import { Injectable } from '@angular/core' |
5 | import { RestExtractor, RestService } from '@app/core' | 5 | import { RestExtractor, RestService } from '@app/core' |
6 | import { LogLevel } from '@shared/models' | 6 | import { ServerLogLevel } from '@shared/models' |
7 | import { environment } from '../../../../environments/environment' | 7 | import { environment } from '../../../../environments/environment' |
8 | import { LogRow } from './log-row.model' | 8 | import { LogRow } from './log-row.model' |
9 | 9 | ||
@@ -22,7 +22,7 @@ export class LogsService { | |||
22 | isAuditLog: boolean | 22 | isAuditLog: boolean |
23 | startDate: string | 23 | startDate: string |
24 | tagsOneOf?: string[] | 24 | tagsOneOf?: string[] |
25 | level?: LogLevel | 25 | level?: ServerLogLevel |
26 | endDate?: string | 26 | endDate?: string |
27 | }): Observable<any[]> { | 27 | }): Observable<any[]> { |
28 | const { isAuditLog, startDate, endDate, tagsOneOf } = options | 28 | const { isAuditLog, startDate, endDate, tagsOneOf } = options |
diff --git a/client/src/app/+plugin-pages/plugin-pages.component.ts b/client/src/app/+plugin-pages/plugin-pages.component.ts index 973e4d021..9fe4b413e 100644 --- a/client/src/app/+plugin-pages/plugin-pages.component.ts +++ b/client/src/app/+plugin-pages/plugin-pages.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core' | 1 | import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { PluginService } from '@app/core' | 3 | import { PluginService } from '@app/core' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | 5 | ||
5 | @Component({ | 6 | @Component({ |
6 | templateUrl: './plugin-pages.component.html' | 7 | templateUrl: './plugin-pages.component.html' |
@@ -26,7 +27,7 @@ export class PluginPagesComponent implements AfterViewInit { | |||
26 | 27 | ||
27 | const registered = this.pluginService.getRegisteredClientRoute(path) | 28 | const registered = this.pluginService.getRegisteredClientRoute(path) |
28 | if (!registered) { | 29 | if (!registered) { |
29 | console.log('Could not find registered route %s.', path, this.pluginService.getAllRegisteredClientRoutes()) | 30 | logger.info(`Could not find registered route ${path}`, this.pluginService.getAllRegisteredClientRoutes()) |
30 | 31 | ||
31 | return this.router.navigate([ '/404' ], { skipLocationChange: true }) | 32 | return this.router.navigate([ '/404' ], { skipLocationChange: true }) |
32 | } | 33 | } |
diff --git a/client/src/app/+search/shared/abstract-lazy-load.resolver.ts b/client/src/app/+search/shared/abstract-lazy-load.resolver.ts index b18a5b64d..7551d977d 100644 --- a/client/src/app/+search/shared/abstract-lazy-load.resolver.ts +++ b/client/src/app/+search/shared/abstract-lazy-load.resolver.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Observable } from 'rxjs' | 1 | import { Observable } from 'rxjs' |
2 | import { map } from 'rxjs/operators' | 2 | import { map } from 'rxjs/operators' |
3 | import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router' | 3 | import { ActivatedRouteSnapshot, Resolve, Router } from '@angular/router' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { ResultList } from '@shared/models' | 5 | import { ResultList } from '@shared/models' |
5 | 6 | ||
6 | export abstract class AbstractLazyLoadResolver <T> implements Resolve<any> { | 7 | export abstract class AbstractLazyLoadResolver <T> implements Resolve<any> { |
@@ -10,7 +11,7 @@ export abstract class AbstractLazyLoadResolver <T> implements Resolve<any> { | |||
10 | const url = route.params.url | 11 | const url = route.params.url |
11 | 12 | ||
12 | if (!url) { | 13 | if (!url) { |
13 | console.error('Could not find url param.', { params: route.params }) | 14 | logger.error('Could not find url param.', { params: route.params }) |
14 | return this.router.navigateByUrl('/404') | 15 | return this.router.navigateByUrl('/404') |
15 | } | 16 | } |
16 | 17 | ||
@@ -18,7 +19,7 @@ export abstract class AbstractLazyLoadResolver <T> implements Resolve<any> { | |||
18 | .pipe( | 19 | .pipe( |
19 | map(result => { | 20 | map(result => { |
20 | if (result.data.length !== 1) { | 21 | if (result.data.length !== 1) { |
21 | console.error('Cannot find result for this URL') | 22 | logger.error('Cannot find result for this URL') |
22 | return this.router.navigateByUrl('/404') | 23 | return this.router.navigateByUrl('/404') |
23 | } | 24 | } |
24 | 25 | ||
diff --git a/client/src/app/+video-studio/edit/video-studio-edit.component.ts b/client/src/app/+video-studio/edit/video-studio-edit.component.ts index 392b65767..bf91c237a 100644 --- a/client/src/app/+video-studio/edit/video-studio-edit.component.ts +++ b/client/src/app/+video-studio/edit/video-studio-edit.component.ts | |||
@@ -4,6 +4,7 @@ import { ConfirmService, Notifier, ServerService } from '@app/core' | |||
4 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | 4 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
5 | import { VideoDetails } from '@app/shared/shared-main' | 5 | import { VideoDetails } from '@app/shared/shared-main' |
6 | import { LoadingBarService } from '@ngx-loading-bar/core' | 6 | import { LoadingBarService } from '@ngx-loading-bar/core' |
7 | import { logger } from '@root-helpers/logger' | ||
7 | import { secondsToTime } from '@shared/core-utils' | 8 | import { secondsToTime } from '@shared/core-utils' |
8 | import { VideoStudioTask, VideoStudioTaskCut } from '@shared/models' | 9 | import { VideoStudioTask, VideoStudioTaskCut } from '@shared/models' |
9 | import { VideoStudioService } from '../shared' | 10 | import { VideoStudioService } from '../shared' |
@@ -97,7 +98,7 @@ export class VideoStudioEditComponent extends FormReactive implements OnInit { | |||
97 | this.loadingBar.useRef().complete() | 98 | this.loadingBar.useRef().complete() |
98 | this.isRunningEdition = false | 99 | this.isRunningEdition = false |
99 | this.notifier.error(err.message) | 100 | this.notifier.error(err.message) |
100 | console.error(err) | 101 | logger.error(err) |
101 | } | 102 | } |
102 | }) | 103 | }) |
103 | } | 104 | } |
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts index c74ef5731..99f8c9034 100644 --- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts +++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts | |||
@@ -38,6 +38,7 @@ import { VideoCaptionAddModalComponent } from './video-caption-add-modal.compone | |||
38 | import { VideoCaptionEditModalComponent } from './video-caption-edit-modal/video-caption-edit-modal.component' | 38 | import { VideoCaptionEditModalComponent } from './video-caption-edit-modal/video-caption-edit-modal.component' |
39 | import { VideoEditType } from './video-edit.type' | 39 | import { VideoEditType } from './video-edit.type' |
40 | import { VideoSource } from '@shared/models/videos/video-source' | 40 | import { VideoSource } from '@shared/models/videos/video-source' |
41 | import { logger } from '@root-helpers/logger' | ||
41 | 42 | ||
42 | type VideoLanguages = VideoConstant<string> & { group?: string } | 43 | type VideoLanguages = VideoConstant<string> & { group?: string } |
43 | type PluginField = { | 44 | type PluginField = { |
@@ -443,7 +444,7 @@ export class VideoEditComponent implements OnInit, OnDestroy { | |||
443 | 444 | ||
444 | const oldChannel = this.userVideoChannels.find(c => c.id === oldChannelId) | 445 | const oldChannel = this.userVideoChannels.find(c => c.id === oldChannelId) |
445 | if (!newChannel || !oldChannel) { | 446 | if (!newChannel || !oldChannel) { |
446 | console.error('Cannot find new or old channel.') | 447 | logger.error('Cannot find new or old channel.') |
447 | return | 448 | return |
448 | } | 449 | } |
449 | 450 | ||
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts index 80e5a73da..91eb66931 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-go-live.component.ts | |||
@@ -7,6 +7,7 @@ import { FormValidatorService } from '@app/shared/shared-forms' | |||
7 | import { Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 7 | import { Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
8 | import { LiveVideoService } from '@app/shared/shared-video-live' | 8 | import { LiveVideoService } from '@app/shared/shared-video-live' |
9 | import { LoadingBarService } from '@ngx-loading-bar/core' | 9 | import { LoadingBarService } from '@ngx-loading-bar/core' |
10 | import { logger } from '@root-helpers/logger' | ||
10 | import { LiveVideo, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models' | 11 | import { LiveVideo, LiveVideoCreate, LiveVideoLatencyMode, LiveVideoUpdate, PeerTubeProblemDocument, ServerErrorCode } from '@shared/models' |
11 | import { VideoSend } from './video-send' | 12 | import { VideoSend } from './video-send' |
12 | 13 | ||
@@ -141,7 +142,7 @@ export class VideoGoLiveComponent extends VideoSend implements OnInit, AfterView | |||
141 | error: err => { | 142 | error: err => { |
142 | this.error = err.message | 143 | this.error = err.message |
143 | scrollToTop() | 144 | scrollToTop() |
144 | console.error(err) | 145 | logger.error(err) |
145 | } | 146 | } |
146 | }) | 147 | }) |
147 | } | 148 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts index da4996902..7b9531d27 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-torrent.component.ts | |||
@@ -6,6 +6,7 @@ import { scrollToTop } from '@app/helpers' | |||
6 | import { FormValidatorService } from '@app/shared/shared-forms' | 6 | import { FormValidatorService } from '@app/shared/shared-forms' |
7 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' | 7 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' |
8 | import { LoadingBarService } from '@ngx-loading-bar/core' | 8 | import { LoadingBarService } from '@ngx-loading-bar/core' |
9 | import { logger } from '@root-helpers/logger' | ||
9 | import { PeerTubeProblemDocument, ServerErrorCode, VideoUpdate } from '@shared/models' | 10 | import { PeerTubeProblemDocument, ServerErrorCode, VideoUpdate } from '@shared/models' |
10 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' | 11 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' |
11 | import { VideoSend } from './video-send' | 12 | import { VideoSend } from './video-send' |
@@ -139,7 +140,7 @@ export class VideoImportTorrentComponent extends VideoSend implements OnInit, Af | |||
139 | error: err => { | 140 | error: err => { |
140 | this.error = err.message | 141 | this.error = err.message |
141 | scrollToTop() | 142 | scrollToTop() |
142 | console.error(err) | 143 | logger.error(err) |
143 | } | 144 | } |
144 | }) | 145 | }) |
145 | } | 146 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts index 971a2a070..4ef7d1321 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-import-url.component.ts | |||
@@ -7,6 +7,7 @@ import { scrollToTop } from '@app/helpers' | |||
7 | import { FormValidatorService } from '@app/shared/shared-forms' | 7 | import { FormValidatorService } from '@app/shared/shared-forms' |
8 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' | 8 | import { VideoCaptionService, VideoEdit, VideoImportService, VideoService } from '@app/shared/shared-main' |
9 | import { LoadingBarService } from '@ngx-loading-bar/core' | 9 | import { LoadingBarService } from '@ngx-loading-bar/core' |
10 | import { logger } from '@root-helpers/logger' | ||
10 | import { VideoUpdate } from '@shared/models' | 11 | import { VideoUpdate } from '@shared/models' |
11 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' | 12 | import { hydrateFormFromVideo } from '../shared/video-edit-utils' |
12 | import { VideoSend } from './video-send' | 13 | import { VideoSend } from './video-send' |
@@ -128,7 +129,7 @@ export class VideoImportUrlComponent extends VideoSend implements OnInit, AfterV | |||
128 | error: err => { | 129 | error: err => { |
129 | this.error = err.message | 130 | this.error = err.message |
130 | scrollToTop() | 131 | scrollToTop() |
131 | console.error(err) | 132 | logger.error(err) |
132 | } | 133 | } |
133 | }) | 134 | }) |
134 | } | 135 | } |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts index 663955d27..66a3967c7 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts | |||
@@ -1,6 +1,5 @@ | |||
1 | import { truncate } from 'lodash-es' | 1 | import { truncate } from 'lodash-es' |
2 | import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' | 2 | import { UploadState, UploadxOptions, UploadxService } from 'ngx-uploadx' |
3 | import { isIOS } from '@root-helpers/web-browser' | ||
4 | import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' | 3 | import { HttpErrorResponse, HttpEventType, HttpHeaders } from '@angular/common/http' |
5 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' | 4 | import { AfterViewInit, Component, ElementRef, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' |
6 | import { ActivatedRoute, Router } from '@angular/router' | 5 | import { ActivatedRoute, Router } from '@angular/router' |
@@ -9,6 +8,8 @@ import { genericUploadErrorHandler, scrollToTop } from '@app/helpers' | |||
9 | import { FormValidatorService } from '@app/shared/shared-forms' | 8 | import { FormValidatorService } from '@app/shared/shared-forms' |
10 | import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 9 | import { BytesPipe, Video, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
11 | import { LoadingBarService } from '@ngx-loading-bar/core' | 10 | import { LoadingBarService } from '@ngx-loading-bar/core' |
11 | import { logger } from '@root-helpers/logger' | ||
12 | import { isIOS } from '@root-helpers/web-browser' | ||
12 | import { HttpStatusCode, VideoCreateResult } from '@shared/models' | 13 | import { HttpStatusCode, VideoCreateResult } from '@shared/models' |
13 | import { UploaderXFormData } from './uploaderx-form-data' | 14 | import { UploaderXFormData } from './uploaderx-form-data' |
14 | import { VideoSend } from './video-send' | 15 | import { VideoSend } from './video-send' |
@@ -264,7 +265,7 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy | |||
264 | error: err => { | 265 | error: err => { |
265 | this.error = err.message | 266 | this.error = err.message |
266 | scrollToTop() | 267 | scrollToTop() |
267 | console.error(err) | 268 | logger.error(err) |
268 | } | 269 | } |
269 | }) | 270 | }) |
270 | } | 271 | } |
diff --git a/client/src/app/+videos/+video-edit/video-update.component.ts b/client/src/app/+videos/+video-edit/video-update.component.ts index 13e786a8e..ed17dff06 100644 --- a/client/src/app/+videos/+video-edit/video-update.component.ts +++ b/client/src/app/+videos/+video-edit/video-update.component.ts | |||
@@ -8,9 +8,10 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | |||
8 | import { Video, VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit, VideoService } from '@app/shared/shared-main' | 8 | import { Video, VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit, VideoService } from '@app/shared/shared-main' |
9 | import { LiveVideoService } from '@app/shared/shared-video-live' | 9 | import { LiveVideoService } from '@app/shared/shared-video-live' |
10 | import { LoadingBarService } from '@ngx-loading-bar/core' | 10 | import { LoadingBarService } from '@ngx-loading-bar/core' |
11 | import { logger } from '@root-helpers/logger' | ||
11 | import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models' | 12 | import { LiveVideo, LiveVideoUpdate, VideoPrivacy } from '@shared/models' |
12 | import { hydrateFormFromVideo } from './shared/video-edit-utils' | ||
13 | import { VideoSource } from '@shared/models/videos/video-source' | 13 | import { VideoSource } from '@shared/models/videos/video-source' |
14 | import { hydrateFormFromVideo } from './shared/video-edit-utils' | ||
14 | 15 | ||
15 | @Component({ | 16 | @Component({ |
16 | selector: 'my-videos-update', | 17 | selector: 'my-videos-update', |
@@ -156,7 +157,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
156 | this.loadingBar.useRef().complete() | 157 | this.loadingBar.useRef().complete() |
157 | this.isUpdatingVideo = false | 158 | this.isUpdatingVideo = false |
158 | this.notifier.error(err.message) | 159 | this.notifier.error(err.message) |
159 | console.error(err) | 160 | logger.error(err) |
160 | } | 161 | } |
161 | }) | 162 | }) |
162 | } | 163 | } |
diff --git a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts index e002b3c22..b5444facb 100644 --- a/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts +++ b/client/src/app/+videos/+video-watch/shared/metadata/video-description.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core' | 1 | import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core' |
2 | import { MarkdownService, Notifier } from '@app/core' | 2 | import { MarkdownService, Notifier } from '@app/core' |
3 | import { VideoDetails, VideoService } from '@app/shared/shared-main' | 3 | import { VideoDetails, VideoService } from '@app/shared/shared-main' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | 5 | ||
5 | @Component({ | 6 | @Component({ |
6 | selector: 'my-video-description', | 7 | selector: 'my-video-description', |
@@ -75,7 +76,7 @@ export class VideoDescriptionComponent implements OnChanges { | |||
75 | private updateVideoDescription (description: string) { | 76 | private updateVideoDescription (description: string) { |
76 | this.video.description = description | 77 | this.video.description = description |
77 | this.setVideoDescriptionHTML() | 78 | this.setVideoDescriptionHTML() |
78 | .catch(err => console.error(err)) | 79 | .catch(err => logger.error(err)) |
79 | } | 80 | } |
80 | 81 | ||
81 | private async setVideoDescriptionHTML () { | 82 | private async setVideoDescriptionHTML () { |
diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts index 6a3bd1522..292ce6441 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts | |||
@@ -24,6 +24,7 @@ import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/sha | |||
24 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' | 24 | import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' |
25 | import { LiveVideoService } from '@app/shared/shared-video-live' | 25 | import { LiveVideoService } from '@app/shared/shared-video-live' |
26 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' | 26 | import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' |
27 | import { logger } from '@root-helpers/logger' | ||
27 | import { isP2PEnabled } from '@root-helpers/video' | 28 | import { isP2PEnabled } from '@root-helpers/video' |
28 | import { timeToInt } from '@shared/core-utils' | 29 | import { timeToInt } from '@shared/core-utils' |
29 | import { | 30 | import { |
@@ -225,7 +226,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
225 | : parseInt(positionParam + '', 10) | 226 | : parseInt(positionParam + '', 10) |
226 | 227 | ||
227 | if (isNaN(this.playlistPosition)) { | 228 | if (isNaN(this.playlistPosition)) { |
228 | console.error(`playlistPosition query param '${positionParam}' was parsed as NaN, defaulting to 1.`) | 229 | logger.error(`playlistPosition query param '${positionParam}' was parsed as NaN, defaulting to 1.`) |
229 | this.playlistPosition = 1 | 230 | this.playlistPosition = 1 |
230 | } | 231 | } |
231 | 232 | ||
@@ -378,7 +379,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
378 | } | 379 | } |
379 | 380 | ||
380 | this.buildPlayer(urlOptions, loggedInOrAnonymousUser) | 381 | this.buildPlayer(urlOptions, loggedInOrAnonymousUser) |
381 | .catch(err => console.error('Cannot build the player', err)) | 382 | .catch(err => logger.error('Cannot build the player', err)) |
382 | 383 | ||
383 | this.setOpenGraphTags() | 384 | this.setOpenGraphTags() |
384 | 385 | ||
@@ -550,7 +551,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
550 | this.player.dispose() | 551 | this.player.dispose() |
551 | this.player = undefined | 552 | this.player = undefined |
552 | } catch (err) { | 553 | } catch (err) { |
553 | console.error('Cannot dispose player.', err) | 554 | logger.error('Cannot dispose player.', err) |
554 | } | 555 | } |
555 | } | 556 | } |
556 | 557 | ||
@@ -717,7 +718,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
717 | private handleLiveStateChange (newState: VideoState) { | 718 | private handleLiveStateChange (newState: VideoState) { |
718 | if (newState !== VideoState.PUBLISHED) return | 719 | if (newState !== VideoState.PUBLISHED) return |
719 | 720 | ||
720 | console.log('Loading video after live update.') | 721 | logger.info('Loading video after live update.') |
721 | 722 | ||
722 | const videoUUID = this.video.uuid | 723 | const videoUUID = this.video.uuid |
723 | 724 | ||
@@ -728,11 +729,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
728 | 729 | ||
729 | private handleLiveViewsChange (newViewers: number) { | 730 | private handleLiveViewsChange (newViewers: number) { |
730 | if (!this.video) { | 731 | if (!this.video) { |
731 | console.error('Cannot update video live views because video is no defined.') | 732 | logger.error('Cannot update video live views because video is no defined.') |
732 | return | 733 | return |
733 | } | 734 | } |
734 | 735 | ||
735 | console.log('Updating live views.') | 736 | logger.info('Updating live views.') |
736 | 737 | ||
737 | this.video.viewers = newViewers | 738 | this.video.viewers = newViewers |
738 | } | 739 | } |
diff --git a/client/src/app/app.component.ts b/client/src/app/app.component.ts index 8fdab0c40..a2ad4806c 100644 --- a/client/src/app/app.component.ts +++ b/client/src/app/app.component.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' | 1 | import { Hotkey, HotkeysService } from 'angular2-hotkeys' |
2 | import { forkJoin, delay } from 'rxjs' | 2 | import { delay, forkJoin } from 'rxjs' |
3 | import { filter, first, map } from 'rxjs/operators' | 3 | import { filter, first, map } from 'rxjs/operators' |
4 | import { DOCUMENT, getLocaleDirection, PlatformLocation } from '@angular/common' | 4 | import { DOCUMENT, getLocaleDirection, PlatformLocation } from '@angular/common' |
5 | import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core' | 5 | import { AfterViewInit, Component, Inject, LOCALE_ID, OnInit, ViewChild } from '@angular/core' |
@@ -20,18 +20,19 @@ import { | |||
20 | import { HooksService } from '@app/core/plugins/hooks.service' | 20 | import { HooksService } from '@app/core/plugins/hooks.service' |
21 | import { PluginService } from '@app/core/plugins/plugin.service' | 21 | import { PluginService } from '@app/core/plugins/plugin.service' |
22 | import { AccountSetupWarningModalComponent } from '@app/modal/account-setup-warning-modal.component' | 22 | import { AccountSetupWarningModalComponent } from '@app/modal/account-setup-warning-modal.component' |
23 | import { AdminWelcomeModalComponent } from '@app/modal/admin-welcome-modal.component' | ||
23 | import { CustomModalComponent } from '@app/modal/custom-modal.component' | 24 | import { CustomModalComponent } from '@app/modal/custom-modal.component' |
24 | import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' | 25 | import { InstanceConfigWarningModalComponent } from '@app/modal/instance-config-warning-modal.component' |
25 | import { AdminWelcomeModalComponent } from '@app/modal/admin-welcome-modal.component' | ||
26 | import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap' | 26 | import { NgbConfig, NgbModal } from '@ng-bootstrap/ng-bootstrap' |
27 | import { LoadingBarService } from '@ngx-loading-bar/core' | 27 | import { LoadingBarService } from '@ngx-loading-bar/core' |
28 | import { logger } from '@root-helpers/logger' | ||
28 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 29 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
29 | import { getShortLocale } from '@shared/core-utils/i18n' | 30 | import { getShortLocale } from '@shared/core-utils/i18n' |
30 | import { BroadcastMessageLevel, HTMLServerConfig, UserRole } from '@shared/models' | 31 | import { BroadcastMessageLevel, HTMLServerConfig, UserRole } from '@shared/models' |
31 | import { MenuService } from './core/menu/menu.service' | 32 | import { MenuService } from './core/menu/menu.service' |
32 | import { POP_STATE_MODAL_DISMISS } from './helpers' | 33 | import { POP_STATE_MODAL_DISMISS } from './helpers' |
33 | import { InstanceService } from './shared/shared-instance' | ||
34 | import { GlobalIconName } from './shared/shared-icons' | 34 | import { GlobalIconName } from './shared/shared-icons' |
35 | import { InstanceService } from './shared/shared-instance' | ||
35 | 36 | ||
36 | @Component({ | 37 | @Component({ |
37 | selector: 'my-app', | 38 | selector: 'my-app', |
@@ -221,7 +222,7 @@ export class AppComponent implements OnInit, AfterViewInit { | |||
221 | /* eslint-disable no-eval */ | 222 | /* eslint-disable no-eval */ |
222 | eval(this.serverConfig.instance.customizations.javascript) | 223 | eval(this.serverConfig.instance.customizations.javascript) |
223 | } catch (err) { | 224 | } catch (err) { |
224 | console.error('Cannot eval custom JavaScript.', err) | 225 | logger.error('Cannot eval custom JavaScript.', err) |
225 | } | 226 | } |
226 | } | 227 | } |
227 | } | 228 | } |
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts index 2ac88c185..ece6bc5d1 100644 --- a/client/src/app/core/auth/auth.service.ts +++ b/client/src/app/core/auth/auth.service.ts | |||
@@ -5,7 +5,7 @@ import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http' | |||
5 | import { Injectable } from '@angular/core' | 5 | import { Injectable } from '@angular/core' |
6 | import { Router } from '@angular/router' | 6 | import { Router } from '@angular/router' |
7 | import { Notifier } from '@app/core/notification/notifier.service' | 7 | import { Notifier } from '@app/core/notification/notifier.service' |
8 | import { objectToUrlEncoded, peertubeLocalStorage, UserTokens } from '@root-helpers/index' | 8 | import { logger, objectToUrlEncoded, peertubeLocalStorage, UserTokens } from '@root-helpers/index' |
9 | import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' | 9 | import { HttpStatusCode, MyUser as UserServerModel, OAuthClientLocal, User, UserLogin, UserRefreshToken } from '@shared/models' |
10 | import { environment } from '../../../environments/environment' | 10 | import { environment } from '../../../environments/environment' |
11 | import { RestExtractor } from '../rest/rest-extractor.service' | 11 | import { RestExtractor } from '../rest/rest-extractor.service' |
@@ -90,7 +90,7 @@ export class AuthService { | |||
90 | peertubeLocalStorage.setItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID, this.clientId) | 90 | peertubeLocalStorage.setItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID, this.clientId) |
91 | peertubeLocalStorage.setItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_SECRET, this.clientSecret) | 91 | peertubeLocalStorage.setItem(AuthService.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_SECRET, this.clientSecret) |
92 | 92 | ||
93 | console.log('Client credentials loaded.') | 93 | logger.info('Client credentials loaded.') |
94 | }, | 94 | }, |
95 | 95 | ||
96 | error: err => { | 96 | error: err => { |
@@ -177,7 +177,7 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
177 | } | 177 | } |
178 | }, | 178 | }, |
179 | 179 | ||
180 | error: err => console.error(err) | 180 | error: err => logger.error(err) |
181 | }) | 181 | }) |
182 | 182 | ||
183 | this.user = null | 183 | this.user = null |
@@ -190,7 +190,7 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
190 | refreshAccessToken () { | 190 | refreshAccessToken () { |
191 | if (this.refreshingTokenObservable) return this.refreshingTokenObservable | 191 | if (this.refreshingTokenObservable) return this.refreshingTokenObservable |
192 | 192 | ||
193 | console.log('Refreshing token...') | 193 | logger.info('Refreshing token...') |
194 | 194 | ||
195 | const refreshToken = this.getRefreshToken() | 195 | const refreshToken = this.getRefreshToken() |
196 | 196 | ||
@@ -212,8 +212,8 @@ Ensure you have correctly configured PeerTube (config/ directory), in particular | |||
212 | catchError(err => { | 212 | catchError(err => { |
213 | this.refreshingTokenObservable = null | 213 | this.refreshingTokenObservable = null |
214 | 214 | ||
215 | console.error(err) | 215 | logger.error(err) |
216 | console.log('Cannot refresh token -> logout...') | 216 | logger.info('Cannot refresh token -> logout...') |
217 | this.logout() | 217 | this.logout() |
218 | this.router.navigate([ '/login' ]) | 218 | this.router.navigate([ '/login' ]) |
219 | 219 | ||
diff --git a/client/src/app/core/notification/notifier.service.ts b/client/src/app/core/notification/notifier.service.ts index 165bb0c76..15af5c1b6 100644 --- a/client/src/app/core/notification/notifier.service.ts +++ b/client/src/app/core/notification/notifier.service.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { MessageService } from 'primeng/api' | 1 | import { MessageService } from 'primeng/api' |
2 | import { Injectable } from '@angular/core' | 2 | import { Injectable } from '@angular/core' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | 4 | ||
4 | @Injectable() | 5 | @Injectable() |
5 | export class Notifier { | 6 | export class Notifier { |
@@ -10,21 +11,21 @@ export class Notifier { | |||
10 | info (text: string, title?: string, timeout?: number, sticky?: boolean) { | 11 | info (text: string, title?: string, timeout?: number, sticky?: boolean) { |
11 | if (!title) title = $localize`Info` | 12 | if (!title) title = $localize`Info` |
12 | 13 | ||
13 | console.info(`${title}: ${text}`) | 14 | logger.info(`${title}: ${text}`) |
14 | return this.notify('info', text, title, timeout, sticky) | 15 | return this.notify('info', text, title, timeout, sticky) |
15 | } | 16 | } |
16 | 17 | ||
17 | error (text: string, title?: string, timeout?: number, sticky?: boolean) { | 18 | error (text: string, title?: string, timeout?: number, sticky?: boolean) { |
18 | if (!title) title = $localize`Error` | 19 | if (!title) title = $localize`Error` |
19 | 20 | ||
20 | console.error(`${title}: ${text}`) | 21 | logger.error(`${title}: ${text}`) |
21 | return this.notify('error', text, title, timeout, sticky) | 22 | return this.notify('error', text, title, timeout, sticky) |
22 | } | 23 | } |
23 | 24 | ||
24 | success (text: string, title?: string, timeout?: number, sticky?: boolean) { | 25 | success (text: string, title?: string, timeout?: number, sticky?: boolean) { |
25 | if (!title) title = $localize`Success` | 26 | if (!title) title = $localize`Success` |
26 | 27 | ||
27 | console.log(`${title}: ${text}`) | 28 | logger.info(`${title}: ${text}`) |
28 | return this.notify('success', text, title, timeout, sticky) | 29 | return this.notify('success', text, title, timeout, sticky) |
29 | } | 30 | } |
30 | 31 | ||
diff --git a/client/src/app/core/plugins/hooks.service.ts b/client/src/app/core/plugins/hooks.service.ts index 062083fd1..7fd56d92e 100644 --- a/client/src/app/core/plugins/hooks.service.ts +++ b/client/src/app/core/plugins/hooks.service.ts | |||
@@ -2,6 +2,7 @@ import { from, Observable } from 'rxjs' | |||
2 | import { mergeMap, switchMap } from 'rxjs/operators' | 2 | import { mergeMap, switchMap } from 'rxjs/operators' |
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { PluginService } from '@app/core/plugins/plugin.service' | 4 | import { PluginService } from '@app/core/plugins/plugin.service' |
5 | import { logger } from '@root-helpers/logger' | ||
5 | import { ClientActionHookName, ClientFilterHookName, PluginClientScope } from '@shared/models' | 6 | import { ClientActionHookName, ClientFilterHookName, PluginClientScope } from '@shared/models' |
6 | import { AuthService, AuthStatus } from '../auth' | 7 | import { AuthService, AuthStatus } from '../auth' |
7 | 8 | ||
@@ -50,7 +51,7 @@ export class HooksService { | |||
50 | runAction<T, U extends ClientActionHookName> (hookName: U, scope: PluginClientScope, params?: T) { | 51 | runAction<T, U extends ClientActionHookName> (hookName: U, scope: PluginClientScope, params?: T) { |
51 | this.pluginService.ensurePluginsAreLoaded(scope) | 52 | this.pluginService.ensurePluginsAreLoaded(scope) |
52 | .then(() => this.pluginService.runHook(hookName, undefined, params)) | 53 | .then(() => this.pluginService.runHook(hookName, undefined, params)) |
53 | .catch((err: any) => console.error('Fatal hook error.', { err })) | 54 | .catch((err: any) => logger.error('Fatal hook error.', err)) |
54 | } | 55 | } |
55 | 56 | ||
56 | async wrapObject<T, U extends ClientFilterHookName> (result: T, scope: PluginClientScope, hookName: U) { | 57 | async wrapObject<T, U extends ClientFilterHookName> (result: T, scope: PluginClientScope, hookName: U) { |
diff --git a/client/src/app/core/rest/rest-extractor.service.ts b/client/src/app/core/rest/rest-extractor.service.ts index 86c7484a5..8a2974563 100644 --- a/client/src/app/core/rest/rest-extractor.service.ts +++ b/client/src/app/core/rest/rest-extractor.service.ts | |||
@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core' | |||
3 | import { Router } from '@angular/router' | 3 | import { Router } from '@angular/router' |
4 | import { dateToHuman } from '@app/helpers' | 4 | import { dateToHuman } from '@app/helpers' |
5 | import { HttpStatusCode, ResultList } from '@shared/models' | 5 | import { HttpStatusCode, ResultList } from '@shared/models' |
6 | import { logger } from '@root-helpers/logger' | ||
6 | 7 | ||
7 | @Injectable() | 8 | @Injectable() |
8 | export class RestExtractor { | 9 | export class RestExtractor { |
@@ -64,7 +65,7 @@ export class RestExtractor { | |||
64 | if (err.error instanceof Error) { | 65 | if (err.error instanceof Error) { |
65 | // A client-side or network error occurred. Handle it accordingly. | 66 | // A client-side or network error occurred. Handle it accordingly. |
66 | const errorMessage = err.error.detail || err.error.title | 67 | const errorMessage = err.error.detail || err.error.title |
67 | console.error('An error occurred:', errorMessage) | 68 | logger.error('An error occurred:', errorMessage) |
68 | 69 | ||
69 | return errorMessage | 70 | return errorMessage |
70 | } | 71 | } |
@@ -75,12 +76,12 @@ export class RestExtractor { | |||
75 | 76 | ||
76 | if (err.status !== undefined) { | 77 | if (err.status !== undefined) { |
77 | const errorMessage = this.buildServerErrorMessage(err) | 78 | const errorMessage = this.buildServerErrorMessage(err) |
78 | console.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`) | 79 | logger.error(`Backend returned code ${err.status}, errorMessage is: ${errorMessage}`) |
79 | 80 | ||
80 | return errorMessage | 81 | return errorMessage |
81 | } | 82 | } |
82 | 83 | ||
83 | console.error(err) | 84 | logger.error(err) |
84 | return err | 85 | return err |
85 | } | 86 | } |
86 | 87 | ||
diff --git a/client/src/app/core/rest/rest-table.ts b/client/src/app/core/rest/rest-table.ts index cb5bd0b89..ec5646b5d 100644 --- a/client/src/app/core/rest/rest-table.ts +++ b/client/src/app/core/rest/rest-table.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import * as debug from 'debug' | 1 | import debug from 'debug' |
2 | import { LazyLoadEvent, SortMeta } from 'primeng/api' | 2 | import { LazyLoadEvent, SortMeta } from 'primeng/api' |
3 | import { ActivatedRoute, Router } from '@angular/router' | 3 | import { ActivatedRoute, Router } from '@angular/router' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 5 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
5 | import { RestPagination } from './rest-pagination' | 6 | import { RestPagination } from './rest-pagination' |
6 | 7 | ||
7 | const logger = debug('peertube:tables:RestTable') | 8 | const debugLogger = debug('peertube:tables:RestTable') |
8 | 9 | ||
9 | export abstract class RestTable { | 10 | export abstract class RestTable { |
10 | 11 | ||
@@ -34,7 +35,7 @@ export abstract class RestTable { | |||
34 | try { | 35 | try { |
35 | this.sort = JSON.parse(result) | 36 | this.sort = JSON.parse(result) |
36 | } catch (err) { | 37 | } catch (err) { |
37 | console.error('Cannot load sort of local storage key ' + this.getSortLocalStorageKey(), err) | 38 | logger.error('Cannot load sort of local storage key ' + this.getSortLocalStorageKey(), err) |
38 | } | 39 | } |
39 | } | 40 | } |
40 | } | 41 | } |
@@ -44,7 +45,7 @@ export abstract class RestTable { | |||
44 | } | 45 | } |
45 | 46 | ||
46 | loadLazy (event: LazyLoadEvent) { | 47 | loadLazy (event: LazyLoadEvent) { |
47 | logger('Load lazy %o.', event) | 48 | debugLogger('Load lazy %o.', event) |
48 | 49 | ||
49 | this.sort = { | 50 | this.sort = { |
50 | order: event.sortOrder, | 51 | order: event.sortOrder, |
diff --git a/client/src/app/core/rest/rest.service.ts b/client/src/app/core/rest/rest.service.ts index fc729f0f6..d8b5ffb18 100644 --- a/client/src/app/core/rest/rest.service.ts +++ b/client/src/app/core/rest/rest.service.ts | |||
@@ -5,7 +5,7 @@ import { Injectable } from '@angular/core' | |||
5 | import { ComponentPaginationLight } from './component-pagination.model' | 5 | import { ComponentPaginationLight } from './component-pagination.model' |
6 | import { RestPagination } from './rest-pagination' | 6 | import { RestPagination } from './rest-pagination' |
7 | 7 | ||
8 | const logger = debug('peertube:rest') | 8 | const debugLogger = debug('peertube:rest') |
9 | 9 | ||
10 | interface QueryStringFilterPrefixes { | 10 | interface QueryStringFilterPrefixes { |
11 | [key: string]: { | 11 | [key: string]: { |
@@ -88,7 +88,7 @@ export class RestService { | |||
88 | const prefixeStrings = Object.values(prefixes) | 88 | const prefixeStrings = Object.values(prefixes) |
89 | .map(p => p.prefix) | 89 | .map(p => p.prefix) |
90 | 90 | ||
91 | logger(`Built tokens "${tokens.join(', ')}" for prefixes "${prefixeStrings.join(', ')}"`) | 91 | debugLogger(`Built tokens "${tokens.join(', ')}" for prefixes "${prefixeStrings.join(', ')}"`) |
92 | 92 | ||
93 | // Search is the querystring minus defined filters | 93 | // Search is the querystring minus defined filters |
94 | const searchTokens = tokens.filter(t => { | 94 | const searchTokens = tokens.filter(t => { |
@@ -127,7 +127,7 @@ export class RestService { | |||
127 | 127 | ||
128 | const search = searchTokens.join(' ') || undefined | 128 | const search = searchTokens.join(' ') || undefined |
129 | 129 | ||
130 | logger('Built search: ' + search, additionalFilters) | 130 | debugLogger('Built search: ' + search, additionalFilters) |
131 | 131 | ||
132 | return { | 132 | return { |
133 | search, | 133 | search, |
diff --git a/client/src/app/core/routing/custom-reuse-strategy.ts b/client/src/app/core/routing/custom-reuse-strategy.ts index 5d3ad2e67..269b9d193 100644 --- a/client/src/app/core/routing/custom-reuse-strategy.ts +++ b/client/src/app/core/routing/custom-reuse-strategy.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { ComponentRef, Injectable } from '@angular/core' | 1 | import { ComponentRef, Injectable } from '@angular/core' |
2 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' | 2 | import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | import { DisableForReuseHook } from './disable-for-reuse-hook' | 4 | import { DisableForReuseHook } from './disable-for-reuse-hook' |
4 | import { PeerTubeRouterService, RouterSetting } from './peertube-router.service' | 5 | import { PeerTubeRouterService, RouterSetting } from './peertube-router.service' |
5 | 6 | ||
@@ -22,7 +23,7 @@ export class CustomReuseStrategy implements RouteReuseStrategy { | |||
22 | const key = this.generateKey(route) | 23 | const key = this.generateKey(route) |
23 | this.recentlyUsed = key | 24 | this.recentlyUsed = key |
24 | 25 | ||
25 | console.log('Storing component %s to reuse later.', key) | 26 | logger.info(`Storing component ${key} to reuse later.`) |
26 | 27 | ||
27 | const componentRef = (handle as any).componentRef as ComponentRef<DisableForReuseHook> | 28 | const componentRef = (handle as any).componentRef as ComponentRef<DisableForReuseHook> |
28 | componentRef.instance.disableForReuse() | 29 | componentRef.instance.disableForReuse() |
@@ -46,7 +47,7 @@ export class CustomReuseStrategy implements RouteReuseStrategy { | |||
46 | const key = this.generateKey(route) | 47 | const key = this.generateKey(route) |
47 | this.recentlyUsed = key | 48 | this.recentlyUsed = key |
48 | 49 | ||
49 | console.log('Reusing component %s.', key) | 50 | logger.info(`Reusing component ${key}.`) |
50 | 51 | ||
51 | const handle = this.storedRouteHandles.get(key) | 52 | const handle = this.storedRouteHandles.get(key) |
52 | if (!handle) return handle; | 53 | if (!handle) return handle; |
@@ -66,7 +67,7 @@ export class CustomReuseStrategy implements RouteReuseStrategy { | |||
66 | this.storedRouteHandles.forEach((r, key) => { | 67 | this.storedRouteHandles.forEach((r, key) => { |
67 | if (key === this.recentlyUsed) return | 68 | if (key === this.recentlyUsed) return |
68 | 69 | ||
69 | console.log('Removing stored component %s.', key); | 70 | logger.info(`Removing stored component ${key}`); |
70 | 71 | ||
71 | (r as any).componentRef.destroy() | 72 | (r as any).componentRef.destroy() |
72 | this.storedRouteHandles.delete(key) | 73 | this.storedRouteHandles.delete(key) |
diff --git a/client/src/app/core/routing/redirect.service.ts b/client/src/app/core/routing/redirect.service.ts index 567fd432b..575b3b2a1 100644 --- a/client/src/app/core/routing/redirect.service.ts +++ b/client/src/app/core/routing/redirect.service.ts | |||
@@ -1,10 +1,11 @@ | |||
1 | import * as debug from 'debug' | 1 | import * as debug from 'debug' |
2 | import { Injectable } from '@angular/core' | 2 | import { Injectable } from '@angular/core' |
3 | import { NavigationCancel, NavigationEnd, Router } from '@angular/router' | 3 | import { NavigationCancel, NavigationEnd, Router } from '@angular/router' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { ServerService } from '../server' | 5 | import { ServerService } from '../server' |
5 | import { SessionStorageService } from '../wrappers/storage.service' | 6 | import { SessionStorageService } from '../wrappers/storage.service' |
6 | 7 | ||
7 | const logger = debug('peertube:router:RedirectService') | 8 | const debugLogger = debug('peertube:router:RedirectService') |
8 | 9 | ||
9 | @Injectable() | 10 | @Injectable() |
10 | export class RedirectService { | 11 | export class RedirectService { |
@@ -40,7 +41,7 @@ export class RedirectService { | |||
40 | this.latestSessionUrl = this.storage.getItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) | 41 | this.latestSessionUrl = this.storage.getItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) |
41 | this.storage.removeItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) | 42 | this.storage.removeItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY) |
42 | 43 | ||
43 | logger('Loaded latest session URL %s', this.latestSessionUrl) | 44 | debugLogger('Loaded latest session URL %s', this.latestSessionUrl) |
44 | 45 | ||
45 | // Track previous url | 46 | // Track previous url |
46 | this.currentUrl = this.router.url | 47 | this.currentUrl = this.router.url |
@@ -51,8 +52,8 @@ export class RedirectService { | |||
51 | this.previousUrl = this.currentUrl | 52 | this.previousUrl = this.currentUrl |
52 | this.currentUrl = event.url | 53 | this.currentUrl = event.url |
53 | 54 | ||
54 | logger('Previous URL is %s, current URL is %s', this.previousUrl, this.currentUrl) | 55 | debugLogger('Previous URL is %s, current URL is %s', this.previousUrl, this.currentUrl) |
55 | logger('Setting %s as latest URL in session storage.', this.currentUrl) | 56 | debugLogger('Setting %s as latest URL in session storage.', this.currentUrl) |
56 | 57 | ||
57 | this.storage.setItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY, this.currentUrl) | 58 | this.storage.setItem(RedirectService.SESSION_STORAGE_LATEST_SESSION_URL_KEY, this.currentUrl) |
58 | } | 59 | } |
@@ -84,18 +85,14 @@ export class RedirectService { | |||
84 | 85 | ||
85 | this.redirectingToHomepage = true | 86 | this.redirectingToHomepage = true |
86 | 87 | ||
87 | console.log('Redirecting to %s...', this.defaultRoute) | 88 | logger.info(`Redirecting to ${this.defaultRoute}...`) |
88 | 89 | ||
89 | this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) | 90 | this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) |
90 | .then(() => this.redirectingToHomepage = false) | 91 | .then(() => this.redirectingToHomepage = false) |
91 | .catch(() => { | 92 | .catch(() => { |
92 | this.redirectingToHomepage = false | 93 | this.redirectingToHomepage = false |
93 | 94 | ||
94 | console.error( | 95 | logger.error(`Cannot navigate to ${this.defaultRoute}, resetting default route to ${RedirectService.INIT_DEFAULT_ROUTE}`) |
95 | 'Cannot navigate to %s, resetting default route to %s.', | ||
96 | this.defaultRoute, | ||
97 | RedirectService.INIT_DEFAULT_ROUTE | ||
98 | ) | ||
99 | 96 | ||
100 | this.defaultRoute = RedirectService.INIT_DEFAULT_ROUTE | 97 | this.defaultRoute = RedirectService.INIT_DEFAULT_ROUTE |
101 | return this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) | 98 | return this.router.navigateByUrl(this.defaultRoute, { skipLocationChange }) |
@@ -104,18 +101,18 @@ export class RedirectService { | |||
104 | } | 101 | } |
105 | 102 | ||
106 | private doRedirect (redirectUrl: string, fallbackRoute?: string) { | 103 | private doRedirect (redirectUrl: string, fallbackRoute?: string) { |
107 | logger('Redirecting on %s', redirectUrl) | 104 | debugLogger('Redirecting on %s', redirectUrl) |
108 | 105 | ||
109 | if (this.isValidRedirection(redirectUrl)) { | 106 | if (this.isValidRedirection(redirectUrl)) { |
110 | return this.router.navigateByUrl(redirectUrl) | 107 | return this.router.navigateByUrl(redirectUrl) |
111 | } | 108 | } |
112 | 109 | ||
113 | logger('%s is not a valid redirection, try fallback route %s', redirectUrl, fallbackRoute) | 110 | debugLogger('%s is not a valid redirection, try fallback route %s', redirectUrl, fallbackRoute) |
114 | if (fallbackRoute) { | 111 | if (fallbackRoute) { |
115 | return this.router.navigateByUrl(fallbackRoute) | 112 | return this.router.navigateByUrl(fallbackRoute) |
116 | } | 113 | } |
117 | 114 | ||
118 | logger('There was no fallback route, redirecting to homepage') | 115 | debugLogger('There was no fallback route, redirecting to homepage') |
119 | return this.redirectToHomepage() | 116 | return this.redirectToHomepage() |
120 | } | 117 | } |
121 | 118 | ||
diff --git a/client/src/app/core/routing/scroll.service.ts b/client/src/app/core/routing/scroll.service.ts index 6d37fde71..0966255b3 100644 --- a/client/src/app/core/routing/scroll.service.ts +++ b/client/src/app/core/routing/scroll.service.ts | |||
@@ -4,8 +4,9 @@ import { ViewportScroller } from '@angular/common' | |||
4 | import { Injectable } from '@angular/core' | 4 | import { Injectable } from '@angular/core' |
5 | import { RouterSetting } from '../' | 5 | import { RouterSetting } from '../' |
6 | import { PeerTubeRouterService } from './peertube-router.service' | 6 | import { PeerTubeRouterService } from './peertube-router.service' |
7 | import { logger } from '@root-helpers/logger' | ||
7 | 8 | ||
8 | const logger = debug('peertube:main:ScrollService') | 9 | const debugLogger = debug('peertube:main:ScrollService') |
9 | 10 | ||
10 | @Injectable() | 11 | @Injectable() |
11 | export class ScrollService { | 12 | export class ScrollService { |
@@ -57,8 +58,8 @@ export class ScrollService { | |||
57 | if (nextSearchParams.toString() !== previousSearchParams.toString()) { | 58 | if (nextSearchParams.toString() !== previousSearchParams.toString()) { |
58 | this.resetScroll = true | 59 | this.resetScroll = true |
59 | } | 60 | } |
60 | } catch (e) { | 61 | } catch (err) { |
61 | console.error('Cannot parse URL to check next scroll.', e) | 62 | logger.error('Cannot parse URL to check next scroll.', err) |
62 | this.resetScroll = true | 63 | this.resetScroll = true |
63 | } | 64 | } |
64 | }) | 65 | }) |
@@ -67,7 +68,7 @@ export class ScrollService { | |||
67 | private consumeScroll () { | 68 | private consumeScroll () { |
68 | // Handle anchors/restore position | 69 | // Handle anchors/restore position |
69 | this.peertubeRouter.getScrollEvents().subscribe(e => { | 70 | this.peertubeRouter.getScrollEvents().subscribe(e => { |
70 | logger('Will schedule scroll after router event %o.', { e, resetScroll: this.resetScroll }) | 71 | debugLogger('Will schedule scroll after router event %o.', { e, resetScroll: this.resetScroll }) |
71 | 72 | ||
72 | // scrollToAnchor first to preserve anchor position when using history navigation | 73 | // scrollToAnchor first to preserve anchor position when using history navigation |
73 | if (e.anchor) { | 74 | if (e.anchor) { |
diff --git a/client/src/app/core/server/server.service.ts b/client/src/app/core/server/server.service.ts index d01942139..9db455cb8 100644 --- a/client/src/app/core/server/server.service.ts +++ b/client/src/app/core/server/server.service.ts | |||
@@ -3,6 +3,7 @@ import { first, map, share, shareReplay, switchMap, tap } from 'rxjs/operators' | |||
3 | import { HttpClient } from '@angular/common/http' | 3 | import { HttpClient } from '@angular/common/http' |
4 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' | 4 | import { Inject, Injectable, LOCALE_ID } from '@angular/core' |
5 | import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' | 5 | import { getDevLocale, isOnDevLocale, sortBy } from '@app/helpers' |
6 | import { logger } from '@root-helpers/logger' | ||
6 | import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' | 7 | import { getCompleteLocale, isDefaultLocale, peertubeTranslate } from '@shared/core-utils/i18n' |
7 | import { HTMLServerConfig, ServerConfig, ServerStats, VideoConstant } from '@shared/models' | 8 | import { HTMLServerConfig, ServerConfig, ServerStats, VideoConstant } from '@shared/models' |
8 | import { environment } from '../../../environments/environment' | 9 | import { environment } from '../../../environments/environment' |
@@ -43,7 +44,7 @@ export class ServerService { | |||
43 | } catch (err) { | 44 | } catch (err) { |
44 | // Expected in dev mode since we can't inject the config in the HTML | 45 | // Expected in dev mode since we can't inject the config in the HTML |
45 | if (environment.production !== false) { | 46 | if (environment.production !== false) { |
46 | console.error('Cannot load config locally. Fallback to API.') | 47 | logger.error('Cannot load config locally. Fallback to API.') |
47 | } | 48 | } |
48 | 49 | ||
49 | return this.getConfig() | 50 | return this.getConfig() |
diff --git a/client/src/app/core/theme/theme.service.ts b/client/src/app/core/theme/theme.service.ts index 40939ecb8..ead1770ba 100644 --- a/client/src/app/core/theme/theme.service.ts +++ b/client/src/app/core/theme/theme.service.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { Injectable } from '@angular/core' | 1 | import { Injectable } from '@angular/core' |
2 | import { logger } from '@root-helpers/logger' | ||
2 | import { capitalizeFirstLetter } from '@root-helpers/string' | 3 | import { capitalizeFirstLetter } from '@root-helpers/string' |
3 | import { UserLocalStorageKeys } from '@root-helpers/users' | 4 | import { UserLocalStorageKeys } from '@root-helpers/users' |
4 | import { HTMLServerConfig, ServerConfigTheme } from '@shared/models' | 5 | import { HTMLServerConfig, ServerConfigTheme } from '@shared/models' |
@@ -57,7 +58,7 @@ export class ThemeService { | |||
57 | private injectThemes (themes: ServerConfigTheme[], fromLocalStorage = false) { | 58 | private injectThemes (themes: ServerConfigTheme[], fromLocalStorage = false) { |
58 | this.themes = themes | 59 | this.themes = themes |
59 | 60 | ||
60 | console.log('Injecting %d themes.', this.themes.length) | 61 | logger.info(`Injecting ${this.themes.length} themes.`) |
61 | 62 | ||
62 | const head = this.getHeadElement() | 63 | const head = this.getHeadElement() |
63 | 64 | ||
@@ -117,13 +118,13 @@ export class ThemeService { | |||
117 | 118 | ||
118 | const currentTheme = this.getCurrentTheme() | 119 | const currentTheme = this.getCurrentTheme() |
119 | 120 | ||
120 | console.log('Enabling %s theme.', currentTheme) | 121 | logger.info(`Enabling ${currentTheme} theme.`) |
121 | 122 | ||
122 | this.loadTheme(currentTheme) | 123 | this.loadTheme(currentTheme) |
123 | 124 | ||
124 | const theme = this.getTheme(currentTheme) | 125 | const theme = this.getTheme(currentTheme) |
125 | if (theme) { | 126 | if (theme) { |
126 | console.log('Adding scripts of theme %s.', currentTheme) | 127 | logger.info(`Adding scripts of theme ${currentTheme}`) |
127 | 128 | ||
128 | this.pluginService.addPlugin(theme, true) | 129 | this.pluginService.addPlugin(theme, true) |
129 | 130 | ||
@@ -165,7 +166,7 @@ export class ThemeService { | |||
165 | this.injectThemes([ lastActiveTheme ], true) | 166 | this.injectThemes([ lastActiveTheme ], true) |
166 | this.updateCurrentTheme() | 167 | this.updateCurrentTheme() |
167 | } catch (err) { | 168 | } catch (err) { |
168 | console.error('Cannot parse last active theme.', err) | 169 | logger.error('Cannot parse last active theme.', err) |
169 | return | 170 | return |
170 | } | 171 | } |
171 | } | 172 | } |
@@ -173,7 +174,7 @@ export class ThemeService { | |||
173 | private removeThemePlugins (themeName: string) { | 174 | private removeThemePlugins (themeName: string) { |
174 | const oldTheme = this.getTheme(themeName) | 175 | const oldTheme = this.getTheme(themeName) |
175 | if (oldTheme) { | 176 | if (oldTheme) { |
176 | console.log('Removing scripts of old theme %s.', themeName) | 177 | logger.info(`Removing scripts of old theme ${themeName}.`) |
177 | this.pluginService.removePlugin(oldTheme) | 178 | this.pluginService.removePlugin(oldTheme) |
178 | } | 179 | } |
179 | } | 180 | } |
diff --git a/client/src/app/core/users/user-local-storage.service.ts b/client/src/app/core/users/user-local-storage.service.ts index d15bf735b..fff649eef 100644 --- a/client/src/app/core/users/user-local-storage.service.ts +++ b/client/src/app/core/users/user-local-storage.service.ts | |||
@@ -2,8 +2,9 @@ | |||
2 | import { filter, throttleTime } from 'rxjs' | 2 | import { filter, throttleTime } from 'rxjs' |
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { AuthService, AuthStatus } from '@app/core/auth' | 4 | import { AuthService, AuthStatus } from '@app/core/auth' |
5 | import { UserLocalStorageKeys, UserTokens } from '@root-helpers/users' | ||
6 | import { getBoolOrDefault } from '@root-helpers/local-storage-utils' | 5 | import { getBoolOrDefault } from '@root-helpers/local-storage-utils' |
6 | import { logger } from '@root-helpers/logger' | ||
7 | import { UserLocalStorageKeys, UserTokens } from '@root-helpers/users' | ||
7 | import { UserRole, UserUpdateMe } from '@shared/models' | 8 | import { UserRole, UserUpdateMe } from '@shared/models' |
8 | import { NSFWPolicyType } from '@shared/models/videos' | 9 | import { NSFWPolicyType } from '@shared/models/videos' |
9 | import { ServerService } from '../server' | 10 | import { ServerService } from '../server' |
@@ -95,7 +96,7 @@ export class UserLocalStorageService { | |||
95 | : null | 96 | : null |
96 | } catch (err) { | 97 | } catch (err) { |
97 | videoLanguages = null | 98 | videoLanguages = null |
98 | console.error('Cannot parse desired video languages from localStorage.', err) | 99 | logger.error('Cannot parse desired video languages from localStorage.', err) |
99 | } | 100 | } |
100 | 101 | ||
101 | const htmlConfig = this.server.getHTMLConfig() | 102 | const htmlConfig = this.server.getHTMLConfig() |
@@ -142,7 +143,7 @@ export class UserLocalStorageService { | |||
142 | 143 | ||
143 | this.localStorageService.setItem(key, localStorageValue) | 144 | this.localStorageService.setItem(key, localStorageValue) |
144 | } catch (err) { | 145 | } catch (err) { |
145 | console.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err) | 146 | logger.error(`Cannot set ${key}->${value} in localStorage. Likely due to a value impossible to stringify.`, err) |
146 | } | 147 | } |
147 | } | 148 | } |
148 | } | 149 | } |
diff --git a/client/src/app/header/search-typeahead.component.ts b/client/src/app/header/search-typeahead.component.ts index 0794ec8f4..d2549315c 100644 --- a/client/src/app/header/search-typeahead.component.ts +++ b/client/src/app/header/search-typeahead.component.ts | |||
@@ -4,6 +4,7 @@ import { ListKeyManager } from '@angular/cdk/a11y' | |||
4 | import { AfterViewChecked, Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core' | 4 | import { AfterViewChecked, Component, OnDestroy, OnInit, QueryList, ViewChildren } from '@angular/core' |
5 | import { ActivatedRoute, Params, Router } from '@angular/router' | 5 | import { ActivatedRoute, Params, Router } from '@angular/router' |
6 | import { AuthService, ServerService } from '@app/core' | 6 | import { AuthService, ServerService } from '@app/core' |
7 | import { logger } from '@root-helpers/logger' | ||
7 | import { HTMLServerConfig, SearchTargetType } from '@shared/models' | 8 | import { HTMLServerConfig, SearchTargetType } from '@shared/models' |
8 | import { SuggestionComponent, SuggestionPayload, SuggestionPayloadType } from './suggestion.component' | 9 | import { SuggestionComponent, SuggestionPayload, SuggestionPayloadType } from './suggestion.component' |
9 | 10 | ||
@@ -91,7 +92,7 @@ export class SearchTypeaheadComponent implements OnInit, AfterViewChecked, OnDes | |||
91 | 92 | ||
92 | const activeIndex = this.suggestionItems.toArray().findIndex(i => i.result.default === true) | 93 | const activeIndex = this.suggestionItems.toArray().findIndex(i => i.result.default === true) |
93 | if (activeIndex === -1) { | 94 | if (activeIndex === -1) { |
94 | console.error('Cannot find active index.', { suggestionItems: this.suggestionItems }) | 95 | logger.error('Cannot find active index.', { suggestionItems: this.suggestionItems }) |
95 | } | 96 | } |
96 | 97 | ||
97 | this.updateItemsState(activeIndex) | 98 | this.updateItemsState(activeIndex) |
diff --git a/client/src/app/helpers/i18n-utils.ts b/client/src/app/helpers/i18n-utils.ts index 2017a31ea..b7d73d16b 100644 --- a/client/src/app/helpers/i18n-utils.ts +++ b/client/src/app/helpers/i18n-utils.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { environment } from '../../environments/environment' | ||
2 | import IntlMessageFormat from 'intl-messageformat' | 1 | import IntlMessageFormat from 'intl-messageformat' |
2 | import { logger } from '@root-helpers/logger' | ||
3 | import { environment } from '../../environments/environment' | ||
3 | 4 | ||
4 | function isOnDevLocale () { | 5 | function isOnDevLocale () { |
5 | return environment.production === false && window.location.search === '?lang=fr' | 6 | return environment.production === false && window.location.search === '?lang=fr' |
@@ -19,14 +20,14 @@ function prepareIcu (icu: string) { | |||
19 | try { | 20 | try { |
20 | return msg.format(context) as string | 21 | return msg.format(context) as string |
21 | } catch (err) { | 22 | } catch (err) { |
22 | if (!alreadyWarned) console.warn('Cannot format ICU %s.', icu, err) | 23 | if (!alreadyWarned) logger.warn(`Cannot format ICU ${icu}.`, err) |
23 | 24 | ||
24 | alreadyWarned = true | 25 | alreadyWarned = true |
25 | return fallback | 26 | return fallback |
26 | } | 27 | } |
27 | } | 28 | } |
28 | } catch (err) { | 29 | } catch (err) { |
29 | console.warn('Cannot build intl message %s.', icu, err) | 30 | logger.warn(`Cannot build intl message ${icu}.`, err) |
30 | 31 | ||
31 | return (_context: unknown, fallback: string) => fallback | 32 | return (_context: unknown, fallback: string) => fallback |
32 | } | 33 | } |
diff --git a/client/src/app/menu/menu.component.ts b/client/src/app/menu/menu.component.ts index 983f0a938..63f01df92 100644 --- a/client/src/app/menu/menu.component.ts +++ b/client/src/app/menu/menu.component.ts | |||
@@ -24,7 +24,7 @@ import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' | |||
24 | import { PluginsManager } from '@root-helpers/plugins-manager' | 24 | import { PluginsManager } from '@root-helpers/plugins-manager' |
25 | import { HTMLServerConfig, ServerConfig, UserRight, VideoConstant } from '@shared/models' | 25 | import { HTMLServerConfig, ServerConfig, UserRight, VideoConstant } from '@shared/models' |
26 | 26 | ||
27 | const logger = debug('peertube:menu:MenuComponent') | 27 | const debugLogger = debug('peertube:menu:MenuComponent') |
28 | 28 | ||
29 | @Component({ | 29 | @Component({ |
30 | selector: 'my-menu', | 30 | selector: 'my-menu', |
@@ -295,8 +295,8 @@ export class MenuComponent implements OnInit { | |||
295 | .pipe( | 295 | .pipe( |
296 | switchMap(() => this.user.computeCanSeeVideosLink(this.userService.getMyVideoQuotaUsed())) | 296 | switchMap(() => this.user.computeCanSeeVideosLink(this.userService.getMyVideoQuotaUsed())) |
297 | ).subscribe(res => { | 297 | ).subscribe(res => { |
298 | if (res === true) logger('User can see videos link.') | 298 | if (res === true) debugLogger('User can see videos link.') |
299 | else logger('User cannot see videos link.') | 299 | else debugLogger('User cannot see videos link.') |
300 | }) | 300 | }) |
301 | } | 301 | } |
302 | 302 | ||
diff --git a/client/src/app/modal/account-setup-warning-modal.component.ts b/client/src/app/modal/account-setup-warning-modal.component.ts index c4cbf92b6..b999a3407 100644 --- a/client/src/app/modal/account-setup-warning-modal.component.ts +++ b/client/src/app/modal/account-setup-warning-modal.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, ElementRef, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, ViewChild } from '@angular/core' |
2 | import { Notifier, ServerService, User, UserService } from '@app/core' | 2 | import { Notifier, ServerService, User, UserService } from '@app/core' |
3 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 3 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 5 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
@@ -71,7 +72,7 @@ export class AccountSetupWarningModalComponent { | |||
71 | 72 | ||
72 | this.userService.updateMyProfile({ noAccountSetupWarningModal: true }) | 73 | this.userService.updateMyProfile({ noAccountSetupWarningModal: true }) |
73 | .subscribe({ | 74 | .subscribe({ |
74 | next: () => console.log('We will not open the account setup modal again.'), | 75 | next: () => logger.info('We will not open the account setup modal again.'), |
75 | 76 | ||
76 | error: err => this.notifier.error(err.message) | 77 | error: err => this.notifier.error(err.message) |
77 | }) | 78 | }) |
diff --git a/client/src/app/modal/admin-welcome-modal.component.ts b/client/src/app/modal/admin-welcome-modal.component.ts index 3679f0847..7a9b89d3d 100644 --- a/client/src/app/modal/admin-welcome-modal.component.ts +++ b/client/src/app/modal/admin-welcome-modal.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, ElementRef, ViewChild } from '@angular/core' | 1 | import { Component, ElementRef, ViewChild } from '@angular/core' |
2 | import { Notifier, User, UserService } from '@app/core' | 2 | import { Notifier, User, UserService } from '@app/core' |
3 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | 3 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 5 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
@@ -42,7 +43,7 @@ export class AdminWelcomeModalComponent { | |||
42 | 43 | ||
43 | this.userService.updateMyProfile({ noWelcomeModal: true }) | 44 | this.userService.updateMyProfile({ noWelcomeModal: true }) |
44 | .subscribe({ | 45 | .subscribe({ |
45 | next: () => console.log('We will not open the welcome modal again.'), | 46 | next: () => logger.info('We will not open the welcome modal again.'), |
46 | 47 | ||
47 | error: err => this.notifier.error(err.message) | 48 | error: err => this.notifier.error(err.message) |
48 | }) | 49 | }) |
diff --git a/client/src/app/modal/custom-modal.component.ts b/client/src/app/modal/custom-modal.component.ts index 559230e04..49343ae71 100644 --- a/client/src/app/modal/custom-modal.component.ts +++ b/client/src/app/modal/custom-modal.component.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { Component, ElementRef, ViewChild, Input } from '@angular/core' | 1 | import { Component, ElementRef, Input, ViewChild } from '@angular/core' |
2 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 2 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | 4 | ||
4 | @Component({ | 5 | @Component({ |
5 | selector: 'my-custom-modal', | 6 | selector: 'my-custom-modal', |
@@ -29,7 +30,7 @@ export class CustomModalComponent { | |||
29 | confirm?: { value: string, action?: () => void } | 30 | confirm?: { value: string, action?: () => void } |
30 | }) { | 31 | }) { |
31 | if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) { | 32 | if (this.modalRef instanceof NgbModalRef && this.modalService.hasOpenModals()) { |
32 | console.error('Cannot open another custom modal, one is already opened.') | 33 | logger.error('Cannot open another custom modal, one is already opened.') |
33 | return | 34 | return |
34 | } | 35 | } |
35 | 36 | ||
diff --git a/client/src/app/modal/instance-config-warning-modal.component.ts b/client/src/app/modal/instance-config-warning-modal.component.ts index 300738a41..23c2c777e 100644 --- a/client/src/app/modal/instance-config-warning-modal.component.ts +++ b/client/src/app/modal/instance-config-warning-modal.component.ts | |||
@@ -2,6 +2,7 @@ import { Location } from '@angular/common' | |||
2 | import { Component, ElementRef, ViewChild } from '@angular/core' | 2 | import { Component, ElementRef, ViewChild } from '@angular/core' |
3 | import { Notifier, User, UserService } from '@app/core' | 3 | import { Notifier, User, UserService } from '@app/core' |
4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | 4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' |
5 | import { logger } from '@root-helpers/logger' | ||
5 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' | 6 | import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage' |
6 | import { About, ServerConfig } from '@shared/models/server' | 7 | import { About, ServerConfig } from '@shared/models/server' |
7 | 8 | ||
@@ -64,7 +65,7 @@ export class InstanceConfigWarningModalComponent { | |||
64 | 65 | ||
65 | this.userService.updateMyProfile({ noInstanceConfigWarningModal: true }) | 66 | this.userService.updateMyProfile({ noInstanceConfigWarningModal: true }) |
66 | .subscribe({ | 67 | .subscribe({ |
67 | next: () => console.log('We will not open the instance config warning modal again.'), | 68 | next: () => logger.info('We will not open the instance config warning modal again.'), |
68 | 69 | ||
69 | error: err => this.notifier.error(err.message) | 70 | error: err => this.notifier.error(err.message) |
70 | }) | 71 | }) |
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts index 8781c16f5..32d3b0093 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts +++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts | |||
@@ -8,13 +8,14 @@ import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } | |||
8 | import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main' | 8 | import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main' |
9 | import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation' | 9 | import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation' |
10 | import { VideoCommentService } from '@app/shared/shared-video-comment' | 10 | import { VideoCommentService } from '@app/shared/shared-video-comment' |
11 | import { logger } from '@root-helpers/logger' | ||
11 | import { AbuseState, AdminAbuse } from '@shared/models' | 12 | import { AbuseState, AdminAbuse } from '@shared/models' |
12 | import { AdvancedInputFilter } from '../shared-forms' | 13 | import { AdvancedInputFilter } from '../shared-forms' |
13 | import { AbuseMessageModalComponent } from './abuse-message-modal.component' | 14 | import { AbuseMessageModalComponent } from './abuse-message-modal.component' |
14 | import { ModerationCommentModalComponent } from './moderation-comment-modal.component' | 15 | import { ModerationCommentModalComponent } from './moderation-comment-modal.component' |
15 | import { ProcessedAbuse } from './processed-abuse.model' | 16 | import { ProcessedAbuse } from './processed-abuse.model' |
16 | 17 | ||
17 | const logger = debug('peertube:moderation:AbuseListTableComponent') | 18 | const debugLogger = debug('peertube:moderation:AbuseListTableComponent') |
18 | 19 | ||
19 | @Component({ | 20 | @Component({ |
20 | selector: 'my-abuse-list-table', | 21 | selector: 'my-abuse-list-table', |
@@ -158,7 +159,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit { | |||
158 | const abuse = this.abuses.find(a => a.id === event.abuseId) | 159 | const abuse = this.abuses.find(a => a.id === event.abuseId) |
159 | 160 | ||
160 | if (!abuse) { | 161 | if (!abuse) { |
161 | console.error('Cannot find abuse %d.', event.abuseId) | 162 | logger.error(`Cannot find abuse ${event.abuseId}`) |
162 | return | 163 | return |
163 | } | 164 | } |
164 | 165 | ||
@@ -177,7 +178,7 @@ export class AbuseListTableComponent extends RestTable implements OnInit { | |||
177 | } | 178 | } |
178 | 179 | ||
179 | protected reloadData () { | 180 | protected reloadData () { |
180 | logger('Loading data.') | 181 | debugLogger('Loading data.') |
181 | 182 | ||
182 | const options = { | 183 | const options = { |
183 | pagination: this.pagination, | 184 | pagination: this.pagination, |
diff --git a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts index 6c8dc6d35..d24a5d58d 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts +++ b/client/src/app/shared/shared-abuse-list/abuse-message-modal.component.ts | |||
@@ -3,6 +3,7 @@ import { AuthService, HtmlRendererService, Notifier } from '@app/core' | |||
3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | 3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' | 4 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap' |
5 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' | 5 | import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' |
6 | import { logger } from '@root-helpers/logger' | ||
6 | import { AbuseMessage, UserAbuse } from '@shared/models' | 7 | import { AbuseMessage, UserAbuse } from '@shared/models' |
7 | import { ABUSE_MESSAGE_VALIDATOR } from '../form-validators/abuse-validators' | 8 | import { ABUSE_MESSAGE_VALIDATOR } from '../form-validators/abuse-validators' |
8 | import { AbuseService } from '../shared-moderation' | 9 | import { AbuseService } from '../shared-moderation' |
@@ -72,7 +73,7 @@ export class AbuseMessageModalComponent extends FormReactive implements OnInit { | |||
72 | 73 | ||
73 | error: err => { | 74 | error: err => { |
74 | this.sendingMessage = false | 75 | this.sendingMessage = false |
75 | console.error(err) | 76 | logger.error(err) |
76 | this.notifier.error('Sorry but you cannot send this message. Please retry later') | 77 | this.notifier.error('Sorry but you cannot send this message. Please retry later') |
77 | } | 78 | } |
78 | }) | 79 | }) |
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts index a959b336d..d738a644e 100644 --- a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts +++ b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts | |||
@@ -20,6 +20,7 @@ import { | |||
20 | VideosListMarkupComponent | 20 | VideosListMarkupComponent |
21 | } from './peertube-custom-tags' | 21 | } from './peertube-custom-tags' |
22 | import { CustomMarkupComponent } from './peertube-custom-tags/shared' | 22 | import { CustomMarkupComponent } from './peertube-custom-tags/shared' |
23 | import { logger } from '@root-helpers/logger' | ||
23 | 24 | ||
24 | type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<CustomMarkupComponent> | 25 | type AngularBuilderFunction = (el: HTMLElement) => ComponentRef<CustomMarkupComponent> |
25 | type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement | 26 | type HTMLBuilderFunction = (el: HTMLElement) => HTMLElement |
@@ -70,7 +71,7 @@ export class CustomMarkupService { | |||
70 | // Insert as first child | 71 | // Insert as first child |
71 | e.insertBefore(element, e.firstChild) | 72 | e.insertBefore(element, e.firstChild) |
72 | } catch (err) { | 73 | } catch (err) { |
73 | console.error('Cannot inject component %s.', selector, err) | 74 | logger.error(`Cannot inject component ${selector}`, err) |
74 | } | 75 | } |
75 | }) | 76 | }) |
76 | } | 77 | } |
@@ -90,7 +91,7 @@ export class CustomMarkupService { | |||
90 | 91 | ||
91 | this.dynamicElementService.injectElement(e, component) | 92 | this.dynamicElementService.injectElement(e, component) |
92 | } catch (err) { | 93 | } catch (err) { |
93 | console.error('Cannot inject component %s.', selector, err) | 94 | logger.error(`Cannot inject component ${selector}`, err) |
94 | } | 95 | } |
95 | }) | 96 | }) |
96 | } | 97 | } |
diff --git a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts index d8aeaa0fa..929438749 100644 --- a/client/src/app/shared/shared-forms/advanced-input-filter.component.ts +++ b/client/src/app/shared/shared-forms/advanced-input-filter.component.ts | |||
@@ -16,7 +16,7 @@ export type AdvancedInputFilterChild = { | |||
16 | value: string | 16 | value: string |
17 | } | 17 | } |
18 | 18 | ||
19 | const logger = debug('peertube:AdvancedInputFilterComponent') | 19 | const debugLogger = debug('peertube:AdvancedInputFilterComponent') |
20 | 20 | ||
21 | @Component({ | 21 | @Component({ |
22 | selector: 'my-advanced-input-filter', | 22 | selector: 'my-advanced-input-filter', |
@@ -98,7 +98,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit { | |||
98 | .subscribe(params => { | 98 | .subscribe(params => { |
99 | const search = params.search || '' | 99 | const search = params.search || '' |
100 | 100 | ||
101 | logger('On route search change "%s".', search) | 101 | debugLogger('On route search change "%s".', search) |
102 | 102 | ||
103 | if (this.searchValue === search) return | 103 | if (this.searchValue === search) return |
104 | 104 | ||
@@ -132,7 +132,7 @@ export class AdvancedInputFilterComponent implements OnInit, AfterViewInit { | |||
132 | return | 132 | return |
133 | } | 133 | } |
134 | 134 | ||
135 | logger('On search "%s".', this.searchValue) | 135 | debugLogger('On search "%s".', this.searchValue) |
136 | 136 | ||
137 | this.search.emit(this.searchValue) | 137 | this.search.emit(this.searchValue) |
138 | } | 138 | } |
diff --git a/client/src/app/shared/shared-main/angular/defer-loading.directive.ts b/client/src/app/shared/shared-main/angular/defer-loading.directive.ts index 9a10e90e3..53d6e70ba 100644 --- a/client/src/app/shared/shared-main/angular/defer-loading.directive.ts +++ b/client/src/app/shared/shared-main/angular/defer-loading.directive.ts | |||
@@ -13,7 +13,7 @@ import { | |||
13 | ViewContainerRef | 13 | ViewContainerRef |
14 | } from '@angular/core' | 14 | } from '@angular/core' |
15 | 15 | ||
16 | const logger = debug('peertube:main:DeferLoadingDirective') | 16 | const debugLogger = debug('peertube:main:DeferLoadingDirective') |
17 | 17 | ||
18 | @Directive({ | 18 | @Directive({ |
19 | selector: '[myDeferLoading]' | 19 | selector: '[myDeferLoading]' |
@@ -52,7 +52,7 @@ export class DeferLoadingDirective implements AfterViewInit, OnDestroy { | |||
52 | load () { | 52 | load () { |
53 | if (this.isLoaded()) return | 53 | if (this.isLoaded()) return |
54 | 54 | ||
55 | logger('Loading component') | 55 | debugLogger('Loading component') |
56 | 56 | ||
57 | this.viewContainer.clear() | 57 | this.viewContainer.clear() |
58 | this.view = this.viewContainer.createEmbeddedView(this.template, {}, 0) | 58 | this.view = this.viewContainer.createEmbeddedView(this.template, {}, 0) |
diff --git a/client/src/app/shared/shared-main/misc/list-overflow.component.ts b/client/src/app/shared/shared-main/misc/list-overflow.component.ts index 541991f74..7e4e1b1d1 100644 --- a/client/src/app/shared/shared-main/misc/list-overflow.component.ts +++ b/client/src/app/shared/shared-main/misc/list-overflow.component.ts | |||
@@ -17,7 +17,7 @@ import { ScreenService } from '@app/core' | |||
17 | import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' | 17 | import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' |
18 | import * as debug from 'debug' | 18 | import * as debug from 'debug' |
19 | 19 | ||
20 | const logger = debug('peertube:main:ListOverflowItem') | 20 | const debugLogger = debug('peertube:main:ListOverflowItem') |
21 | 21 | ||
22 | export interface ListOverflowItem { | 22 | export interface ListOverflowItem { |
23 | label: string | 23 | label: string |
@@ -66,7 +66,7 @@ export class ListOverflowComponent<T extends ListOverflowItem> implements AfterV | |||
66 | let showItemsUntilIndexExcluded: number | 66 | let showItemsUntilIndexExcluded: number |
67 | let accWidth = 0 | 67 | let accWidth = 0 |
68 | 68 | ||
69 | logger('Parent width is %d', parentWidth) | 69 | debugLogger('Parent width is %d', parentWidth) |
70 | 70 | ||
71 | for (const [ index, el ] of this.itemsRendered.toArray().entries()) { | 71 | for (const [ index, el ] of this.itemsRendered.toArray().entries()) { |
72 | accWidth += el.nativeElement.getBoundingClientRect().width | 72 | accWidth += el.nativeElement.getBoundingClientRect().width |
@@ -79,7 +79,7 @@ export class ListOverflowComponent<T extends ListOverflowItem> implements AfterV | |||
79 | e.style.visibility = shouldBeVisible ? 'inherit' : 'hidden' | 79 | e.style.visibility = shouldBeVisible ? 'inherit' : 'hidden' |
80 | } | 80 | } |
81 | 81 | ||
82 | logger('Accumulated children width is %d so exclude index is %d', accWidth, showItemsUntilIndexExcluded) | 82 | debugLogger('Accumulated children width is %d so exclude index is %d', accWidth, showItemsUntilIndexExcluded) |
83 | 83 | ||
84 | this.showItemsUntilIndexExcluded = showItemsUntilIndexExcluded | 84 | this.showItemsUntilIndexExcluded = showItemsUntilIndexExcluded |
85 | this.cdr.markForCheck() | 85 | this.cdr.markForCheck() |
diff --git a/client/src/app/shared/shared-main/users/user-notification.model.ts b/client/src/app/shared/shared-main/users/user-notification.model.ts index a2367166e..bf8870a79 100644 --- a/client/src/app/shared/shared-main/users/user-notification.model.ts +++ b/client/src/app/shared/shared-main/users/user-notification.model.ts | |||
@@ -2,6 +2,7 @@ import { AuthUser } from '@app/core' | |||
2 | import { Account } from '@app/shared/shared-main/account/account.model' | 2 | import { Account } from '@app/shared/shared-main/account/account.model' |
3 | import { Actor } from '@app/shared/shared-main/account/actor.model' | 3 | import { Actor } from '@app/shared/shared-main/account/actor.model' |
4 | import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model' | 4 | import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model' |
5 | import { logger } from '@root-helpers/logger' | ||
5 | import { | 6 | import { |
6 | AbuseState, | 7 | AbuseState, |
7 | ActorInfo, | 8 | ActorInfo, |
@@ -234,7 +235,7 @@ export class UserNotification implements UserNotificationServer { | |||
234 | } | 235 | } |
235 | } catch (err) { | 236 | } catch (err) { |
236 | this.type = null | 237 | this.type = null |
237 | console.error(err) | 238 | logger.error(err) |
238 | } | 239 | } |
239 | } | 240 | } |
240 | 241 | ||
diff --git a/client/src/app/shared/shared-search/find-in-bulk.service.ts b/client/src/app/shared/shared-search/find-in-bulk.service.ts index 117685cc6..d2f8c3213 100644 --- a/client/src/app/shared/shared-search/find-in-bulk.service.ts +++ b/client/src/app/shared/shared-search/find-in-bulk.service.ts | |||
@@ -9,7 +9,7 @@ import { VideoPlaylist } from '../shared-video-playlist' | |||
9 | import { SearchService } from './search.service' | 9 | import { SearchService } from './search.service' |
10 | import { AdvancedSearch } from './advanced-search.model' | 10 | import { AdvancedSearch } from './advanced-search.model' |
11 | 11 | ||
12 | const logger = debug('peertube:search:FindInBulkService') | 12 | const debugLogger = debug('peertube:search:FindInBulkService') |
13 | 13 | ||
14 | type BulkObservables <P extends number | string, R> = { | 14 | type BulkObservables <P extends number | string, R> = { |
15 | notifier: Subject<P> | 15 | notifier: Subject<P> |
@@ -36,7 +36,7 @@ export class FindInBulkService { | |||
36 | } | 36 | } |
37 | 37 | ||
38 | getVideo (uuid: string): Observable<Video> { | 38 | getVideo (uuid: string): Observable<Video> { |
39 | logger('Schedule video fetch for uuid %s.', uuid) | 39 | debugLogger('Schedule video fetch for uuid %s.', uuid) |
40 | 40 | ||
41 | return this.getData({ | 41 | return this.getData({ |
42 | observableObject: this.getVideoInBulk, | 42 | observableObject: this.getVideoInBulk, |
@@ -46,7 +46,7 @@ export class FindInBulkService { | |||
46 | } | 46 | } |
47 | 47 | ||
48 | getChannel (handle: string): Observable<VideoChannel> { | 48 | getChannel (handle: string): Observable<VideoChannel> { |
49 | logger('Schedule channel fetch for handle %s.', handle) | 49 | debugLogger('Schedule channel fetch for handle %s.', handle) |
50 | 50 | ||
51 | return this.getData({ | 51 | return this.getData({ |
52 | observableObject: this.getChannelInBulk, | 52 | observableObject: this.getChannelInBulk, |
@@ -56,7 +56,7 @@ export class FindInBulkService { | |||
56 | } | 56 | } |
57 | 57 | ||
58 | getPlaylist (uuid: string): Observable<VideoPlaylist> { | 58 | getPlaylist (uuid: string): Observable<VideoPlaylist> { |
59 | logger('Schedule playlist fetch for uuid %s.', uuid) | 59 | debugLogger('Schedule playlist fetch for uuid %s.', uuid) |
60 | 60 | ||
61 | return this.getData({ | 61 | return this.getData({ |
62 | observableObject: this.getPlaylistInBulk, | 62 | observableObject: this.getPlaylistInBulk, |
@@ -94,7 +94,7 @@ export class FindInBulkService { | |||
94 | } | 94 | } |
95 | 95 | ||
96 | private getVideosInBulk (uuids: string[]) { | 96 | private getVideosInBulk (uuids: string[]) { |
97 | logger('Fetching videos %s.', uuids.join(', ')) | 97 | debugLogger('Fetching videos %s.', uuids.join(', ')) |
98 | 98 | ||
99 | return this.searchService.searchVideos({ | 99 | return this.searchService.searchVideos({ |
100 | uuids, | 100 | uuids, |
@@ -104,7 +104,7 @@ export class FindInBulkService { | |||
104 | } | 104 | } |
105 | 105 | ||
106 | private getChannelsInBulk (handles: string[]) { | 106 | private getChannelsInBulk (handles: string[]) { |
107 | logger('Fetching channels %s.', handles.join(', ')) | 107 | debugLogger('Fetching channels %s.', handles.join(', ')) |
108 | 108 | ||
109 | return this.searchService.searchVideoChannels({ | 109 | return this.searchService.searchVideoChannels({ |
110 | handles, | 110 | handles, |
@@ -114,7 +114,7 @@ export class FindInBulkService { | |||
114 | } | 114 | } |
115 | 115 | ||
116 | private getPlaylistsInBulk (uuids: string[]) { | 116 | private getPlaylistsInBulk (uuids: string[]) { |
117 | logger('Fetching playlists %s.', uuids.join(', ')) | 117 | debugLogger('Fetching playlists %s.', uuids.join(', ')) |
118 | 118 | ||
119 | return this.searchService.searchVideoPlaylists({ | 119 | return this.searchService.searchVideoPlaylists({ |
120 | uuids, | 120 | uuids, |
diff --git a/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts b/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts index 369692715..7bcfdd8aa 100644 --- a/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts +++ b/client/src/app/shared/shared-user-subscription/remote-subscribe.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Component, Input, OnInit } from '@angular/core' | 1 | import { Component, Input, OnInit } from '@angular/core' |
2 | import { Notifier } from '@app/core' | 2 | import { Notifier } from '@app/core' |
3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' | 3 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { USER_HANDLE_VALIDATOR } from '../form-validators/user-validators' | 5 | import { USER_HANDLE_VALIDATOR } from '../form-validators/user-validators' |
5 | 6 | ||
6 | @Component({ | 7 | @Component({ |
@@ -59,7 +60,7 @@ export class RemoteSubscribeComponent extends FormReactive implements OnInit { | |||
59 | }) | 60 | }) |
60 | .then(window.open) | 61 | .then(window.open) |
61 | .catch(err => { | 62 | .catch(err => { |
62 | console.error(err) | 63 | logger.error(err) |
63 | 64 | ||
64 | this.notifier.error($localize`Cannot fetch information of this remote account`) | 65 | this.notifier.error($localize`Cannot fetch information of this remote account`) |
65 | }) | 66 | }) |
diff --git a/client/src/app/shared/shared-user-subscription/user-subscription.service.ts b/client/src/app/shared/shared-user-subscription/user-subscription.service.ts index 33a2d04fd..9cf6b4d16 100644 --- a/client/src/app/shared/shared-user-subscription/user-subscription.service.ts +++ b/client/src/app/shared/shared-user-subscription/user-subscription.service.ts | |||
@@ -9,7 +9,7 @@ import { Video, VideoChannel, VideoChannelService, VideoService } from '@app/sha | |||
9 | import { ActorFollow, ResultList, VideoChannel as VideoChannelServer, VideoSortField } from '@shared/models' | 9 | import { ActorFollow, ResultList, VideoChannel as VideoChannelServer, VideoSortField } from '@shared/models' |
10 | import { environment } from '../../../environments/environment' | 10 | import { environment } from '../../../environments/environment' |
11 | 11 | ||
12 | const logger = debug('peertube:subscriptions:UserSubscriptionService') | 12 | const debugLogger = debug('peertube:subscriptions:UserSubscriptionService') |
13 | 13 | ||
14 | type SubscriptionExistResult = { [ uri: string ]: boolean } | 14 | type SubscriptionExistResult = { [ uri: string ]: boolean } |
15 | type SubscriptionExistResultObservable = { [ uri: string ]: Observable<boolean> } | 15 | type SubscriptionExistResultObservable = { [ uri: string ]: Observable<boolean> } |
@@ -176,17 +176,17 @@ export class UserSubscriptionService { | |||
176 | } | 176 | } |
177 | 177 | ||
178 | doesSubscriptionExist (nameWithHost: string) { | 178 | doesSubscriptionExist (nameWithHost: string) { |
179 | logger('Running subscription check for %d.', nameWithHost) | 179 | debugLogger('Running subscription check for %d.', nameWithHost) |
180 | 180 | ||
181 | if (nameWithHost in this.myAccountSubscriptionCache) { | 181 | if (nameWithHost in this.myAccountSubscriptionCache) { |
182 | logger('Found cache for %d.', nameWithHost) | 182 | debugLogger('Found cache for %d.', nameWithHost) |
183 | 183 | ||
184 | return of(this.myAccountSubscriptionCache[nameWithHost]) | 184 | return of(this.myAccountSubscriptionCache[nameWithHost]) |
185 | } | 185 | } |
186 | 186 | ||
187 | this.existsSubject.next(nameWithHost) | 187 | this.existsSubject.next(nameWithHost) |
188 | 188 | ||
189 | logger('Fetching from network for %d.', nameWithHost) | 189 | debugLogger('Fetching from network for %d.', nameWithHost) |
190 | return this.existsObservable.pipe( | 190 | return this.existsObservable.pipe( |
191 | filter(existsResult => existsResult[nameWithHost] !== undefined), | 191 | filter(existsResult => existsResult[nameWithHost] !== undefined), |
192 | map(existsResult => existsResult[nameWithHost]), | 192 | map(existsResult => existsResult[nameWithHost]), |
diff --git a/client/src/app/shared/shared-video-miniature/video-download.component.ts b/client/src/app/shared/shared-video-miniature/video-download.component.ts index bbda39c2d..47482caaa 100644 --- a/client/src/app/shared/shared-video-miniature/video-download.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-download.component.ts | |||
@@ -4,6 +4,7 @@ import { tap } from 'rxjs/operators' | |||
4 | import { Component, ElementRef, Inject, LOCALE_ID, ViewChild } from '@angular/core' | 4 | import { Component, ElementRef, Inject, LOCALE_ID, ViewChild } from '@angular/core' |
5 | import { AuthService, HooksService, Notifier } from '@app/core' | 5 | import { AuthService, HooksService, Notifier } from '@app/core' |
6 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' | 6 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' |
7 | import { logger } from '@root-helpers/logger' | ||
7 | import { VideoCaption, VideoFile, VideoPrivacy } from '@shared/models' | 8 | import { VideoCaption, VideoFile, VideoPrivacy } from '@shared/models' |
8 | import { BytesPipe, NumberFormatterPipe, VideoDetails, VideoService } from '../shared-main' | 9 | import { BytesPipe, NumberFormatterPipe, VideoDetails, VideoService } from '../shared-main' |
9 | 10 | ||
@@ -142,7 +143,7 @@ export class VideoDownloadComponent { | |||
142 | .find(f => f.resolution.id === this.resolutionId) | 143 | .find(f => f.resolution.id === this.resolutionId) |
143 | 144 | ||
144 | if (!file) { | 145 | if (!file) { |
145 | console.error('Could not find file with resolution %d.', this.resolutionId) | 146 | logger.error(`Could not find file with resolution ${this.resolutionId}`) |
146 | return undefined | 147 | return undefined |
147 | } | 148 | } |
148 | 149 | ||
@@ -175,7 +176,7 @@ export class VideoDownloadComponent { | |||
175 | .find(c => c.language.id === this.subtitleLanguageId) | 176 | .find(c => c.language.id === this.subtitleLanguageId) |
176 | 177 | ||
177 | if (!caption) { | 178 | if (!caption) { |
178 | console.error('Cannot find caption %s.', this.subtitleLanguageId) | 179 | logger.error(`Cannot find caption ${this.subtitleLanguageId}`) |
179 | return undefined | 180 | return undefined |
180 | } | 181 | } |
181 | 182 | ||
diff --git a/client/src/app/shared/shared-video-miniature/video-filters-header.component.ts b/client/src/app/shared/shared-video-miniature/video-filters-header.component.ts index 7b806248b..a5da9ebf3 100644 --- a/client/src/app/shared/shared-video-miniature/video-filters-header.component.ts +++ b/client/src/app/shared/shared-video-miniature/video-filters-header.component.ts | |||
@@ -8,7 +8,7 @@ import { UserRight } from '@shared/models' | |||
8 | import { PeertubeModalService } from '../shared-main' | 8 | import { PeertubeModalService } from '../shared-main' |
9 | import { VideoFilters } from './video-filters.model' | 9 | import { VideoFilters } from './video-filters.model' |
10 | 10 | ||
11 | const logger = debug('peertube:videos:VideoFiltersHeaderComponent') | 11 | const debugLogger = debug('peertube:videos:VideoFiltersHeaderComponent') |
12 | 12 | ||
13 | @Component({ | 13 | @Component({ |
14 | selector: 'my-video-filters-header', | 14 | selector: 'my-video-filters-header', |
@@ -54,7 +54,7 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy { | |||
54 | }) | 54 | }) |
55 | 55 | ||
56 | this.form.valueChanges.subscribe(values => { | 56 | this.form.valueChanges.subscribe(values => { |
57 | logger('Loading values from form: %O', values) | 57 | debugLogger('Loading values from form: %O', values) |
58 | 58 | ||
59 | this.filters.load(values) | 59 | this.filters.load(values) |
60 | this.filtersChanged.emit() | 60 | this.filtersChanged.emit() |
@@ -105,6 +105,6 @@ export class VideoFiltersHeaderComponent implements OnInit, OnDestroy { | |||
105 | const defaultValues = this.filters.toFormObject() | 105 | const defaultValues = this.filters.toFormObject() |
106 | this.form.patchValue(defaultValues, { emitEvent }) | 106 | this.form.patchValue(defaultValues, { emitEvent }) |
107 | 107 | ||
108 | logger('Patched form: %O', defaultValues) | 108 | debugLogger('Patched form: %O', defaultValues) |
109 | } | 109 | } |
110 | } | 110 | } |
diff --git a/client/src/app/shared/shared-video-miniature/videos-list.component.ts b/client/src/app/shared/shared-video-miniature/videos-list.component.ts index 38a80b973..508a189fd 100644 --- a/client/src/app/shared/shared-video-miniature/videos-list.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-list.component.ts | |||
@@ -14,13 +14,14 @@ import { | |||
14 | UserService | 14 | UserService |
15 | } from '@app/core' | 15 | } from '@app/core' |
16 | import { GlobalIconName } from '@app/shared/shared-icons' | 16 | import { GlobalIconName } from '@app/shared/shared-icons' |
17 | import { logger } from '@root-helpers/logger' | ||
17 | import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils' | 18 | import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils' |
18 | import { ResultList, UserRight, VideoSortField } from '@shared/models' | 19 | import { ResultList, UserRight, VideoSortField } from '@shared/models' |
19 | import { Syndication, Video } from '../shared-main' | 20 | import { Syndication, Video } from '../shared-main' |
20 | import { VideoFilters, VideoFilterScope } from './video-filters.model' | 21 | import { VideoFilters, VideoFilterScope } from './video-filters.model' |
21 | import { MiniatureDisplayOptions } from './video-miniature.component' | 22 | import { MiniatureDisplayOptions } from './video-miniature.component' |
22 | 23 | ||
23 | const logger = debug('peertube:videos:VideosListComponent') | 24 | const debugLogger = debug('peertube:videos:VideosListComponent') |
24 | 25 | ||
25 | export type HeaderAction = { | 26 | export type HeaderAction = { |
26 | iconName: GlobalIconName | 27 | iconName: GlobalIconName |
@@ -245,7 +246,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { | |||
245 | error: err => { | 246 | error: err => { |
246 | const message = $localize`Cannot load more videos. Try again later.` | 247 | const message = $localize`Cannot load more videos. Try again later.` |
247 | 248 | ||
248 | console.error(message, { err }) | 249 | logger.error(message, err) |
249 | this.notifier.error(message) | 250 | this.notifier.error(message) |
250 | } | 251 | } |
251 | }) | 252 | }) |
@@ -323,7 +324,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { | |||
323 | } | 324 | } |
324 | 325 | ||
325 | onFiltersChanged (customizedByUser: boolean) { | 326 | onFiltersChanged (customizedByUser: boolean) { |
326 | logger('Running on filters changed') | 327 | debugLogger('Running on filters changed') |
327 | 328 | ||
328 | this.updateUrl(customizedByUser) | 329 | this.updateUrl(customizedByUser) |
329 | 330 | ||
@@ -364,7 +365,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { | |||
364 | if (!items || items.length === 0) this.syndicationItems = undefined | 365 | if (!items || items.length === 0) this.syndicationItems = undefined |
365 | else this.syndicationItems = items | 366 | else this.syndicationItems = items |
366 | }) | 367 | }) |
367 | .catch(err => console.error('Cannot get syndication items.', err)) | 368 | .catch(err => logger.error('Cannot get syndication items.', err)) |
368 | } | 369 | } |
369 | 370 | ||
370 | private updateUrl (customizedByUser: boolean) { | 371 | private updateUrl (customizedByUser: boolean) { |
@@ -375,7 +376,7 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { | |||
375 | ? { ...baseQuery, c: customizedByUser } | 376 | ? { ...baseQuery, c: customizedByUser } |
376 | : baseQuery | 377 | : baseQuery |
377 | 378 | ||
378 | logger('Will inject %O in URL query', queryParams) | 379 | debugLogger('Will inject %O in URL query', queryParams) |
379 | 380 | ||
380 | const baseRoute = this.baseRouteBuilderFunction | 381 | const baseRoute = this.baseRouteBuilderFunction |
381 | ? this.baseRouteBuilderFunction(this.filters) | 382 | ? this.baseRouteBuilderFunction(this.filters) |
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts index bac828fba..fa3c79bbb 100644 --- a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { Observable, Subject } from 'rxjs' | 1 | import { Observable, Subject } from 'rxjs' |
2 | import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core' | 2 | import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core' |
3 | import { ComponentPagination, Notifier, User } from '@app/core' | 3 | import { ComponentPagination, Notifier, User } from '@app/core' |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { ResultList, VideoSortField } from '@shared/models' | 5 | import { ResultList, VideoSortField } from '@shared/models' |
5 | import { PeerTubeTemplateDirective, Video } from '../shared-main' | 6 | import { PeerTubeTemplateDirective, Video } from '../shared-main' |
6 | import { MiniatureDisplayOptions } from './video-miniature.component' | 7 | import { MiniatureDisplayOptions } from './video-miniature.component' |
@@ -128,7 +129,7 @@ export class VideosSelectionComponent implements AfterContentInit { | |||
128 | error: err => { | 129 | error: err => { |
129 | const message = $localize`Cannot load more videos. Try again later.` | 130 | const message = $localize`Cannot load more videos. Try again later.` |
130 | 131 | ||
131 | console.error(message, { err }) | 132 | logger.error(message, err) |
132 | this.notifier.error(message) | 133 | this.notifier.error(message) |
133 | } | 134 | } |
134 | }) | 135 | }) |
diff --git a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts index e4972ec10..e019fdd26 100644 --- a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts +++ b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts | |||
@@ -16,7 +16,7 @@ import { | |||
16 | import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators' | 16 | import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators' |
17 | import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service' | 17 | import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service' |
18 | 18 | ||
19 | const logger = debug('peertube:playlists:VideoAddToPlaylistComponent') | 19 | const debugLogger = debug('peertube:playlists:VideoAddToPlaylistComponent') |
20 | 20 | ||
21 | type PlaylistElement = { | 21 | type PlaylistElement = { |
22 | enabled: boolean | 22 | enabled: boolean |
@@ -110,7 +110,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, | |||
110 | } | 110 | } |
111 | 111 | ||
112 | reload () { | 112 | reload () { |
113 | logger('Reloading component') | 113 | debugLogger('Reloading component') |
114 | 114 | ||
115 | this.videoPlaylists = [] | 115 | this.videoPlaylists = [] |
116 | this.videoPlaylistSearch = undefined | 116 | this.videoPlaylistSearch = undefined |
@@ -121,7 +121,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, | |||
121 | } | 121 | } |
122 | 122 | ||
123 | load () { | 123 | load () { |
124 | logger('Loading component') | 124 | debugLogger('Loading component') |
125 | 125 | ||
126 | this.listenToVideoPlaylistChange() | 126 | this.listenToVideoPlaylistChange() |
127 | 127 | ||
@@ -331,7 +331,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, | |||
331 | } | 331 | } |
332 | 332 | ||
333 | private rebuildPlaylists (existResult: VideoExistInPlaylist[]) { | 333 | private rebuildPlaylists (existResult: VideoExistInPlaylist[]) { |
334 | logger('Got existing results for %d.', this.video.id, existResult) | 334 | debugLogger('Got existing results for %d.', this.video.id, existResult) |
335 | 335 | ||
336 | const oldPlaylists = this.videoPlaylists | 336 | const oldPlaylists = this.videoPlaylists |
337 | 337 | ||
@@ -359,7 +359,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit, | |||
359 | this.videoPlaylists.push(playlistSummary) | 359 | this.videoPlaylists.push(playlistSummary) |
360 | } | 360 | } |
361 | 361 | ||
362 | logger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists) | 362 | debugLogger('Rebuilt playlist state for video %d.', this.video.id, this.videoPlaylists) |
363 | 363 | ||
364 | this.cd.markForCheck() | 364 | this.cd.markForCheck() |
365 | } | 365 | } |
diff --git a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts index db9f78a7a..81ae0f292 100644 --- a/client/src/app/shared/shared-video-playlist/video-playlist.service.ts +++ b/client/src/app/shared/shared-video-playlist/video-playlist.service.ts | |||
@@ -23,7 +23,7 @@ import { environment } from '../../../environments/environment' | |||
23 | import { VideoPlaylistElement } from './video-playlist-element.model' | 23 | import { VideoPlaylistElement } from './video-playlist-element.model' |
24 | import { VideoPlaylist } from './video-playlist.model' | 24 | import { VideoPlaylist } from './video-playlist.model' |
25 | 25 | ||
26 | const logger = debug('peertube:playlists:VideoPlaylistService') | 26 | const debugLogger = debug('peertube:playlists:VideoPlaylistService') |
27 | 27 | ||
28 | export type CachedPlaylist = VideoPlaylist | { id: number, displayName: string } | 28 | export type CachedPlaylist = VideoPlaylist | { id: number, displayName: string } |
29 | 29 | ||
@@ -287,15 +287,15 @@ export class VideoPlaylistService { | |||
287 | } | 287 | } |
288 | 288 | ||
289 | runPlaylistCheck (videoId: number) { | 289 | runPlaylistCheck (videoId: number) { |
290 | logger('Running playlist check.') | 290 | debugLogger('Running playlist check.') |
291 | 291 | ||
292 | if (this.videoExistsCache[videoId]) { | 292 | if (this.videoExistsCache[videoId]) { |
293 | logger('Found cache for %d.', videoId) | 293 | debugLogger('Found cache for %d.', videoId) |
294 | 294 | ||
295 | return this.videoExistsInPlaylistCacheSubject.next({ [videoId]: this.videoExistsCache[videoId] }) | 295 | return this.videoExistsInPlaylistCacheSubject.next({ [videoId]: this.videoExistsCache[videoId] }) |
296 | } | 296 | } |
297 | 297 | ||
298 | logger('Fetching from network for %d.', videoId) | 298 | debugLogger('Fetching from network for %d.', videoId) |
299 | return this.videoExistsInPlaylistNotifier.next(videoId) | 299 | return this.videoExistsInPlaylistNotifier.next(videoId) |
300 | } | 300 | } |
301 | 301 | ||
diff --git a/client/src/assets/player/peertube-player-local-storage.ts b/client/src/assets/player/peertube-player-local-storage.ts index d9dacfba5..64040abf1 100644 --- a/client/src/assets/player/peertube-player-local-storage.ts +++ b/client/src/assets/player/peertube-player-local-storage.ts | |||
@@ -1,3 +1,5 @@ | |||
1 | import { logger } from '@root-helpers/logger' | ||
2 | |||
1 | function getStoredVolume () { | 3 | function getStoredVolume () { |
2 | const value = getLocalStorage('volume') | 4 | const value = getLocalStorage('volume') |
3 | if (value !== null && value !== undefined) { | 5 | if (value !== null && value !== undefined) { |
@@ -81,7 +83,7 @@ function getStoredVideoWatchHistory (videoUUID?: string) { | |||
81 | 83 | ||
82 | data = JSON.parse(value) | 84 | data = JSON.parse(value) |
83 | } catch (error) { | 85 | } catch (error) { |
84 | console.error('Cannot parse video watch history from local storage: ', error) | 86 | logger.error('Cannot parse video watch history from local storage/', error) |
85 | } | 87 | } |
86 | 88 | ||
87 | data = data || {} | 89 | data = data || {} |
diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts index b24b6966e..b9077dcae 100644 --- a/client/src/assets/player/peertube-player-manager.ts +++ b/client/src/assets/player/peertube-player-manager.ts | |||
@@ -23,6 +23,7 @@ import './shared/mobile/peertube-mobile-plugin' | |||
23 | import './shared/mobile/peertube-mobile-buttons' | 23 | import './shared/mobile/peertube-mobile-buttons' |
24 | import './shared/hotkeys/peertube-hotkeys-plugin' | 24 | import './shared/hotkeys/peertube-hotkeys-plugin' |
25 | import videojs from 'video.js' | 25 | import videojs from 'video.js' |
26 | import { logger } from '@root-helpers/logger' | ||
26 | import { PluginsManager } from '@root-helpers/plugins-manager' | 27 | import { PluginsManager } from '@root-helpers/plugins-manager' |
27 | import { isMobile } from '@root-helpers/web-browser' | 28 | import { isMobile } from '@root-helpers/web-browser' |
28 | import { saveAverageBandwidth } from './peertube-player-local-storage' | 29 | import { saveAverageBandwidth } from './peertube-player-local-storage' |
@@ -145,7 +146,7 @@ export class PeertubePlayerManager { | |||
145 | return | 146 | return |
146 | } | 147 | } |
147 | 148 | ||
148 | console.log('Fast forwarding HLS to recover from an error.') | 149 | logger.info('Fast forwarding HLS to recover from an error.') |
149 | 150 | ||
150 | this.videojsDecodeErrors++ | 151 | this.videojsDecodeErrors++ |
151 | 152 | ||
@@ -170,7 +171,7 @@ export class PeertubePlayerManager { | |||
170 | return | 171 | return |
171 | } | 172 | } |
172 | 173 | ||
173 | console.log('Fallback to webtorrent.') | 174 | logger.info('Fallback to webtorrent.') |
174 | 175 | ||
175 | this.rebuildAndUpdateVideoElement(currentPlayer, options.common) | 176 | this.rebuildAndUpdateVideoElement(currentPlayer, options.common) |
176 | 177 | ||
diff --git a/client/src/assets/player/shared/manager-options/hls-options-builder.ts b/client/src/assets/player/shared/manager-options/hls-options-builder.ts index cdfad0f4c..ed12f6e8b 100644 --- a/client/src/assets/player/shared/manager-options/hls-options-builder.ts +++ b/client/src/assets/player/shared/manager-options/hls-options-builder.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core' | 1 | import { HybridLoaderSettings } from '@peertube/p2p-media-loader-core' |
2 | import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs' | 2 | import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | import { LiveVideoLatencyMode } from '@shared/models' | 4 | import { LiveVideoLatencyMode } from '@shared/models' |
4 | import { getAverageBandwidthInStore } from '../../peertube-player-local-storage' | 5 | import { getAverageBandwidthInStore } from '../../peertube-player-local-storage' |
5 | import { P2PMediaLoader, P2PMediaLoaderPluginOptions } from '../../types' | 6 | import { P2PMediaLoader, P2PMediaLoaderPluginOptions } from '../../types' |
@@ -61,7 +62,7 @@ export class HLSOptionsBuilder { | |||
61 | private getP2PMediaLoaderOptions (redundancyUrlManager: RedundancyUrlManager): HlsJsEngineSettings { | 62 | private getP2PMediaLoaderOptions (redundancyUrlManager: RedundancyUrlManager): HlsJsEngineSettings { |
62 | let consumeOnly = false | 63 | let consumeOnly = false |
63 | if ((navigator as any)?.connection?.type === 'cellular') { | 64 | if ((navigator as any)?.connection?.type === 'cellular') { |
64 | console.log('We are on a cellular connection: disabling seeding.') | 65 | logger.info('We are on a cellular connection: disabling seeding.') |
65 | consumeOnly = true | 66 | consumeOnly = true |
66 | } | 67 | } |
67 | 68 | ||
diff --git a/client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts b/client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts index 91dda7f94..646e9f8c6 100644 --- a/client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts +++ b/client/src/assets/player/shared/mobile/peertube-mobile-plugin.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { PeerTubeMobileButtons } from './peertube-mobile-buttons' | ||
2 | import videojs from 'video.js' | ||
3 | import debug from 'debug' | 1 | import debug from 'debug' |
2 | import videojs from 'video.js' | ||
3 | import { logger } from '@root-helpers/logger' | ||
4 | import { PeerTubeMobileButtons } from './peertube-mobile-buttons' | ||
4 | 5 | ||
5 | const logger = debug('peertube:player:mobile') | 6 | const debugLogger = debug('peertube:player:mobile') |
6 | 7 | ||
7 | const Plugin = videojs.getPlugin('plugin') | 8 | const Plugin = videojs.getPlugin('plugin') |
8 | 9 | ||
@@ -45,7 +46,7 @@ class PeerTubeMobilePlugin extends Plugin { | |||
45 | if (!this.player.isFullscreen() || this.isPortraitVideo()) return | 46 | if (!this.player.isFullscreen() || this.isPortraitVideo()) return |
46 | 47 | ||
47 | screen.orientation.lock('landscape') | 48 | screen.orientation.lock('landscape') |
48 | .catch(err => console.error('Cannot lock screen to landscape.', err)) | 49 | .catch(err => logger.error('Cannot lock screen to landscape.', err)) |
49 | }) | 50 | }) |
50 | } | 51 | } |
51 | 52 | ||
@@ -61,7 +62,7 @@ class PeerTubeMobilePlugin extends Plugin { | |||
61 | } | 62 | } |
62 | 63 | ||
63 | if (this.lastTapEvent && event.timeStamp - this.lastTapEvent.timeStamp < PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) { | 64 | if (this.lastTapEvent && event.timeStamp - this.lastTapEvent.timeStamp < PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) { |
64 | logger('Detected double tap') | 65 | debugLogger('Detected double tap') |
65 | 66 | ||
66 | this.lastTapEvent = undefined | 67 | this.lastTapEvent = undefined |
67 | this.onDoubleTap(event) | 68 | this.onDoubleTap(event) |
@@ -71,7 +72,7 @@ class PeerTubeMobilePlugin extends Plugin { | |||
71 | this.newActiveState = !this.player.userActive() | 72 | this.newActiveState = !this.player.userActive() |
72 | 73 | ||
73 | this.tapTimeout = setTimeout(() => { | 74 | this.tapTimeout = setTimeout(() => { |
74 | logger('No double tap detected, set user active state to %s.', this.newActiveState) | 75 | debugLogger('No double tap detected, set user active state to %s.', this.newActiveState) |
75 | 76 | ||
76 | this.player.userActive(this.newActiveState) | 77 | this.player.userActive(this.newActiveState) |
77 | }, PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) | 78 | }, PeerTubeMobilePlugin.DOUBLE_TAP_DELAY_MS) |
@@ -100,19 +101,19 @@ class PeerTubeMobilePlugin extends Plugin { | |||
100 | const rect = this.findPlayerTarget((event.target as HTMLElement)).getBoundingClientRect() | 101 | const rect = this.findPlayerTarget((event.target as HTMLElement)).getBoundingClientRect() |
101 | const offsetX = event.targetTouches[0].pageX - rect.left | 102 | const offsetX = event.targetTouches[0].pageX - rect.left |
102 | 103 | ||
103 | logger('Calculating double tap zone (player width: %d, offset X: %d)', playerWidth, offsetX) | 104 | debugLogger('Calculating double tap zone (player width: %d, offset X: %d)', playerWidth, offsetX) |
104 | 105 | ||
105 | if (offsetX > 0.66 * playerWidth) { | 106 | if (offsetX > 0.66 * playerWidth) { |
106 | if (this.seekAmount < 0) this.seekAmount = 0 | 107 | if (this.seekAmount < 0) this.seekAmount = 0 |
107 | 108 | ||
108 | this.seekAmount += 10 | 109 | this.seekAmount += 10 |
109 | 110 | ||
110 | logger('Will forward %d seconds', this.seekAmount) | 111 | debugLogger('Will forward %d seconds', this.seekAmount) |
111 | } else if (offsetX < 0.33 * playerWidth) { | 112 | } else if (offsetX < 0.33 * playerWidth) { |
112 | if (this.seekAmount > 0) this.seekAmount = 0 | 113 | if (this.seekAmount > 0) this.seekAmount = 0 |
113 | 114 | ||
114 | this.seekAmount -= 10 | 115 | this.seekAmount -= 10 |
115 | logger('Will rewind %d seconds', this.seekAmount) | 116 | debugLogger('Will rewind %d seconds', this.seekAmount) |
116 | } | 117 | } |
117 | 118 | ||
118 | this.peerTubeMobileButtons.displayFastSeek(this.seekAmount) | 119 | this.peerTubeMobileButtons.displayFastSeek(this.seekAmount) |
diff --git a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts b/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts index d0105fa36..e49e5c694 100644 --- a/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts +++ b/client/src/assets/player/shared/p2p-media-loader/hls-plugin.ts | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | import Hlsjs, { ErrorData, HlsConfig, Level, LevelSwitchingData, ManifestParsedData } from 'hls.js' | 4 | import Hlsjs, { ErrorData, HlsConfig, Level, LevelSwitchingData, ManifestParsedData } from 'hls.js' |
5 | import videojs from 'video.js' | 5 | import videojs from 'video.js' |
6 | import { logger } from '@root-helpers/logger' | ||
6 | import { HlsjsConfigHandlerOptions, PeerTubeResolution, VideoJSTechHLS } from '../../types' | 7 | import { HlsjsConfigHandlerOptions, PeerTubeResolution, VideoJSTechHLS } from '../../types' |
7 | 8 | ||
8 | type ErrorCounts = { | 9 | type ErrorCounts = { |
@@ -17,14 +18,14 @@ type HookFn = (player: videojs.Player, hljs: Hlsjs) => void | |||
17 | 18 | ||
18 | const registerSourceHandler = function (vjs: typeof videojs) { | 19 | const registerSourceHandler = function (vjs: typeof videojs) { |
19 | if (!Hlsjs.isSupported()) { | 20 | if (!Hlsjs.isSupported()) { |
20 | console.warn('Hls.js is not supported in this browser!') | 21 | logger.warn('Hls.js is not supported in this browser!') |
21 | return | 22 | return |
22 | } | 23 | } |
23 | 24 | ||
24 | const html5 = vjs.getTech('Html5') | 25 | const html5 = vjs.getTech('Html5') |
25 | 26 | ||
26 | if (!html5) { | 27 | if (!html5) { |
27 | console.error('No Hml5 tech found in videojs') | 28 | logger.error('No Hml5 tech found in videojs') |
28 | return | 29 | return |
29 | } | 30 | } |
30 | 31 | ||
@@ -120,7 +121,7 @@ class Html5Hlsjs { | |||
120 | 121 | ||
121 | if (!mediaError) return | 122 | if (!mediaError) return |
122 | 123 | ||
123 | console.log(mediaError) | 124 | logger.info(mediaError) |
124 | switch (mediaError.code) { | 125 | switch (mediaError.code) { |
125 | case mediaError.MEDIA_ERR_ABORTED: | 126 | case mediaError.MEDIA_ERR_ABORTED: |
126 | errorTxt = 'You aborted the video playback' | 127 | errorTxt = 'You aborted the video playback' |
@@ -141,7 +142,7 @@ class Html5Hlsjs { | |||
141 | errorTxt = mediaError.message | 142 | errorTxt = mediaError.message |
142 | } | 143 | } |
143 | 144 | ||
144 | console.error('MEDIA_ERROR: ', errorTxt) | 145 | logger.error(`MEDIA_ERROR: ${errorTxt}`) |
145 | }) | 146 | }) |
146 | 147 | ||
147 | this.initialize() | 148 | this.initialize() |
@@ -212,20 +213,20 @@ class Html5Hlsjs { | |||
212 | 213 | ||
213 | private _handleMediaError (error: any) { | 214 | private _handleMediaError (error: any) { |
214 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 1) { | 215 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 1) { |
215 | console.info('trying to recover media error') | 216 | logger.info('trying to recover media error') |
216 | this.hls.recoverMediaError() | 217 | this.hls.recoverMediaError() |
217 | return | 218 | return |
218 | } | 219 | } |
219 | 220 | ||
220 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 2) { | 221 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] === 2) { |
221 | console.info('2nd try to recover media error (by swapping audio codec') | 222 | logger.info('2nd try to recover media error (by swapping audio codec') |
222 | this.hls.swapAudioCodec() | 223 | this.hls.swapAudioCodec() |
223 | this.hls.recoverMediaError() | 224 | this.hls.recoverMediaError() |
224 | return | 225 | return |
225 | } | 226 | } |
226 | 227 | ||
227 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] > 2) { | 228 | if (this.errorCounts[Hlsjs.ErrorTypes.MEDIA_ERROR] > 2) { |
228 | console.info('bubbling media error up to VIDEOJS') | 229 | logger.info('bubbling media error up to VIDEOJS') |
229 | this.hls.destroy() | 230 | this.hls.destroy() |
230 | this.tech.error = () => error | 231 | this.tech.error = () => error |
231 | this.tech.trigger('error') | 232 | this.tech.trigger('error') |
@@ -234,7 +235,7 @@ class Html5Hlsjs { | |||
234 | 235 | ||
235 | private _handleNetworkError (error: any) { | 236 | private _handleNetworkError (error: any) { |
236 | if (this.errorCounts[Hlsjs.ErrorTypes.NETWORK_ERROR] <= this.maxNetworkErrorRecovery) { | 237 | if (this.errorCounts[Hlsjs.ErrorTypes.NETWORK_ERROR] <= this.maxNetworkErrorRecovery) { |
237 | console.info('trying to recover network error') | 238 | logger.info('trying to recover network error') |
238 | 239 | ||
239 | // Wait 1 second and retry | 240 | // Wait 1 second and retry |
240 | setTimeout(() => this.hls.startLoad(), 1000) | 241 | setTimeout(() => this.hls.startLoad(), 1000) |
@@ -247,7 +248,7 @@ class Html5Hlsjs { | |||
247 | return | 248 | return |
248 | } | 249 | } |
249 | 250 | ||
250 | console.info('bubbling network error up to VIDEOJS') | 251 | logger.info('bubbling network error up to VIDEOJS') |
251 | this.hls.destroy() | 252 | this.hls.destroy() |
252 | this.tech.error = () => error | 253 | this.tech.error = () => error |
253 | this.tech.trigger('error') | 254 | this.tech.trigger('error') |
@@ -262,8 +263,8 @@ class Html5Hlsjs { | |||
262 | if (this.errorCounts[data.type]) this.errorCounts[data.type] += 1 | 263 | if (this.errorCounts[data.type]) this.errorCounts[data.type] += 1 |
263 | else this.errorCounts[data.type] = 1 | 264 | else this.errorCounts[data.type] = 1 |
264 | 265 | ||
265 | if (data.fatal) console.warn(error.message) | 266 | if (data.fatal) logger.warn(error.message) |
266 | else console.error(error.message, data) | 267 | else logger.error(error.message, { data }) |
267 | 268 | ||
268 | if (data.type === Hlsjs.ErrorTypes.NETWORK_ERROR) { | 269 | if (data.type === Hlsjs.ErrorTypes.NETWORK_ERROR) { |
269 | error.code = 2 | 270 | error.code = 2 |
@@ -273,7 +274,7 @@ class Html5Hlsjs { | |||
273 | this._handleMediaError(error) | 274 | this._handleMediaError(error) |
274 | } else if (data.fatal) { | 275 | } else if (data.fatal) { |
275 | this.hls.destroy() | 276 | this.hls.destroy() |
276 | console.info('bubbling error up to VIDEOJS') | 277 | logger.info('bubbling error up to VIDEOJS') |
277 | this.tech.error = () => error as any | 278 | this.tech.error = () => error as any |
278 | this.tech.trigger('error') | 279 | this.tech.trigger('error') |
279 | } | 280 | } |
diff --git a/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts b/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts index 5c0f0021f..e5f099dea 100644 --- a/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts +++ b/client/src/assets/player/shared/p2p-media-loader/p2p-media-loader-plugin.ts | |||
@@ -5,6 +5,7 @@ import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from '@peertub | |||
5 | import { timeToInt } from '@shared/core-utils' | 5 | import { timeToInt } from '@shared/core-utils' |
6 | import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../../types' | 6 | import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../../types' |
7 | import { registerConfigPlugin, registerSourceHandler } from './hls-plugin' | 7 | import { registerConfigPlugin, registerSourceHandler } from './hls-plugin' |
8 | import { logger } from '@root-helpers/logger' | ||
8 | 9 | ||
9 | registerConfigPlugin(videojs) | 10 | registerConfigPlugin(videojs) |
10 | registerSourceHandler(videojs) | 11 | registerSourceHandler(videojs) |
@@ -43,11 +44,11 @@ class P2pMediaLoaderPlugin extends Plugin { | |||
43 | 44 | ||
44 | // FIXME: typings https://github.com/Microsoft/TypeScript/issues/14080 | 45 | // FIXME: typings https://github.com/Microsoft/TypeScript/issues/14080 |
45 | if (!(videojs as any).Html5Hlsjs) { | 46 | if (!(videojs as any).Html5Hlsjs) { |
46 | console.warn('HLS.js does not seem to be supported. Try to fallback to built in HLS.') | 47 | logger.warn('HLS.js does not seem to be supported. Try to fallback to built in HLS.') |
47 | 48 | ||
48 | if (!player.canPlayType('application/vnd.apple.mpegurl')) { | 49 | if (!player.canPlayType('application/vnd.apple.mpegurl')) { |
49 | const message = 'Cannot fallback to built-in HLS' | 50 | const message = 'Cannot fallback to built-in HLS' |
50 | console.warn(message) | 51 | logger.warn(message) |
51 | 52 | ||
52 | player.ready(() => player.trigger('error', new Error(message))) | 53 | player.ready(() => player.trigger('error', new Error(message))) |
53 | return | 54 | return |
@@ -114,7 +115,7 @@ class P2pMediaLoaderPlugin extends Plugin { | |||
114 | this.p2pEngine = this.options.loader.getEngine() | 115 | this.p2pEngine = this.options.loader.getEngine() |
115 | 116 | ||
116 | this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => { | 117 | this.p2pEngine.on(Events.SegmentError, (segment: Segment, err) => { |
117 | console.error('Segment error.', segment, err) | 118 | logger.error(`Segment ${segment.id} error.`, err) |
118 | 119 | ||
119 | this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl) | 120 | this.options.redundancyUrlManager.removeBySegmentUrl(segment.requestUrl) |
120 | }) | 121 | }) |
diff --git a/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts b/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts index abab8aa99..376efb835 100644 --- a/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts +++ b/client/src/assets/player/shared/p2p-media-loader/redundancy-url-manager.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { basename, dirname } from 'path' | 1 | import { basename, dirname } from 'path' |
2 | import { logger } from '@root-helpers/logger' | ||
2 | 3 | ||
3 | class RedundancyUrlManager { | 4 | class RedundancyUrlManager { |
4 | 5 | ||
@@ -7,7 +8,7 @@ class RedundancyUrlManager { | |||
7 | } | 8 | } |
8 | 9 | ||
9 | removeBySegmentUrl (segmentUrl: string) { | 10 | removeBySegmentUrl (segmentUrl: string) { |
10 | console.log('Removing redundancy of segment URL %s.', segmentUrl) | 11 | logger.info(`Removing redundancy of segment URL ${segmentUrl}.`) |
11 | 12 | ||
12 | const baseUrl = dirname(segmentUrl) | 13 | const baseUrl = dirname(segmentUrl) |
13 | 14 | ||
diff --git a/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts b/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts index f7f83a8a4..18cb6750f 100644 --- a/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts +++ b/client/src/assets/player/shared/p2p-media-loader/segment-validator.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { wait } from '@root-helpers/utils' | ||
2 | import { Segment } from '@peertube/p2p-media-loader-core' | ||
3 | import { basename } from 'path' | 1 | import { basename } from 'path' |
2 | import { Segment } from '@peertube/p2p-media-loader-core' | ||
3 | import { logger } from '@root-helpers/logger' | ||
4 | import { wait } from '@root-helpers/utils' | ||
4 | 5 | ||
5 | type SegmentsJSON = { [filename: string]: string | { [byterange: string]: string } } | 6 | type SegmentsJSON = { [filename: string]: string | { [byterange: string]: string } } |
6 | 7 | ||
@@ -23,7 +24,7 @@ function segmentValidatorFactory (segmentsSha256Url: string, isLive: boolean) { | |||
23 | } | 24 | } |
24 | 25 | ||
25 | if (!segmentValue) { | 26 | if (!segmentValue) { |
26 | console.log('Refetching sha segments for %s.', filename) | 27 | logger.info(`Refetching sha segments for ${filename}`) |
27 | 28 | ||
28 | await wait(1000) | 29 | await wait(1000) |
29 | 30 | ||
@@ -71,7 +72,7 @@ function fetchSha256Segments (url: string) { | |||
71 | return fetch(url) | 72 | return fetch(url) |
72 | .then(res => res.json() as Promise<SegmentsJSON>) | 73 | .then(res => res.json() as Promise<SegmentsJSON>) |
73 | .catch(err => { | 74 | .catch(err => { |
74 | console.error('Cannot get sha256 segments', err) | 75 | logger.error('Cannot get sha256 segments', err) |
75 | return {} | 76 | return {} |
76 | }) | 77 | }) |
77 | } | 78 | } |
diff --git a/client/src/assets/player/shared/peertube/peertube-plugin.ts b/client/src/assets/player/shared/peertube/peertube-plugin.ts index a29a0921f..69a7b2d65 100644 --- a/client/src/assets/player/shared/peertube/peertube-plugin.ts +++ b/client/src/assets/player/shared/peertube/peertube-plugin.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import debug from 'debug' | 1 | import debug from 'debug' |
2 | import videojs from 'video.js' | 2 | import videojs from 'video.js' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | import { isMobile } from '@root-helpers/web-browser' | 4 | import { isMobile } from '@root-helpers/web-browser' |
4 | import { timeToInt } from '@shared/core-utils' | 5 | import { timeToInt } from '@shared/core-utils' |
5 | import { VideoView, VideoViewEvent } from '@shared/models/videos' | 6 | import { VideoView, VideoViewEvent } from '@shared/models/videos' |
@@ -15,7 +16,7 @@ import { | |||
15 | import { PeerTubePluginOptions, VideoJSCaption } from '../../types' | 16 | import { PeerTubePluginOptions, VideoJSCaption } from '../../types' |
16 | import { SettingsButton } from '../settings/settings-menu-button' | 17 | import { SettingsButton } from '../settings/settings-menu-button' |
17 | 18 | ||
18 | const logger = debug('peertube:player:peertube') | 19 | const debugLogger = debug('peertube:player:peertube') |
19 | 20 | ||
20 | const Plugin = videojs.getPlugin('plugin') | 21 | const Plugin = videojs.getPlugin('plugin') |
21 | 22 | ||
@@ -176,7 +177,7 @@ class PeerTubePlugin extends Plugin { | |||
176 | lastCurrentTime = currentTime | 177 | lastCurrentTime = currentTime |
177 | 178 | ||
178 | this.notifyUserIsWatching(currentTime, lastViewEvent) | 179 | this.notifyUserIsWatching(currentTime, lastViewEvent) |
179 | .catch(err => console.error('Cannot notify user is watching.', err)) | 180 | .catch(err => logger.error('Cannot notify user is watching.', err)) |
180 | 181 | ||
181 | lastViewEvent = undefined | 182 | lastViewEvent = undefined |
182 | 183 | ||
@@ -249,7 +250,7 @@ class PeerTubePlugin extends Plugin { | |||
249 | (this.player as any).cache_.inactivityTimeout = timeout | 250 | (this.player as any).cache_.inactivityTimeout = timeout |
250 | this.player.options_.inactivityTimeout = timeout | 251 | this.player.options_.inactivityTimeout = timeout |
251 | 252 | ||
252 | logger('Set player inactivity to ' + timeout) | 253 | debugLogger('Set player inactivity to ' + timeout) |
253 | } | 254 | } |
254 | 255 | ||
255 | private initCaptions () { | 256 | private initCaptions () { |
diff --git a/client/src/assets/player/shared/stats/stats-card.ts b/client/src/assets/player/shared/stats/stats-card.ts index e9f9b6bd2..b65adcfca 100644 --- a/client/src/assets/player/shared/stats/stats-card.ts +++ b/client/src/assets/player/shared/stats/stats-card.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import videojs from 'video.js' | 1 | import videojs from 'video.js' |
2 | import { logger } from '@root-helpers/logger' | ||
2 | import { secondsToTime } from '@shared/core-utils' | 3 | import { secondsToTime } from '@shared/core-utils' |
3 | import { PlayerNetworkInfo as EventPlayerNetworkInfo } from '../../types' | 4 | import { PlayerNetworkInfo as EventPlayerNetworkInfo } from '../../types' |
4 | import { bytes } from '../common' | 5 | import { bytes } from '../common' |
@@ -125,7 +126,7 @@ class StatsCard extends Component { | |||
125 | 126 | ||
126 | this.populateInfoValues(options) | 127 | this.populateInfoValues(options) |
127 | } catch (err) { | 128 | } catch (err) { |
128 | console.error('Cannot update stats.', err) | 129 | logger.error('Cannot update stats.', err) |
129 | clearInterval(this.updateInterval) | 130 | clearInterval(this.updateInterval) |
130 | } | 131 | } |
131 | }, this.intervalMs) | 132 | }, this.intervalMs) |
diff --git a/client/src/assets/player/shared/webtorrent/peertube-chunk-store.ts b/client/src/assets/player/shared/webtorrent/peertube-chunk-store.ts index 81378c277..74ae17704 100644 --- a/client/src/assets/player/shared/webtorrent/peertube-chunk-store.ts +++ b/client/src/assets/player/shared/webtorrent/peertube-chunk-store.ts | |||
@@ -2,8 +2,9 @@ | |||
2 | // We use temporary IndexDB (all data are removed on destroy) to avoid RAM issues | 2 | // We use temporary IndexDB (all data are removed on destroy) to avoid RAM issues |
3 | // Thanks @santiagogil and @Feross | 3 | // Thanks @santiagogil and @Feross |
4 | 4 | ||
5 | import { EventEmitter } from 'events' | ||
6 | import Dexie from 'dexie' | 5 | import Dexie from 'dexie' |
6 | import { EventEmitter } from 'events' | ||
7 | import { logger } from '@root-helpers/logger' | ||
7 | 8 | ||
8 | class ChunkDatabase extends Dexie { | 9 | class ChunkDatabase extends Dexie { |
9 | chunks: Dexie.Table<{ id: number, buf: Buffer }, number> | 10 | chunks: Dexie.Table<{ id: number, buf: Buffer }, number> |
@@ -104,7 +105,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
104 | return this.db.chunks.bulkPut(processing.map(p => ({ id: p.id, buf: p.buf }))) | 105 | return this.db.chunks.bulkPut(processing.map(p => ({ id: p.id, buf: p.buf }))) |
105 | }) | 106 | }) |
106 | } catch (err) { | 107 | } catch (err) { |
107 | console.log('Cannot bulk insert chunks. Store them in memory.', { err }) | 108 | logger.info('Cannot bulk insert chunks. Store them in memory.', err) |
108 | 109 | ||
109 | processing.forEach(p => { | 110 | processing.forEach(p => { |
110 | this.memoryChunks[p.id] = p.buf | 111 | this.memoryChunks[p.id] = p.buf |
@@ -143,7 +144,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
143 | return cb(null, buf.slice(offset, len + offset)) | 144 | return cb(null, buf.slice(offset, len + offset)) |
144 | }) | 145 | }) |
145 | .catch(err => { | 146 | .catch(err => { |
146 | console.error(err) | 147 | logger.error(err) |
147 | return cb(err) | 148 | return cb(err) |
148 | }) | 149 | }) |
149 | } | 150 | } |
@@ -176,7 +177,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
176 | 177 | ||
177 | return cb() | 178 | return cb() |
178 | } catch (err) { | 179 | } catch (err) { |
179 | console.error('Cannot destroy peertube chunk store.', err) | 180 | logger.error('Cannot destroy peertube chunk store.', err) |
180 | return cb(err) | 181 | return cb(err) |
181 | } | 182 | } |
182 | } | 183 | } |
@@ -204,7 +205,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
204 | databasesToDeleteInfo = await this.expirationDB.databases.where('expiration').below(now).toArray() | 205 | databasesToDeleteInfo = await this.expirationDB.databases.where('expiration').below(now).toArray() |
205 | }) | 206 | }) |
206 | } catch (err) { | 207 | } catch (err) { |
207 | console.error('Cannot update expiration of fetch expired databases.', err) | 208 | logger.error('Cannot update expiration of fetch expired databases.', err) |
208 | } | 209 | } |
209 | 210 | ||
210 | for (const databaseToDeleteInfo of databasesToDeleteInfo) { | 211 | for (const databaseToDeleteInfo of databasesToDeleteInfo) { |
@@ -214,7 +215,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
214 | 215 | ||
215 | private async dropDatabase (databaseName: string) { | 216 | private async dropDatabase (databaseName: string) { |
216 | const dbToDelete = new ChunkDatabase(databaseName) | 217 | const dbToDelete = new ChunkDatabase(databaseName) |
217 | console.log('Destroying IndexDB database %s.', databaseName) | 218 | logger.info(`Destroying IndexDB database ${databaseName}`) |
218 | 219 | ||
219 | try { | 220 | try { |
220 | await dbToDelete.delete() | 221 | await dbToDelete.delete() |
@@ -223,7 +224,7 @@ export class PeertubeChunkStore extends EventEmitter { | |||
223 | return this.expirationDB.databases.where({ name: databaseName }).delete() | 224 | return this.expirationDB.databases.where({ name: databaseName }).delete() |
224 | }) | 225 | }) |
225 | } catch (err) { | 226 | } catch (err) { |
226 | console.error('Cannot delete %s.', databaseName, err) | 227 | logger.error(`Cannot delete ${databaseName}.`, err) |
227 | } | 228 | } |
228 | } | 229 | } |
229 | 230 | ||
diff --git a/client/src/assets/player/shared/webtorrent/video-renderer.ts b/client/src/assets/player/shared/webtorrent/video-renderer.ts index 9b80fea2c..a85d7a838 100644 --- a/client/src/assets/player/shared/webtorrent/video-renderer.ts +++ b/client/src/assets/player/shared/webtorrent/video-renderer.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | // Thanks: https://github.com/feross/render-media | 1 | // Thanks: https://github.com/feross/render-media |
2 | 2 | ||
3 | const MediaElementWrapper = require('mediasource') | 3 | const MediaElementWrapper = require('mediasource') |
4 | import { logger } from '@root-helpers/logger' | ||
4 | import { extname } from 'path' | 5 | import { extname } from 'path' |
5 | const Videostream = require('videostream') | 6 | const Videostream = require('videostream') |
6 | 7 | ||
@@ -77,8 +78,8 @@ function renderMedia (file: any, elem: HTMLVideoElement, opts: RenderMediaOption | |||
77 | } | 78 | } |
78 | 79 | ||
79 | function fallbackToMediaSource (useVP9 = false) { | 80 | function fallbackToMediaSource (useVP9 = false) { |
80 | if (useVP9 === true) console.log('Falling back to media source with VP9 enabled.') | 81 | if (useVP9 === true) logger.info('Falling back to media source with VP9 enabled.') |
81 | else console.log('Falling back to media source..') | 82 | else logger.info('Falling back to media source..') |
82 | 83 | ||
83 | useMediaSource(useVP9) | 84 | useMediaSource(useVP9) |
84 | } | 85 | } |
diff --git a/client/src/assets/player/shared/webtorrent/webtorrent-plugin.ts b/client/src/assets/player/shared/webtorrent/webtorrent-plugin.ts index 83b483d87..ab9ab56ac 100644 --- a/client/src/assets/player/shared/webtorrent/webtorrent-plugin.ts +++ b/client/src/assets/player/shared/webtorrent/webtorrent-plugin.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import videojs from 'video.js' | 1 | import videojs from 'video.js' |
2 | import * as WebTorrent from 'webtorrent' | 2 | import * as WebTorrent from 'webtorrent' |
3 | import { logger } from '@root-helpers/logger' | ||
3 | import { isIOS } from '@root-helpers/web-browser' | 4 | import { isIOS } from '@root-helpers/web-browser' |
4 | import { timeToInt } from '@shared/core-utils' | 5 | import { timeToInt } from '@shared/core-utils' |
5 | import { VideoFile } from '@shared/models' | 6 | import { VideoFile } from '@shared/models' |
@@ -210,7 +211,7 @@ class WebTorrentPlugin extends Plugin { | |||
210 | if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy() | 211 | if (destroyRenderer === true && this.renderer && this.renderer.destroy) this.renderer.destroy() |
211 | 212 | ||
212 | this.webtorrent.remove(videoFile.magnetUri) | 213 | this.webtorrent.remove(videoFile.magnetUri) |
213 | console.log('Removed ' + videoFile.magnetUri) | 214 | logger.info(`Removed ${videoFile.magnetUri}`) |
214 | } | 215 | } |
215 | } | 216 | } |
216 | 217 | ||
@@ -256,7 +257,7 @@ class WebTorrentPlugin extends Plugin { | |||
256 | ) { | 257 | ) { |
257 | if (!magnetOrTorrentUrl) return this.fallbackToHttp(options, done) | 258 | if (!magnetOrTorrentUrl) return this.fallbackToHttp(options, done) |
258 | 259 | ||
259 | console.log('Adding ' + magnetOrTorrentUrl + '.') | 260 | logger.info(`Adding ${magnetOrTorrentUrl}.`) |
260 | 261 | ||
261 | const oldTorrent = this.torrent | 262 | const oldTorrent = this.torrent |
262 | const torrentOptions = { | 263 | const torrentOptions = { |
@@ -269,7 +270,7 @@ class WebTorrentPlugin extends Plugin { | |||
269 | } | 270 | } |
270 | 271 | ||
271 | this.torrent = this.webtorrent.add(magnetOrTorrentUrl, torrentOptions, torrent => { | 272 | this.torrent = this.webtorrent.add(magnetOrTorrentUrl, torrentOptions, torrent => { |
272 | console.log('Added ' + magnetOrTorrentUrl + '.') | 273 | logger.info(`Added ${magnetOrTorrentUrl}.`) |
273 | 274 | ||
274 | if (oldTorrent) { | 275 | if (oldTorrent) { |
275 | // Pause the old torrent | 276 | // Pause the old torrent |
@@ -309,7 +310,7 @@ class WebTorrentPlugin extends Plugin { | |||
309 | }, options.delay || 0) | 310 | }, options.delay || 0) |
310 | }) | 311 | }) |
311 | 312 | ||
312 | this.torrent.on('error', (err: any) => console.error(err)) | 313 | this.torrent.on('error', (err: any) => logger.error(err)) |
313 | 314 | ||
314 | this.torrent.on('warning', (err: any) => { | 315 | this.torrent.on('warning', (err: any) => { |
315 | // We don't support HTTP tracker but we don't care -> we use the web socket tracker | 316 | // We don't support HTTP tracker but we don't care -> we use the web socket tracker |
@@ -317,13 +318,13 @@ class WebTorrentPlugin extends Plugin { | |||
317 | 318 | ||
318 | // Users don't care about issues with WebRTC, but developers do so log it in the console | 319 | // Users don't care about issues with WebRTC, but developers do so log it in the console |
319 | if (err.message.indexOf('Ice connection failed') !== -1) { | 320 | if (err.message.indexOf('Ice connection failed') !== -1) { |
320 | console.log(err) | 321 | logger.info(err) |
321 | return | 322 | return |
322 | } | 323 | } |
323 | 324 | ||
324 | // Magnet hash is not up to date with the torrent file, add directly the torrent file | 325 | // Magnet hash is not up to date with the torrent file, add directly the torrent file |
325 | if (err.message.indexOf('incorrect info hash') !== -1) { | 326 | if (err.message.indexOf('incorrect info hash') !== -1) { |
326 | console.error('Incorrect info hash detected, falling back to torrent file.') | 327 | logger.error('Incorrect info hash detected, falling back to torrent file.') |
327 | const newOptions = { forcePlay: true, seek: options.seek } | 328 | const newOptions = { forcePlay: true, seek: options.seek } |
328 | return this.addTorrent(this.torrent['xs'], previousVideoFile, newOptions, done) | 329 | return this.addTorrent(this.torrent['xs'], previousVideoFile, newOptions, done) |
329 | } | 330 | } |
@@ -333,7 +334,7 @@ class WebTorrentPlugin extends Plugin { | |||
333 | this.handleError(err) | 334 | this.handleError(err) |
334 | } | 335 | } |
335 | 336 | ||
336 | console.warn(err) | 337 | logger.warn(err) |
337 | }) | 338 | }) |
338 | } | 339 | } |
339 | 340 | ||
@@ -348,7 +349,7 @@ class WebTorrentPlugin extends Plugin { | |||
348 | return | 349 | return |
349 | } | 350 | } |
350 | 351 | ||
351 | console.error(err) | 352 | logger.error(err) |
352 | this.player.pause() | 353 | this.player.pause() |
353 | this.player.posterImage.show() | 354 | this.player.posterImage.show() |
354 | this.player.removeClass('vjs-has-autoplay') | 355 | this.player.removeClass('vjs-has-autoplay') |
@@ -465,10 +466,10 @@ class WebTorrentPlugin extends Plugin { | |||
465 | 466 | ||
466 | // Lower resolution | 467 | // Lower resolution |
467 | if (this.isPlayerWaiting() && file.resolution.id < this.currentVideoFile.resolution.id) { | 468 | if (this.isPlayerWaiting() && file.resolution.id < this.currentVideoFile.resolution.id) { |
468 | console.log('Downgrading automatically the resolution to: %s', file.resolution.label) | 469 | logger.info(`Downgrading automatically the resolution to: ${file.resolution.label}`) |
469 | changeResolution = true | 470 | changeResolution = true |
470 | } else if (file.resolution.id > this.currentVideoFile.resolution.id) { // Higher resolution | 471 | } else if (file.resolution.id > this.currentVideoFile.resolution.id) { // Higher resolution |
471 | console.log('Upgrading automatically the resolution to: %s', file.resolution.label) | 472 | logger.info(`Upgrading automatically the resolution to: ${file.resolution.label}`) |
472 | changeResolution = true | 473 | changeResolution = true |
473 | changeResolutionDelay = this.CONSTANTS.AUTO_QUALITY_HIGHER_RESOLUTION_DELAY | 474 | changeResolutionDelay = this.CONSTANTS.AUTO_QUALITY_HIGHER_RESOLUTION_DELAY |
474 | } | 475 | } |
@@ -577,7 +578,7 @@ class WebTorrentPlugin extends Plugin { | |||
577 | 578 | ||
578 | // The renderer returns an error when we destroy it, so skip them | 579 | // The renderer returns an error when we destroy it, so skip them |
579 | if (this.destroyingFakeRenderer === false && err) { | 580 | if (this.destroyingFakeRenderer === false && err) { |
580 | console.error('Cannot render new torrent in fake video element.', err) | 581 | logger.error('Cannot render new torrent in fake video element.', err) |
581 | } | 582 | } |
582 | 583 | ||
583 | // Load the future file at the correct time (in delay MS - 2 seconds) | 584 | // Load the future file at the correct time (in delay MS - 2 seconds) |
@@ -593,7 +594,7 @@ class WebTorrentPlugin extends Plugin { | |||
593 | try { | 594 | try { |
594 | this.fakeRenderer.destroy() | 595 | this.fakeRenderer.destroy() |
595 | } catch (err) { | 596 | } catch (err) { |
596 | console.log('Cannot destroy correctly fake renderer.', err) | 597 | logger.info('Cannot destroy correctly fake renderer.', err) |
597 | } | 598 | } |
598 | } | 599 | } |
599 | this.fakeRenderer = undefined | 600 | this.fakeRenderer = undefined |
diff --git a/client/src/assets/player/translations-manager.ts b/client/src/assets/player/translations-manager.ts index 8a6e67dda..bf9c2d471 100644 --- a/client/src/assets/player/translations-manager.ts +++ b/client/src/assets/player/translations-manager.ts | |||
@@ -1,3 +1,4 @@ | |||
1 | import { logger } from '@root-helpers/logger' | ||
1 | import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '@shared/core-utils/i18n' | 2 | import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '@shared/core-utils/i18n' |
2 | 3 | ||
3 | export class TranslationsManager { | 4 | export class TranslationsManager { |
@@ -11,7 +12,7 @@ export class TranslationsManager { | |||
11 | return fetch(path + '/server.json') | 12 | return fetch(path + '/server.json') |
12 | .then(res => res.json()) | 13 | .then(res => res.json()) |
13 | .catch(err => { | 14 | .catch(err => { |
14 | console.error('Cannot get server translations', err) | 15 | logger.error('Cannot get server translations', err) |
15 | return undefined | 16 | return undefined |
16 | }) | 17 | }) |
17 | } | 18 | } |
@@ -33,7 +34,7 @@ export class TranslationsManager { | |||
33 | return json | 34 | return json |
34 | }) | 35 | }) |
35 | .catch(err => { | 36 | .catch(err => { |
36 | console.error('Cannot get player translations', err) | 37 | logger.error('Cannot get player translations', err) |
37 | return undefined | 38 | return undefined |
38 | }) | 39 | }) |
39 | } | 40 | } |
diff --git a/client/src/main.ts b/client/src/main.ts index 84c82203d..432db0eac 100644 --- a/client/src/main.ts +++ b/client/src/main.ts | |||
@@ -3,11 +3,14 @@ import { enableDebugTools } from '@angular/platform-browser' | |||
3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' | 3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic' |
4 | import { AppModule } from './app/app.module' | 4 | import { AppModule } from './app/app.module' |
5 | import { environment } from './environments/environment' | 5 | import { environment } from './environments/environment' |
6 | import { logger } from './root-helpers' | ||
6 | 7 | ||
7 | if (environment.production) { | 8 | if (environment.production) { |
8 | enableProdMode() | 9 | enableProdMode() |
9 | } | 10 | } |
10 | 11 | ||
12 | logger.registerServerSending(environment.apiUrl) | ||
13 | |||
11 | const bootstrap = () => platformBrowserDynamic() | 14 | const bootstrap = () => platformBrowserDynamic() |
12 | .bootstrapModule(AppModule) | 15 | .bootstrapModule(AppModule) |
13 | .then(bootstrapModule => { | 16 | .then(bootstrapModule => { |
@@ -22,7 +25,7 @@ const bootstrap = () => platformBrowserDynamic() | |||
22 | return bootstrapModule | 25 | return bootstrapModule |
23 | }) | 26 | }) |
24 | .catch(err => { | 27 | .catch(err => { |
25 | console.error(err) | 28 | logger.error(err) |
26 | return null | 29 | return null |
27 | }) | 30 | }) |
28 | 31 | ||
diff --git a/client/src/root-helpers/images.ts b/client/src/root-helpers/images.ts index fb229ce6d..c4b09ec3c 100644 --- a/client/src/root-helpers/images.ts +++ b/client/src/root-helpers/images.ts | |||
@@ -1,8 +1,10 @@ | |||
1 | import { logger } from './logger' | ||
2 | |||
1 | function imageToDataURL (input: File | Blob) { | 3 | function imageToDataURL (input: File | Blob) { |
2 | return new Promise<string>(res => { | 4 | return new Promise<string>(res => { |
3 | const reader = new FileReader() | 5 | const reader = new FileReader() |
4 | 6 | ||
5 | reader.onerror = err => console.error('Cannot read input file.', err) | 7 | reader.onerror = err => logger.error('Cannot read input file.', err) |
6 | reader.onloadend = () => res(reader.result as string) | 8 | reader.onloadend = () => res(reader.result as string) |
7 | reader.readAsDataURL(input) | 9 | reader.readAsDataURL(input) |
8 | }) | 10 | }) |
diff --git a/client/src/root-helpers/index.ts b/client/src/root-helpers/index.ts index a19855761..86301eafa 100644 --- a/client/src/root-helpers/index.ts +++ b/client/src/root-helpers/index.ts | |||
@@ -2,6 +2,7 @@ export * from './users' | |||
2 | export * from './bytes' | 2 | export * from './bytes' |
3 | export * from './images' | 3 | export * from './images' |
4 | export * from './local-storage-utils' | 4 | export * from './local-storage-utils' |
5 | export * from './logger' | ||
5 | export * from './peertube-web-storage' | 6 | export * from './peertube-web-storage' |
6 | export * from './plugins-manager' | 7 | export * from './plugins-manager' |
7 | export * from './string' | 8 | export * from './string' |
diff --git a/client/src/root-helpers/logger.ts b/client/src/root-helpers/logger.ts new file mode 100644 index 000000000..cd559cfa7 --- /dev/null +++ b/client/src/root-helpers/logger.ts | |||
@@ -0,0 +1,138 @@ | |||
1 | import { ClientLogCreate } from '@shared/models/server' | ||
2 | import { peertubeLocalStorage } from './peertube-web-storage' | ||
3 | import { UserTokens } from './users' | ||
4 | |||
5 | export type LoggerHook = (message: LoggerMessage, meta?: LoggerMeta) => void | ||
6 | export type LoggerLevel = 'info' | 'warn' | 'error' | ||
7 | |||
8 | export type LoggerMessage = string | Error | object | ||
9 | export type LoggerMeta = Error | { [ id: string ]: any, err?: Error } | ||
10 | |||
11 | declare global { | ||
12 | interface Window { | ||
13 | logger: Logger | ||
14 | } | ||
15 | } | ||
16 | |||
17 | class Logger { | ||
18 | private readonly hooks: { level: LoggerLevel, hook: LoggerHook }[] = [] | ||
19 | |||
20 | info (message: LoggerMessage, meta?: LoggerMeta) { | ||
21 | this.runHooks('info', message, meta) | ||
22 | |||
23 | if (meta) console.log(message, meta) | ||
24 | else console.log(message) | ||
25 | } | ||
26 | |||
27 | warn (message: LoggerMessage, meta?: LoggerMeta) { | ||
28 | this.runHooks('warn', message, meta) | ||
29 | |||
30 | if (meta) console.warn(message, meta) | ||
31 | else console.warn(message) | ||
32 | } | ||
33 | |||
34 | error (message: LoggerMessage, meta?: LoggerMeta) { | ||
35 | this.runHooks('error', message, meta) | ||
36 | |||
37 | if (meta) console.error(message, meta) | ||
38 | else console.error(message) | ||
39 | } | ||
40 | |||
41 | addHook (level: LoggerLevel, hook: LoggerHook) { | ||
42 | this.hooks.push({ level, hook }) | ||
43 | } | ||
44 | |||
45 | registerServerSending (serverUrl: string) { | ||
46 | this.addHook('warn', (message, meta) => this.sendClientLog(serverUrl, this.buildServerLogPayload('warn', message, meta))) | ||
47 | this.addHook('error', (message, meta) => this.sendClientLog(serverUrl, this.buildServerLogPayload('error', message, meta))) | ||
48 | } | ||
49 | |||
50 | sendClientLog (serverUrl: string, payload: ClientLogCreate | null) { | ||
51 | if (!payload) return | ||
52 | |||
53 | const headers = new Headers({ | ||
54 | Accept: 'application/json', | ||
55 | 'Content-Type': 'application/json' | ||
56 | }) | ||
57 | |||
58 | try { | ||
59 | const tokens = UserTokens.getUserTokens(peertubeLocalStorage) | ||
60 | |||
61 | if (tokens) headers.set('Authorization', `${tokens.tokenType} ${tokens.accessToken}`) | ||
62 | } catch (err) { | ||
63 | console.error('Cannot set tokens to client log sender.', { err }) | ||
64 | } | ||
65 | |||
66 | try { | ||
67 | fetch(serverUrl + '/api/v1/server/logs/client', { | ||
68 | headers, | ||
69 | method: 'POST', | ||
70 | body: JSON.stringify(payload) | ||
71 | }) | ||
72 | } catch (err) { | ||
73 | console.error('Cannot send client warn/error to server.', err) | ||
74 | } | ||
75 | } | ||
76 | |||
77 | private buildServerLogPayload (level: Extract<LoggerLevel, 'warn' | 'error'>, message: LoggerMessage, meta?: LoggerMeta) { | ||
78 | if (!message) return null | ||
79 | |||
80 | return { | ||
81 | message: this.buildMessageServerLogPayload(message), | ||
82 | userAgent: navigator.userAgent, | ||
83 | url: window.location.href, | ||
84 | level, | ||
85 | stackTrace: this.buildStackServerLogPayload(message, meta), | ||
86 | meta: this.buildMetaServerLogPayload(meta) | ||
87 | } | ||
88 | } | ||
89 | |||
90 | private buildMessageServerLogPayload (message: LoggerMessage) { | ||
91 | if (typeof message === 'string') return message | ||
92 | if (message instanceof Error) return message.message | ||
93 | |||
94 | return JSON.stringify(message) | ||
95 | } | ||
96 | |||
97 | private buildStackServerLogPayload (message: LoggerMessage, meta?: LoggerMeta) { | ||
98 | if (message instanceof Error) return message.stack | ||
99 | if (meta instanceof Error) return meta.stack | ||
100 | if (meta?.err instanceof Error) return meta.err.stack | ||
101 | |||
102 | return undefined | ||
103 | } | ||
104 | |||
105 | private buildMetaServerLogPayload (meta?: LoggerMeta) { | ||
106 | if (!meta) return undefined | ||
107 | if (meta instanceof Error) return undefined | ||
108 | |||
109 | let result: string | ||
110 | |||
111 | try { | ||
112 | result = JSON.stringify(meta, (key, value) => { | ||
113 | if (key === 'err') return undefined | ||
114 | |||
115 | return value | ||
116 | }) | ||
117 | } catch (err) { | ||
118 | console.error('Cannot stringify meta.', err) | ||
119 | } | ||
120 | |||
121 | return result | ||
122 | } | ||
123 | |||
124 | private runHooks (level: LoggerLevel, message: LoggerMessage, meta?: LoggerMeta) { | ||
125 | for (const hookObj of this.hooks) { | ||
126 | if (hookObj.level !== level) continue | ||
127 | |||
128 | hookObj.hook(message, meta) | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | const logger = window.logger || new Logger() | ||
134 | window.logger = logger | ||
135 | |||
136 | export { | ||
137 | logger | ||
138 | } | ||
diff --git a/client/src/root-helpers/plugins-manager.ts b/client/src/root-helpers/plugins-manager.ts index 49a19781b..37a52be72 100644 --- a/client/src/root-helpers/plugins-manager.ts +++ b/client/src/root-helpers/plugins-manager.ts | |||
@@ -21,6 +21,7 @@ import { | |||
21 | } from '@shared/models' | 21 | } from '@shared/models' |
22 | import { environment } from '../environments/environment' | 22 | import { environment } from '../environments/environment' |
23 | import { ClientScript } from '../types' | 23 | import { ClientScript } from '../types' |
24 | import { logger } from './logger' | ||
24 | 25 | ||
25 | interface HookStructValue extends RegisterClientHookOptions { | 26 | interface HookStructValue extends RegisterClientHookOptions { |
26 | plugin: ServerConfigPlugin | 27 | plugin: ServerConfigPlugin |
@@ -48,7 +49,7 @@ type OnSettingsScripts = (pluginInfo: PluginInfo, options: RegisterClientSetting | |||
48 | 49 | ||
49 | type OnClientRoute = (options: RegisterClientRouteOptions) => void | 50 | type OnClientRoute = (options: RegisterClientRouteOptions) => void |
50 | 51 | ||
51 | const logger = debug('peertube:plugins') | 52 | const debugLogger = debug('peertube:plugins') |
52 | 53 | ||
53 | class PluginsManager { | 54 | class PluginsManager { |
54 | private hooks: Hooks = {} | 55 | private hooks: Hooks = {} |
@@ -109,10 +110,10 @@ class PluginsManager { | |||
109 | const hookType = getHookType(hookName) | 110 | const hookType = getHookType(hookName) |
110 | 111 | ||
111 | for (const hook of this.hooks[hookName]) { | 112 | for (const hook of this.hooks[hookName]) { |
112 | console.log('Running hook %s of plugin %s.', hookName, hook.plugin.name) | 113 | logger.info(`Running hook ${hookName} of plugin ${hook.plugin.name}`) |
113 | 114 | ||
114 | result = await internalRunHook(hook.handler, hookType, result, params, err => { | 115 | result = await internalRunHook(hook.handler, hookType, result, params, err => { |
115 | console.error('Cannot run hook %s of script %s of plugin %s.', hookName, hook.clientScript.script, hook.plugin.name, err) | 116 | logger.error(`Cannot run hook ${hookName} of script ${hook.clientScript.script} of plugin ${hook.plugin.name}`, err) |
116 | }) | 117 | }) |
117 | } | 118 | } |
118 | 119 | ||
@@ -170,7 +171,7 @@ class PluginsManager { | |||
170 | 171 | ||
171 | this.loadingScopes[scope] = true | 172 | this.loadingScopes[scope] = true |
172 | 173 | ||
173 | logger('Loading scope %s', scope) | 174 | debugLogger('Loading scope %s', scope) |
174 | 175 | ||
175 | try { | 176 | try { |
176 | if (!isReload) this.loadedScopes.push(scope) | 177 | if (!isReload) this.loadedScopes.push(scope) |
@@ -180,7 +181,7 @@ class PluginsManager { | |||
180 | this.loadingScopes[scope] = false | 181 | this.loadingScopes[scope] = false |
181 | this.pluginsLoaded[scope].next(true) | 182 | this.pluginsLoaded[scope].next(true) |
182 | 183 | ||
183 | logger('Nothing to load for scope %s', scope) | 184 | debugLogger('Nothing to load for scope %s', scope) |
184 | return | 185 | return |
185 | } | 186 | } |
186 | 187 | ||
@@ -200,9 +201,9 @@ class PluginsManager { | |||
200 | this.pluginsLoaded[scope].next(true) | 201 | this.pluginsLoaded[scope].next(true) |
201 | this.loadingScopes[scope] = false | 202 | this.loadingScopes[scope] = false |
202 | 203 | ||
203 | logger('Scope %s loaded', scope) | 204 | debugLogger('Scope %s loaded', scope) |
204 | } catch (err) { | 205 | } catch (err) { |
205 | console.error('Cannot load plugins by scope %s.', scope, err) | 206 | logger.error(`Cannot load plugins by scope ${scope}`, err) |
206 | } | 207 | } |
207 | } | 208 | } |
208 | 209 | ||
@@ -211,7 +212,7 @@ class PluginsManager { | |||
211 | 212 | ||
212 | const registerHook = (options: RegisterClientHookOptions) => { | 213 | const registerHook = (options: RegisterClientHookOptions) => { |
213 | if (clientHookObject[options.target] !== true) { | 214 | if (clientHookObject[options.target] !== true) { |
214 | console.error('Unknown hook %s of plugin %s. Skipping.', options.target, plugin.name) | 215 | logger.error(`Unknown hook ${options.target} of plugin ${plugin.name}. Skipping.`) |
215 | return | 216 | return |
216 | } | 217 | } |
217 | 218 | ||
@@ -252,7 +253,7 @@ class PluginsManager { | |||
252 | 253 | ||
253 | const peertubeHelpers = this.peertubeHelpersFactory(pluginInfo) | 254 | const peertubeHelpers = this.peertubeHelpersFactory(pluginInfo) |
254 | 255 | ||
255 | console.log('Loading script %s of plugin %s.', clientScript.script, plugin.name) | 256 | logger.info(`Loading script ${clientScript.script} of plugin ${plugin.name}`) |
256 | 257 | ||
257 | const absURL = (environment.apiUrl || window.location.origin) + clientScript.script | 258 | const absURL = (environment.apiUrl || window.location.origin) + clientScript.script |
258 | return dynamicImport(absURL) | 259 | return dynamicImport(absURL) |
@@ -266,7 +267,7 @@ class PluginsManager { | |||
266 | }) | 267 | }) |
267 | }) | 268 | }) |
268 | .then(() => this.sortHooksByPriority()) | 269 | .then(() => this.sortHooksByPriority()) |
269 | .catch(err => console.error('Cannot import or register plugin %s.', pluginInfo.plugin.name, err)) | 270 | .catch(err => logger.error(`Cannot import or register plugin ${pluginInfo.plugin.name}`, err)) |
270 | } | 271 | } |
271 | 272 | ||
272 | private sortHooksByPriority () { | 273 | private sortHooksByPriority () { |
@@ -294,7 +295,7 @@ async function dynamicImport (url: string) { | |||
294 | // eslint-disable-next-line no-new-func | 295 | // eslint-disable-next-line no-new-func |
295 | return new Function(`return import('${url}')`)() | 296 | return new Function(`return import('${url}')`)() |
296 | } catch { | 297 | } catch { |
297 | console.log('Fallback to import polyfill') | 298 | logger.info('Fallback to import polyfill') |
298 | 299 | ||
299 | return new Promise((resolve, reject) => { | 300 | return new Promise((resolve, reject) => { |
300 | const vector = '$importModule$' + Math.random().toString(32).slice(2) | 301 | const vector = '$importModule$' + Math.random().toString(32).slice(2) |
diff --git a/client/src/standalone/videos/embed-api.ts b/client/src/standalone/videos/embed-api.ts index 84d664654..2124b4711 100644 --- a/client/src/standalone/videos/embed-api.ts +++ b/client/src/standalone/videos/embed-api.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import './embed.scss' | 1 | import './embed.scss' |
2 | |||
3 | import * as Channel from 'jschannel' | 2 | import * as Channel from 'jschannel' |
3 | import { logger } from '../../root-helpers' | ||
4 | import { PeerTubeResolution, PeerTubeTextTrack } from '../player/definitions' | 4 | import { PeerTubeResolution, PeerTubeTextTrack } from '../player/definitions' |
5 | import { PeerTubeEmbed } from './embed' | 5 | import { PeerTubeEmbed } from './embed' |
6 | 6 | ||
@@ -59,7 +59,7 @@ export class PeerTubeEmbedApi { | |||
59 | } | 59 | } |
60 | 60 | ||
61 | private setResolution (resolutionId: number) { | 61 | private setResolution (resolutionId: number) { |
62 | console.log('set resolution %d', resolutionId) | 62 | logger.info(`Set resolution ${resolutionId}`) |
63 | 63 | ||
64 | if (this.isWebtorrent()) { | 64 | if (this.isWebtorrent()) { |
65 | if (resolutionId === -1 && this.embed.player.webtorrent().isAutoResolutionPossible() === false) return | 65 | if (resolutionId === -1 && this.embed.player.webtorrent().isAutoResolutionPossible() === false) return |
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index c15d4db17..5384ada1c 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts | |||
@@ -6,7 +6,7 @@ import { peertubeTranslate } from '../../../../shared/core-utils/i18n' | |||
6 | import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models' | 6 | import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models' |
7 | import { PeertubePlayerManager } from '../../assets/player' | 7 | import { PeertubePlayerManager } from '../../assets/player' |
8 | import { TranslationsManager } from '../../assets/player/translations-manager' | 8 | import { TranslationsManager } from '../../assets/player/translations-manager' |
9 | import { getParamString } from '../../root-helpers' | 9 | import { getParamString, logger } from '../../root-helpers' |
10 | import { PeerTubeEmbedApi } from './embed-api' | 10 | import { PeerTubeEmbedApi } from './embed-api' |
11 | import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared' | 11 | import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared' |
12 | import { PlayerHTML } from './shared/player-html' | 12 | import { PlayerHTML } from './shared/player-html' |
@@ -31,6 +31,8 @@ export class PeerTubeEmbed { | |||
31 | private playlistTracker: PlaylistTracker | 31 | private playlistTracker: PlaylistTracker |
32 | 32 | ||
33 | constructor (videoWrapperId: string) { | 33 | constructor (videoWrapperId: string) { |
34 | logger.registerServerSending(window.location.origin) | ||
35 | |||
34 | this.http = new AuthHTTP() | 36 | this.http = new AuthHTTP() |
35 | 37 | ||
36 | this.videoFetcher = new VideoFetcher(this.http) | 38 | this.videoFetcher = new VideoFetcher(this.http) |
@@ -43,7 +45,7 @@ export class PeerTubeEmbed { | |||
43 | try { | 45 | try { |
44 | this.config = JSON.parse(window['PeerTubeServerConfig']) | 46 | this.config = JSON.parse(window['PeerTubeServerConfig']) |
45 | } catch (err) { | 47 | } catch (err) { |
46 | console.error('Cannot parse HTML config.', err) | 48 | logger.error('Cannot parse HTML config.', err) |
47 | } | 49 | } |
48 | } | 50 | } |
49 | 51 | ||
@@ -125,7 +127,7 @@ export class PeerTubeEmbed { | |||
125 | async playNextPlaylistVideo () { | 127 | async playNextPlaylistVideo () { |
126 | const next = this.playlistTracker.getNextPlaylistElement() | 128 | const next = this.playlistTracker.getNextPlaylistElement() |
127 | if (!next) { | 129 | if (!next) { |
128 | console.log('Next element not found in playlist.') | 130 | logger.info('Next element not found in playlist.') |
129 | return | 131 | return |
130 | } | 132 | } |
131 | 133 | ||
@@ -137,7 +139,7 @@ export class PeerTubeEmbed { | |||
137 | async playPreviousPlaylistVideo () { | 139 | async playPreviousPlaylistVideo () { |
138 | const previous = this.playlistTracker.getPreviousPlaylistElement() | 140 | const previous = this.playlistTracker.getPreviousPlaylistElement() |
139 | if (!previous) { | 141 | if (!previous) { |
140 | console.log('Previous element not found in playlist.') | 142 | logger.info('Previous element not found in playlist.') |
141 | return | 143 | return |
142 | } | 144 | } |
143 | 145 | ||
@@ -343,5 +345,5 @@ PeerTubeEmbed.main() | |||
343 | .catch(err => { | 345 | .catch(err => { |
344 | (window as any).displayIncompatibleBrowser() | 346 | (window as any).displayIncompatibleBrowser() |
345 | 347 | ||
346 | console.error('Cannot init embed.', err) | 348 | logger.error('Cannot init embed.', err) |
347 | }) | 349 | }) |
diff --git a/client/src/standalone/videos/shared/player-html.ts b/client/src/standalone/videos/shared/player-html.ts index eb6324ac7..61231d2cb 100644 --- a/client/src/standalone/videos/shared/player-html.ts +++ b/client/src/standalone/videos/shared/player-html.ts | |||
@@ -1,5 +1,6 @@ | |||
1 | import { peertubeTranslate } from '../../../../../shared/core-utils/i18n' | 1 | import { peertubeTranslate } from '../../../../../shared/core-utils/i18n' |
2 | import { VideoDetails } from '../../../../../shared/models' | 2 | import { VideoDetails } from '../../../../../shared/models' |
3 | import { logger } from '../../../root-helpers' | ||
3 | import { Translations } from './translations' | 4 | import { Translations } from './translations' |
4 | 5 | ||
5 | export class PlayerHTML { | 6 | export class PlayerHTML { |
@@ -29,7 +30,7 @@ export class PlayerHTML { | |||
29 | } | 30 | } |
30 | 31 | ||
31 | displayError (text: string, translations: Translations) { | 32 | displayError (text: string, translations: Translations) { |
32 | console.error(text) | 33 | logger.error(text) |
33 | 34 | ||
34 | // Remove video element | 35 | // Remove video element |
35 | if (this.playerElement) { | 36 | if (this.playerElement) { |
diff --git a/client/src/standalone/videos/shared/player-manager-options.ts b/client/src/standalone/videos/shared/player-manager-options.ts index f3bd46a69..2eeb5ecac 100644 --- a/client/src/standalone/videos/shared/player-manager-options.ts +++ b/client/src/standalone/videos/shared/player-manager-options.ts | |||
@@ -14,6 +14,7 @@ import { | |||
14 | getParamString, | 14 | getParamString, |
15 | getParamToggle, | 15 | getParamToggle, |
16 | isP2PEnabled, | 16 | isP2PEnabled, |
17 | logger, | ||
17 | peertubeLocalStorage, | 18 | peertubeLocalStorage, |
18 | UserLocalStorageKeys | 19 | UserLocalStorageKeys |
19 | } from '../../../root-helpers' | 20 | } from '../../../root-helpers' |
@@ -137,7 +138,7 @@ export class PlayerManagerOptions { | |||
137 | else this.mode = 'webtorrent' | 138 | else this.mode = 'webtorrent' |
138 | } | 139 | } |
139 | } catch (err) { | 140 | } catch (err) { |
140 | console.error('Cannot get params from URL.', err) | 141 | logger.error('Cannot get params from URL.', err) |
141 | } | 142 | } |
142 | } | 143 | } |
143 | 144 | ||
diff --git a/client/src/standalone/videos/shared/playlist-fetcher.ts b/client/src/standalone/videos/shared/playlist-fetcher.ts index a7e72c177..713d82e3a 100644 --- a/client/src/standalone/videos/shared/playlist-fetcher.ts +++ b/client/src/standalone/videos/shared/playlist-fetcher.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { HttpStatusCode, ResultList, VideoPlaylistElement } from '../../../../../shared/models' | 1 | import { HttpStatusCode, ResultList, VideoPlaylistElement } from '../../../../../shared/models' |
2 | import { logger } from '../../../root-helpers' | ||
2 | import { AuthHTTP } from './auth-http' | 3 | import { AuthHTTP } from './auth-http' |
3 | 4 | ||
4 | export class PlaylistFetcher { | 5 | export class PlaylistFetcher { |
@@ -18,7 +19,7 @@ export class PlaylistFetcher { | |||
18 | playlistResponse = await playlistPromise | 19 | playlistResponse = await playlistPromise |
19 | isResponseOk = playlistResponse.status === HttpStatusCode.OK_200 | 20 | isResponseOk = playlistResponse.status === HttpStatusCode.OK_200 |
20 | } catch (err) { | 21 | } catch (err) { |
21 | console.error(err) | 22 | logger.error(err) |
22 | isResponseOk = false | 23 | isResponseOk = false |
23 | } | 24 | } |
24 | 25 | ||
@@ -49,7 +50,7 @@ export class PlaylistFetcher { | |||
49 | } | 50 | } |
50 | 51 | ||
51 | if (i === 10) { | 52 | if (i === 10) { |
52 | console.error('Cannot fetch all playlists elements, there are too many!') | 53 | logger.error('Cannot fetch all playlists elements, there are too many!') |
53 | } | 54 | } |
54 | 55 | ||
55 | return elements | 56 | return elements |
diff --git a/client/src/standalone/videos/shared/playlist-tracker.ts b/client/src/standalone/videos/shared/playlist-tracker.ts index 75d10b4e2..9ea4be83f 100644 --- a/client/src/standalone/videos/shared/playlist-tracker.ts +++ b/client/src/standalone/videos/shared/playlist-tracker.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { VideoPlaylist, VideoPlaylistElement } from '../../../../../shared/models' | 1 | import { VideoPlaylist, VideoPlaylistElement } from '../../../../../shared/models' |
2 | import { logger } from '../../../root-helpers' | ||
2 | 3 | ||
3 | export class PlaylistTracker { | 4 | export class PlaylistTracker { |
4 | private currentPlaylistElement: VideoPlaylistElement | 5 | private currentPlaylistElement: VideoPlaylistElement |
@@ -68,7 +69,7 @@ export class PlaylistTracker { | |||
68 | setPosition (position: number) { | 69 | setPosition (position: number) { |
69 | this.currentPlaylistElement = this.playlistElements.find(e => e.position === position) | 70 | this.currentPlaylistElement = this.playlistElements.find(e => e.position === position) |
70 | if (!this.currentPlaylistElement || !this.currentPlaylistElement.video) { | 71 | if (!this.currentPlaylistElement || !this.currentPlaylistElement.video) { |
71 | console.error('Current playlist element is not valid.', this.currentPlaylistElement) | 72 | logger.error('Current playlist element is not valid.', this.currentPlaylistElement) |
72 | this.currentPlaylistElement = this.getNextPlaylistElement() | 73 | this.currentPlaylistElement = this.getNextPlaylistElement() |
73 | } | 74 | } |
74 | 75 | ||
diff --git a/client/src/standalone/videos/shared/video-fetcher.ts b/client/src/standalone/videos/shared/video-fetcher.ts index e78d38536..b42d622f9 100644 --- a/client/src/standalone/videos/shared/video-fetcher.ts +++ b/client/src/standalone/videos/shared/video-fetcher.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { HttpStatusCode, LiveVideo, VideoDetails } from '../../../../../shared/models' | 1 | import { HttpStatusCode, LiveVideo, VideoDetails } from '../../../../../shared/models' |
2 | import { logger } from '../../../root-helpers' | ||
2 | import { AuthHTTP } from './auth-http' | 3 | import { AuthHTTP } from './auth-http' |
3 | 4 | ||
4 | export class VideoFetcher { | 5 | export class VideoFetcher { |
@@ -17,7 +18,7 @@ export class VideoFetcher { | |||
17 | videoResponse = await videoPromise | 18 | videoResponse = await videoPromise |
18 | isResponseOk = videoResponse.status === HttpStatusCode.OK_200 | 19 | isResponseOk = videoResponse.status === HttpStatusCode.OK_200 |
19 | } catch (err) { | 20 | } catch (err) { |
20 | console.error(err) | 21 | logger.error(err) |
21 | 22 | ||
22 | isResponseOk = false | 23 | isResponseOk = false |
23 | } | 24 | } |
diff --git a/client/src/standalone/videos/test-embed.ts b/client/src/standalone/videos/test-embed.ts index 18c338a2d..ab5262902 100644 --- a/client/src/standalone/videos/test-embed.ts +++ b/client/src/standalone/videos/test-embed.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import './test-embed.scss' | 1 | import './test-embed.scss' |
2 | import { PeerTubeResolution, PlayerEventType } from '../player/definitions' | 2 | import { PeerTubeResolution, PlayerEventType } from '../player/definitions' |
3 | import { PeerTubePlayer } from '../player/player' | 3 | import { PeerTubePlayer } from '../player/player' |
4 | import { logger } from '../../root-helpers' | ||
4 | 5 | ||
5 | window.addEventListener('load', async () => { | 6 | window.addEventListener('load', async () => { |
6 | const urlParts = window.location.href.split('/') | 7 | const urlParts = window.location.href.split('/') |
@@ -20,14 +21,14 @@ window.addEventListener('load', async () => { | |||
20 | const mainElement = document.querySelector('#host') | 21 | const mainElement = document.querySelector('#host') |
21 | mainElement.appendChild(iframe) | 22 | mainElement.appendChild(iframe) |
22 | 23 | ||
23 | console.log('Document finished loading.') | 24 | logger.info('Document finished loading.') |
24 | const player = new PeerTubePlayer(document.querySelector('iframe')) | 25 | const player = new PeerTubePlayer(document.querySelector('iframe')) |
25 | 26 | ||
26 | window['player'] = player | 27 | window['player'] = player |
27 | 28 | ||
28 | console.log('Awaiting player ready...') | 29 | logger.info('Awaiting player ready...') |
29 | await player.ready | 30 | await player.ready |
30 | console.log('Player is ready.') | 31 | logger.info('Player is ready.') |
31 | 32 | ||
32 | const monitoredEvents = [ | 33 | const monitoredEvents = [ |
33 | 'pause', | 34 | 'pause', |
@@ -37,8 +38,8 @@ window.addEventListener('load', async () => { | |||
37 | ] | 38 | ] |
38 | 39 | ||
39 | monitoredEvents.forEach(e => { | 40 | monitoredEvents.forEach(e => { |
40 | player.addEventListener(e as PlayerEventType, (param) => console.log(`PLAYER: event '${e}' received`, param)) | 41 | player.addEventListener(e as PlayerEventType, (param) => logger.info(`PLAYER: event '${e}' received`, { param })) |
41 | console.log(`PLAYER: now listening for event '${e}'`) | 42 | logger.info(`PLAYER: now listening for event '${e}'`) |
42 | 43 | ||
43 | player.getCurrentPosition() | 44 | player.getCurrentPosition() |
44 | .then(position => { | 45 | .then(position => { |
diff --git a/client/src/standalone/videos/tsconfig.json b/client/src/standalone/videos/tsconfig.json new file mode 100644 index 000000000..e0cab7ca3 --- /dev/null +++ b/client/src/standalone/videos/tsconfig.json | |||
@@ -0,0 +1,7 @@ | |||
1 | { | ||
2 | "extends": "../../../tsconfig.json", | ||
3 | "include": [ | ||
4 | "src/standalone/videos/embed.ts", | ||
5 | "src/standalone/videos/test-embed.ts" | ||
6 | ] | ||
7 | } | ||
diff --git a/client/webpack/webpack.video-embed.js b/client/webpack/webpack.video-embed.js index f5c75dd47..547e8aa63 100644 --- a/client/webpack/webpack.video-embed.js +++ b/client/webpack/webpack.video-embed.js | |||
@@ -69,7 +69,7 @@ module.exports = function () { | |||
69 | { | 69 | { |
70 | loader: 'ts-loader', | 70 | loader: 'ts-loader', |
71 | options: { | 71 | options: { |
72 | configFile: helpers.root('tsconfig.json') | 72 | configFile: helpers.root('src/standalone/videos/tsconfig.json') |
73 | } | 73 | } |
74 | } | 74 | } |
75 | ] | 75 | ] |
diff --git a/config/default.yaml b/config/default.yaml index 2c1b9c64f..7e07165b9 100644 --- a/config/default.yaml +++ b/config/default.yaml | |||
@@ -27,6 +27,10 @@ rates_limit: | |||
27 | # 3 attempts in 5 min | 27 | # 3 attempts in 5 min |
28 | window: 5 minutes | 28 | window: 5 minutes |
29 | max: 3 | 29 | max: 3 |
30 | receive_client_log: | ||
31 | # 10 attempts in 10 min | ||
32 | window: 10 minutes | ||
33 | max: 10 | ||
30 | 34 | ||
31 | # Proxies to trust to get real client IP | 35 | # Proxies to trust to get real client IP |
32 | # If you run PeerTube just behind a local proxy (nginx), keep 'loopback' | 36 | # If you run PeerTube just behind a local proxy (nginx), keep 'loopback' |
@@ -168,15 +172,22 @@ object_storage: | |||
168 | 172 | ||
169 | log: | 173 | log: |
170 | level: 'info' # 'debug' | 'info' | 'warn' | 'error' | 174 | level: 'info' # 'debug' | 'info' | 'warn' | 'error' |
175 | |||
171 | rotation: | 176 | rotation: |
172 | enabled : true # Enabled by default, if disabled make sure that 'storage.logs' is pointing to a folder handled by logrotate | 177 | enabled : true # Enabled by default, if disabled make sure that 'storage.logs' is pointing to a folder handled by logrotate |
173 | max_file_size: 12MB | 178 | max_file_size: 12MB |
174 | max_files: 20 | 179 | max_files: 20 |
180 | |||
175 | anonymize_ip: false | 181 | anonymize_ip: false |
182 | |||
176 | log_ping_requests: true | 183 | log_ping_requests: true |
177 | log_tracker_unknown_infohash: true | 184 | log_tracker_unknown_infohash: true |
185 | |||
178 | prettify_sql: false | 186 | prettify_sql: false |
179 | 187 | ||
188 | # Accept warn/error logs coming from the client | ||
189 | accept_client_log: true | ||
190 | |||
180 | # Highly experimental support of Open Telemetry | 191 | # Highly experimental support of Open Telemetry |
181 | open_telemetry: | 192 | open_telemetry: |
182 | metrics: | 193 | metrics: |
diff --git a/config/production.yaml.example b/config/production.yaml.example index 3e4035eaa..042f5a641 100644 --- a/config/production.yaml.example +++ b/config/production.yaml.example | |||
@@ -25,6 +25,10 @@ rates_limit: | |||
25 | # 3 attempts in 5 min | 25 | # 3 attempts in 5 min |
26 | window: 5 minutes | 26 | window: 5 minutes |
27 | max: 3 | 27 | max: 3 |
28 | receive_client_log: | ||
29 | # 10 attempts in 10 min | ||
30 | window: 10 minutes | ||
31 | max: 10 | ||
28 | 32 | ||
29 | # Proxies to trust to get real client IP | 33 | # Proxies to trust to get real client IP |
30 | # If you run PeerTube just behind a local proxy (nginx), keep 'loopback' | 34 | # If you run PeerTube just behind a local proxy (nginx), keep 'loopback' |
@@ -166,15 +170,22 @@ object_storage: | |||
166 | 170 | ||
167 | log: | 171 | log: |
168 | level: 'info' # 'debug' | 'info' | 'warn' | 'error' | 172 | level: 'info' # 'debug' | 'info' | 'warn' | 'error' |
173 | |||
169 | rotation: | 174 | rotation: |
170 | enabled : true # Enabled by default, if disabled make sure that 'storage.logs' is pointing to a folder handled by logrotate | 175 | enabled : true # Enabled by default, if disabled make sure that 'storage.logs' is pointing to a folder handled by logrotate |
171 | max_file_size: 12MB | 176 | max_file_size: 12MB |
172 | max_files: 20 | 177 | max_files: 20 |
178 | |||
173 | anonymize_ip: false | 179 | anonymize_ip: false |
180 | |||
174 | log_ping_requests: true | 181 | log_ping_requests: true |
175 | log_tracker_unknown_infohash: true | 182 | log_tracker_unknown_infohash: true |
183 | |||
176 | prettify_sql: false | 184 | prettify_sql: false |
177 | 185 | ||
186 | # Accept warn/error logs coming from the client | ||
187 | accept_client_log: true | ||
188 | |||
178 | # Highly experimental support of Open Telemetry | 189 | # Highly experimental support of Open Telemetry |
179 | open_telemetry: | 190 | open_telemetry: |
180 | metrics: | 191 | metrics: |
diff --git a/server/controllers/api/server/logs.ts b/server/controllers/api/server/logs.ts index 8aa4b7190..ed0aa6e8e 100644 --- a/server/controllers/api/server/logs.ts +++ b/server/controllers/api/server/logs.ts | |||
@@ -3,15 +3,29 @@ import { readdir, readFile } from 'fs-extra' | |||
3 | import { join } from 'path' | 3 | import { join } from 'path' |
4 | import { isArray } from '@server/helpers/custom-validators/misc' | 4 | import { isArray } from '@server/helpers/custom-validators/misc' |
5 | import { logger, mtimeSortFilesDesc } from '@server/helpers/logger' | 5 | import { logger, mtimeSortFilesDesc } from '@server/helpers/logger' |
6 | import { LogLevel } from '../../../../shared/models/server/log-level.type' | 6 | import { pick } from '@shared/core-utils' |
7 | import { ClientLogCreate, HttpStatusCode } from '@shared/models' | ||
8 | import { ServerLogLevel } from '../../../../shared/models/server/server-log-level.type' | ||
7 | import { UserRight } from '../../../../shared/models/users' | 9 | import { UserRight } from '../../../../shared/models/users' |
8 | import { CONFIG } from '../../../initializers/config' | 10 | import { CONFIG } from '../../../initializers/config' |
9 | import { AUDIT_LOG_FILENAME, LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers/constants' | 11 | import { AUDIT_LOG_FILENAME, LOG_FILENAME, MAX_LOGS_OUTPUT_CHARACTERS } from '../../../initializers/constants' |
10 | import { asyncMiddleware, authenticate, ensureUserHasRight } from '../../../middlewares' | 12 | import { asyncMiddleware, authenticate, buildRateLimiter, ensureUserHasRight, optionalAuthenticate } from '../../../middlewares' |
11 | import { getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs' | 13 | import { createClientLogValidator, getAuditLogsValidator, getLogsValidator } from '../../../middlewares/validators/logs' |
14 | |||
15 | const createClientLogRateLimiter = buildRateLimiter({ | ||
16 | windowMs: CONFIG.RATES_LIMIT.RECEIVE_CLIENT_LOG.WINDOW_MS, | ||
17 | max: CONFIG.RATES_LIMIT.RECEIVE_CLIENT_LOG.MAX | ||
18 | }) | ||
12 | 19 | ||
13 | const logsRouter = express.Router() | 20 | const logsRouter = express.Router() |
14 | 21 | ||
22 | logsRouter.post('/logs/client', | ||
23 | createClientLogRateLimiter, | ||
24 | optionalAuthenticate, | ||
25 | createClientLogValidator, | ||
26 | createClientLog | ||
27 | ) | ||
28 | |||
15 | logsRouter.get('/logs', | 29 | logsRouter.get('/logs', |
16 | authenticate, | 30 | authenticate, |
17 | ensureUserHasRight(UserRight.MANAGE_LOGS), | 31 | ensureUserHasRight(UserRight.MANAGE_LOGS), |
@@ -34,6 +48,21 @@ export { | |||
34 | 48 | ||
35 | // --------------------------------------------------------------------------- | 49 | // --------------------------------------------------------------------------- |
36 | 50 | ||
51 | function createClientLog (req: express.Request, res: express.Response) { | ||
52 | const logInfo = req.body as ClientLogCreate | ||
53 | |||
54 | const meta = { | ||
55 | tags: [ 'client' ], | ||
56 | username: res.locals.oauth?.token?.User?.username, | ||
57 | |||
58 | ...pick(logInfo, [ 'userAgent', 'stackTrace', 'meta', 'url' ]) | ||
59 | } | ||
60 | |||
61 | logger.log(logInfo.level, `Client log: ${logInfo.message}`, meta) | ||
62 | |||
63 | return res.sendStatus(HttpStatusCode.NO_CONTENT_204) | ||
64 | } | ||
65 | |||
37 | const auditLogNameFilter = generateLogNameFilter(AUDIT_LOG_FILENAME) | 66 | const auditLogNameFilter = generateLogNameFilter(AUDIT_LOG_FILENAME) |
38 | async function getAuditLogs (req: express.Request, res: express.Response) { | 67 | async function getAuditLogs (req: express.Request, res: express.Response) { |
39 | const output = await generateOutput({ | 68 | const output = await generateOutput({ |
@@ -63,7 +92,7 @@ async function generateOutput (options: { | |||
63 | startDateQuery: string | 92 | startDateQuery: string |
64 | endDateQuery?: string | 93 | endDateQuery?: string |
65 | 94 | ||
66 | level: LogLevel | 95 | level: ServerLogLevel |
67 | nameFilter: RegExp | 96 | nameFilter: RegExp |
68 | tagsOneOf?: string[] | 97 | tagsOneOf?: string[] |
69 | }) { | 98 | }) { |
@@ -104,7 +133,7 @@ async function getOutputFromFile (options: { | |||
104 | path: string | 133 | path: string |
105 | startDate: Date | 134 | startDate: Date |
106 | endDate: Date | 135 | endDate: Date |
107 | level: LogLevel | 136 | level: ServerLogLevel |
108 | currentSize: number | 137 | currentSize: number |
109 | tagsOneOf: Set<string> | 138 | tagsOneOf: Set<string> |
110 | }) { | 139 | }) { |
@@ -116,7 +145,7 @@ async function getOutputFromFile (options: { | |||
116 | 145 | ||
117 | let logTime: number | 146 | let logTime: number |
118 | 147 | ||
119 | const logsLevel: { [ id in LogLevel ]: number } = { | 148 | const logsLevel: { [ id in ServerLogLevel ]: number } = { |
120 | audit: -1, | 149 | audit: -1, |
121 | debug: 0, | 150 | debug: 0, |
122 | info: 1, | 151 | info: 1, |
diff --git a/server/helpers/custom-validators/logs.ts b/server/helpers/custom-validators/logs.ts index 0f266ed3b..41d45cbb2 100644 --- a/server/helpers/custom-validators/logs.ts +++ b/server/helpers/custom-validators/logs.ts | |||
@@ -1,14 +1,42 @@ | |||
1 | import validator from 'validator' | ||
2 | import { CONSTRAINTS_FIELDS } from '@server/initializers/constants' | ||
3 | import { ClientLogLevel, ServerLogLevel } from '@shared/models' | ||
1 | import { exists } from './misc' | 4 | import { exists } from './misc' |
2 | import { LogLevel } from '../../../shared/models/server/log-level.type' | ||
3 | 5 | ||
4 | const logLevels: LogLevel[] = [ 'debug', 'info', 'warn', 'error' ] | 6 | const serverLogLevels: Set<ServerLogLevel> = new Set([ 'debug', 'info', 'warn', 'error' ]) |
7 | const clientLogLevels: Set<ClientLogLevel> = new Set([ 'warn', 'error' ]) | ||
5 | 8 | ||
6 | function isValidLogLevel (value: any) { | 9 | function isValidLogLevel (value: any) { |
7 | return exists(value) && logLevels.includes(value) | 10 | return exists(value) && serverLogLevels.has(value) |
11 | } | ||
12 | |||
13 | function isValidClientLogMessage (value: any) { | ||
14 | return typeof value === 'string' && validator.isLength(value, CONSTRAINTS_FIELDS.LOGS.CLIENT_MESSAGE) | ||
15 | } | ||
16 | |||
17 | function isValidClientLogLevel (value: any) { | ||
18 | return exists(value) && clientLogLevels.has(value) | ||
19 | } | ||
20 | |||
21 | function isValidClientLogStackTrace (value: any) { | ||
22 | return typeof value === 'string' && validator.isLength(value, CONSTRAINTS_FIELDS.LOGS.CLIENT_STACK_TRACE) | ||
23 | } | ||
24 | |||
25 | function isValidClientLogMeta (value: any) { | ||
26 | return typeof value === 'string' && validator.isLength(value, CONSTRAINTS_FIELDS.LOGS.CLIENT_META) | ||
27 | } | ||
28 | |||
29 | function isValidClientLogUserAgent (value: any) { | ||
30 | return typeof value === 'string' && validator.isLength(value, CONSTRAINTS_FIELDS.LOGS.CLIENT_USER_AGENT) | ||
8 | } | 31 | } |
9 | 32 | ||
10 | // --------------------------------------------------------------------------- | 33 | // --------------------------------------------------------------------------- |
11 | 34 | ||
12 | export { | 35 | export { |
13 | isValidLogLevel | 36 | isValidLogLevel, |
37 | isValidClientLogMessage, | ||
38 | isValidClientLogStackTrace, | ||
39 | isValidClientLogMeta, | ||
40 | isValidClientLogLevel, | ||
41 | isValidClientLogUserAgent | ||
14 | } | 42 | } |
diff --git a/server/initializers/config.ts b/server/initializers/config.ts index 0943ffe2d..ba0f756ef 100644 --- a/server/initializers/config.ts +++ b/server/initializers/config.ts | |||
@@ -149,6 +149,10 @@ const CONFIG = { | |||
149 | WINDOW_MS: parseDurationToMs(config.get<string>('rates_limit.login.window')), | 149 | WINDOW_MS: parseDurationToMs(config.get<string>('rates_limit.login.window')), |
150 | MAX: config.get<number>('rates_limit.login.max') | 150 | MAX: config.get<number>('rates_limit.login.max') |
151 | }, | 151 | }, |
152 | RECEIVE_CLIENT_LOG: { | ||
153 | WINDOW_MS: parseDurationToMs(config.get<string>('rates_limit.receive_client_log.window')), | ||
154 | MAX: config.get<number>('rates_limit.receive_client_log.max') | ||
155 | }, | ||
152 | ASK_SEND_EMAIL: { | 156 | ASK_SEND_EMAIL: { |
153 | WINDOW_MS: parseDurationToMs(config.get<string>('rates_limit.ask_send_email.window')), | 157 | WINDOW_MS: parseDurationToMs(config.get<string>('rates_limit.ask_send_email.window')), |
154 | MAX: config.get<number>('rates_limit.ask_send_email.max') | 158 | MAX: config.get<number>('rates_limit.ask_send_email.max') |
@@ -165,7 +169,8 @@ const CONFIG = { | |||
165 | ANONYMIZE_IP: config.get<boolean>('log.anonymize_ip'), | 169 | ANONYMIZE_IP: config.get<boolean>('log.anonymize_ip'), |
166 | LOG_PING_REQUESTS: config.get<boolean>('log.log_ping_requests'), | 170 | LOG_PING_REQUESTS: config.get<boolean>('log.log_ping_requests'), |
167 | LOG_TRACKER_UNKNOWN_INFOHASH: config.get<boolean>('log.log_tracker_unknown_infohash'), | 171 | LOG_TRACKER_UNKNOWN_INFOHASH: config.get<boolean>('log.log_tracker_unknown_infohash'), |
168 | PRETTIFY_SQL: config.get<boolean>('log.prettify_sql') | 172 | PRETTIFY_SQL: config.get<boolean>('log.prettify_sql'), |
173 | ACCEPT_CLIENT_LOG: config.get<boolean>('log.accept_client_log') | ||
169 | }, | 174 | }, |
170 | OPEN_TELEMETRY: { | 175 | OPEN_TELEMETRY: { |
171 | METRICS: { | 176 | METRICS: { |
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 009f878fc..8cb4d5f4a 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -365,6 +365,12 @@ const CONSTRAINTS_FIELDS = { | |||
365 | VIDEO_STUDIO: { | 365 | VIDEO_STUDIO: { |
366 | TASKS: { min: 1, max: 10 }, // Number of tasks | 366 | TASKS: { min: 1, max: 10 }, // Number of tasks |
367 | CUT_TIME: { min: 0 } // Value | 367 | CUT_TIME: { min: 0 } // Value |
368 | }, | ||
369 | LOGS: { | ||
370 | CLIENT_MESSAGE: { min: 1, max: 1000 }, // Length | ||
371 | CLIENT_STACK_TRACE: { min: 1, max: 5000 }, // Length | ||
372 | CLIENT_META: { min: 1, max: 5000 }, // Length | ||
373 | CLIENT_USER_AGENT: { min: 1, max: 200 } // Length | ||
368 | } | 374 | } |
369 | } | 375 | } |
370 | 376 | ||
diff --git a/server/middlewares/validators/logs.ts b/server/middlewares/validators/logs.ts index 901d8ca64..324ba6915 100644 --- a/server/middlewares/validators/logs.ts +++ b/server/middlewares/validators/logs.ts | |||
@@ -1,11 +1,56 @@ | |||
1 | import express from 'express' | 1 | import express from 'express' |
2 | import { query } from 'express-validator' | 2 | import { body, query } from 'express-validator' |
3 | import { isUrlValid } from '@server/helpers/custom-validators/activitypub/misc' | ||
3 | import { isStringArray } from '@server/helpers/custom-validators/search' | 4 | import { isStringArray } from '@server/helpers/custom-validators/search' |
4 | import { isValidLogLevel } from '../../helpers/custom-validators/logs' | 5 | import { CONFIG } from '@server/initializers/config' |
6 | import { HttpStatusCode } from '@shared/models' | ||
7 | import { | ||
8 | isValidClientLogLevel, | ||
9 | isValidClientLogMessage, | ||
10 | isValidClientLogMeta, | ||
11 | isValidClientLogStackTrace, | ||
12 | isValidClientLogUserAgent, | ||
13 | isValidLogLevel | ||
14 | } from '../../helpers/custom-validators/logs' | ||
5 | import { isDateValid, toArray } from '../../helpers/custom-validators/misc' | 15 | import { isDateValid, toArray } from '../../helpers/custom-validators/misc' |
6 | import { logger } from '../../helpers/logger' | 16 | import { logger } from '../../helpers/logger' |
7 | import { areValidationErrors } from './shared' | 17 | import { areValidationErrors } from './shared' |
8 | 18 | ||
19 | const createClientLogValidator = [ | ||
20 | body('message') | ||
21 | .custom(isValidClientLogMessage).withMessage('Should have a valid log message'), | ||
22 | |||
23 | body('url') | ||
24 | .custom(isUrlValid).withMessage('Should have a valid log url'), | ||
25 | |||
26 | body('level') | ||
27 | .custom(isValidClientLogLevel).withMessage('Should have a valid log message'), | ||
28 | |||
29 | body('stackTrace') | ||
30 | .optional() | ||
31 | .custom(isValidClientLogStackTrace).withMessage('Should have a valid log stack trace'), | ||
32 | |||
33 | body('meta') | ||
34 | .optional() | ||
35 | .custom(isValidClientLogMeta).withMessage('Should have a valid log meta'), | ||
36 | |||
37 | body('userAgent') | ||
38 | .optional() | ||
39 | .custom(isValidClientLogUserAgent).withMessage('Should have a valid log user agent'), | ||
40 | |||
41 | (req: express.Request, res: express.Response, next: express.NextFunction) => { | ||
42 | logger.debug('Checking createClientLogValidator parameters.', { parameters: req.query }) | ||
43 | |||
44 | if (CONFIG.LOG.ACCEPT_CLIENT_LOG !== true) { | ||
45 | return res.sendStatus(HttpStatusCode.FORBIDDEN_403) | ||
46 | } | ||
47 | |||
48 | if (areValidationErrors(req, res)) return | ||
49 | |||
50 | return next() | ||
51 | } | ||
52 | ] | ||
53 | |||
9 | const getLogsValidator = [ | 54 | const getLogsValidator = [ |
10 | query('startDate') | 55 | query('startDate') |
11 | .custom(isDateValid).withMessage('Should have a start date that conforms to ISO 8601'), | 56 | .custom(isDateValid).withMessage('Should have a start date that conforms to ISO 8601'), |
@@ -49,5 +94,6 @@ const getAuditLogsValidator = [ | |||
49 | 94 | ||
50 | export { | 95 | export { |
51 | getLogsValidator, | 96 | getLogsValidator, |
52 | getAuditLogsValidator | 97 | getAuditLogsValidator, |
98 | createClientLogValidator | ||
53 | } | 99 | } |
diff --git a/server/tests/api/check-params/logs.ts b/server/tests/api/check-params/logs.ts index 970671c15..fa67408b7 100644 --- a/server/tests/api/check-params/logs.ts +++ b/server/tests/api/check-params/logs.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ | 1 | /* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */ |
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | 4 | import { expect } from 'chai' |
5 | import { HttpStatusCode } from '@shared/models' | 5 | import { HttpStatusCode } from '@shared/models' |
6 | import { cleanupTests, createSingleServer, makeGetRequest, PeerTubeServer, setAccessTokensToServers } from '@shared/server-commands' | ||
6 | 7 | ||
7 | describe('Test logs API validators', function () { | 8 | describe('Test logs API validators', function () { |
8 | const path = '/api/v1/server/logs' | 9 | const path = '/api/v1/server/logs' |
@@ -95,6 +96,62 @@ describe('Test logs API validators', function () { | |||
95 | }) | 96 | }) |
96 | }) | 97 | }) |
97 | 98 | ||
99 | describe('When creating client logs', function () { | ||
100 | const base = { | ||
101 | level: 'warn' as 'warn', | ||
102 | message: 'my super message', | ||
103 | url: 'https://example.com/toto' | ||
104 | } | ||
105 | const expectedStatus = HttpStatusCode.BAD_REQUEST_400 | ||
106 | |||
107 | it('Should fail with an invalid level', async function () { | ||
108 | await server.logs.createLogClient({ payload: { ...base, level: '' as any }, expectedStatus }) | ||
109 | await server.logs.createLogClient({ payload: { ...base, level: undefined }, expectedStatus }) | ||
110 | await server.logs.createLogClient({ payload: { ...base, level: 'toto' as any }, expectedStatus }) | ||
111 | }) | ||
112 | |||
113 | it('Should fail with an invalid message', async function () { | ||
114 | await server.logs.createLogClient({ payload: { ...base, message: undefined }, expectedStatus }) | ||
115 | await server.logs.createLogClient({ payload: { ...base, message: '' }, expectedStatus }) | ||
116 | await server.logs.createLogClient({ payload: { ...base, message: 'm'.repeat(2500) }, expectedStatus }) | ||
117 | }) | ||
118 | |||
119 | it('Should fail with an invalid url', async function () { | ||
120 | await server.logs.createLogClient({ payload: { ...base, url: undefined }, expectedStatus }) | ||
121 | await server.logs.createLogClient({ payload: { ...base, url: 'toto' }, expectedStatus }) | ||
122 | }) | ||
123 | |||
124 | it('Should fail with an invalid stackTrace', async function () { | ||
125 | await server.logs.createLogClient({ payload: { ...base, stackTrace: 's'.repeat(10000) }, expectedStatus }) | ||
126 | }) | ||
127 | |||
128 | it('Should fail with an invalid userAgent', async function () { | ||
129 | await server.logs.createLogClient({ payload: { ...base, userAgent: 's'.repeat(500) }, expectedStatus }) | ||
130 | }) | ||
131 | |||
132 | it('Should fail with an invalid meta', async function () { | ||
133 | await server.logs.createLogClient({ payload: { ...base, meta: 's'.repeat(10000) }, expectedStatus }) | ||
134 | }) | ||
135 | |||
136 | it('Should succeed with the correct params', async function () { | ||
137 | await server.logs.createLogClient({ payload: { ...base, stackTrace: 'stackTrace', meta: '{toto}', userAgent: 'userAgent' } }) | ||
138 | }) | ||
139 | |||
140 | it('Should rate limit log creation', async function () { | ||
141 | let fail = false | ||
142 | |||
143 | for (let i = 0; i < 10; i++) { | ||
144 | try { | ||
145 | await server.logs.createLogClient({ token: null, payload: base }) | ||
146 | } catch { | ||
147 | fail = true | ||
148 | } | ||
149 | } | ||
150 | |||
151 | expect(fail).to.be.true | ||
152 | }) | ||
153 | }) | ||
154 | |||
98 | after(async function () { | 155 | after(async function () { |
99 | await cleanupTests([ server ]) | 156 | await cleanupTests([ server ]) |
100 | }) | 157 | }) |
diff --git a/server/tests/api/server/logs.ts b/server/tests/api/server/logs.ts index 697f10337..ed7555fd7 100644 --- a/server/tests/api/server/logs.ts +++ b/server/tests/api/server/logs.ts | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | import 'mocha' | 3 | import 'mocha' |
4 | import * as chai from 'chai' | 4 | import * as chai from 'chai' |
5 | import { HttpStatusCode } from '@shared/models' | ||
5 | import { | 6 | import { |
6 | cleanupTests, | 7 | cleanupTests, |
7 | createSingleServer, | 8 | createSingleServer, |
@@ -198,6 +199,70 @@ describe('Test logs', function () { | |||
198 | }) | 199 | }) |
199 | }) | 200 | }) |
200 | 201 | ||
202 | describe('When creating log from the client', function () { | ||
203 | |||
204 | it('Should create a warn client log', async function () { | ||
205 | const now = new Date() | ||
206 | |||
207 | await server.logs.createLogClient({ | ||
208 | payload: { | ||
209 | level: 'warn', | ||
210 | url: 'http://example.com', | ||
211 | message: 'my super client message' | ||
212 | }, | ||
213 | token: null | ||
214 | }) | ||
215 | |||
216 | const body = await logsCommand.getLogs({ startDate: now }) | ||
217 | const logsString = JSON.stringify(body) | ||
218 | |||
219 | expect(logsString.includes('my super client message')).to.be.true | ||
220 | }) | ||
221 | |||
222 | it('Should create an error authenticated client log', async function () { | ||
223 | const now = new Date() | ||
224 | |||
225 | await server.logs.createLogClient({ | ||
226 | payload: { | ||
227 | url: 'https://example.com/page1', | ||
228 | level: 'error', | ||
229 | message: 'my super client message 2', | ||
230 | userAgent: 'super user agent', | ||
231 | meta: '{hello}', | ||
232 | stackTrace: 'super stack trace' | ||
233 | } | ||
234 | }) | ||
235 | |||
236 | const body = await logsCommand.getLogs({ startDate: now }) | ||
237 | const logsString = JSON.stringify(body) | ||
238 | |||
239 | expect(logsString.includes('my super client message 2')).to.be.true | ||
240 | expect(logsString.includes('super user agent')).to.be.true | ||
241 | expect(logsString.includes('super stack trace')).to.be.true | ||
242 | expect(logsString.includes('{hello}')).to.be.true | ||
243 | expect(logsString.includes('https://example.com/page1')).to.be.true | ||
244 | }) | ||
245 | |||
246 | it('Should refuse to create client logs', async function () { | ||
247 | await server.kill() | ||
248 | |||
249 | await server.run({ | ||
250 | log: { | ||
251 | accept_client_log: false | ||
252 | } | ||
253 | }) | ||
254 | |||
255 | await server.logs.createLogClient({ | ||
256 | payload: { | ||
257 | level: 'warn', | ||
258 | url: 'http://example.com', | ||
259 | message: 'my super client message' | ||
260 | }, | ||
261 | expectedStatus: HttpStatusCode.FORBIDDEN_403 | ||
262 | }) | ||
263 | }) | ||
264 | }) | ||
265 | |||
201 | after(async function () { | 266 | after(async function () { |
202 | await cleanupTests([ server ]) | 267 | await cleanupTests([ server ]) |
203 | }) | 268 | }) |
diff --git a/shared/models/server/client-log-create.model.ts b/shared/models/server/client-log-create.model.ts new file mode 100644 index 000000000..c9dc65568 --- /dev/null +++ b/shared/models/server/client-log-create.model.ts | |||
@@ -0,0 +1,11 @@ | |||
1 | import { ClientLogLevel } from './client-log-level.type' | ||
2 | |||
3 | export interface ClientLogCreate { | ||
4 | message: string | ||
5 | url: string | ||
6 | level: ClientLogLevel | ||
7 | |||
8 | stackTrace?: string | ||
9 | userAgent?: string | ||
10 | meta?: string | ||
11 | } | ||
diff --git a/shared/models/server/client-log-level.type.ts b/shared/models/server/client-log-level.type.ts new file mode 100644 index 000000000..18dea2751 --- /dev/null +++ b/shared/models/server/client-log-level.type.ts | |||
@@ -0,0 +1 @@ | |||
export type ClientLogLevel = 'warn' | 'error' | |||
diff --git a/shared/models/server/index.ts b/shared/models/server/index.ts index 0f7646c7a..a9136f3d4 100644 --- a/shared/models/server/index.ts +++ b/shared/models/server/index.ts | |||
@@ -1,14 +1,16 @@ | |||
1 | export * from './about.model' | 1 | export * from './about.model' |
2 | export * from './broadcast-message-level.type' | 2 | export * from './broadcast-message-level.type' |
3 | export * from './client-log-create.model' | ||
4 | export * from './client-log-level.type' | ||
3 | export * from './contact-form.model' | 5 | export * from './contact-form.model' |
4 | export * from './custom-config.model' | 6 | export * from './custom-config.model' |
5 | export * from './debug.model' | 7 | export * from './debug.model' |
6 | export * from './emailer.model' | 8 | export * from './emailer.model' |
7 | export * from './job.model' | 9 | export * from './job.model' |
8 | export * from './log-level.type' | ||
9 | export * from './peertube-problem-document.model' | 10 | export * from './peertube-problem-document.model' |
10 | export * from './server-config.model' | 11 | export * from './server-config.model' |
11 | export * from './server-debug.model' | 12 | export * from './server-debug.model' |
12 | export * from './server-error-code.enum' | 13 | export * from './server-error-code.enum' |
13 | export * from './server-follow-create.model' | 14 | export * from './server-follow-create.model' |
15 | export * from './server-log-level.type' | ||
14 | export * from './server-stats.model' | 16 | export * from './server-stats.model' |
diff --git a/shared/models/server/log-level.type.ts b/shared/models/server/log-level.type.ts deleted file mode 100644 index 4afb92d11..000000000 --- a/shared/models/server/log-level.type.ts +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'audit' | ||
diff --git a/shared/models/server/server-log-level.type.ts b/shared/models/server/server-log-level.type.ts new file mode 100644 index 000000000..f0f31a4ae --- /dev/null +++ b/shared/models/server/server-log-level.type.ts | |||
@@ -0,0 +1 @@ | |||
export type ServerLogLevel = 'debug' | 'info' | 'warn' | 'error' | 'audit' | |||
diff --git a/shared/server-commands/logs/logs-command.ts b/shared/server-commands/logs/logs-command.ts index 8f63383ea..1c5de7f59 100644 --- a/shared/server-commands/logs/logs-command.ts +++ b/shared/server-commands/logs/logs-command.ts | |||
@@ -1,12 +1,25 @@ | |||
1 | import { HttpStatusCode, LogLevel } from '@shared/models' | 1 | import { ClientLogCreate, HttpStatusCode, ServerLogLevel } from '@shared/models' |
2 | import { AbstractCommand, OverrideCommandOptions } from '../shared' | 2 | import { AbstractCommand, OverrideCommandOptions } from '../shared' |
3 | 3 | ||
4 | export class LogsCommand extends AbstractCommand { | 4 | export class LogsCommand extends AbstractCommand { |
5 | 5 | ||
6 | createLogClient (options: OverrideCommandOptions & { payload: ClientLogCreate }) { | ||
7 | const path = '/api/v1/server/logs/client' | ||
8 | |||
9 | return this.postBodyRequest({ | ||
10 | ...options, | ||
11 | |||
12 | path, | ||
13 | fields: options.payload, | ||
14 | implicitToken: true, | ||
15 | defaultExpectedStatus: HttpStatusCode.NO_CONTENT_204 | ||
16 | }) | ||
17 | } | ||
18 | |||
6 | getLogs (options: OverrideCommandOptions & { | 19 | getLogs (options: OverrideCommandOptions & { |
7 | startDate: Date | 20 | startDate: Date |
8 | endDate?: Date | 21 | endDate?: Date |
9 | level?: LogLevel | 22 | level?: ServerLogLevel |
10 | tagsOneOf?: string[] | 23 | tagsOneOf?: string[] |
11 | }) { | 24 | }) { |
12 | const { startDate, endDate, tagsOneOf, level } = options | 25 | const { startDate, endDate, tagsOneOf, level } = options |
diff --git a/support/doc/api/openapi.yaml b/support/doc/api/openapi.yaml index 93c545e36..9745f68e9 100644 --- a/support/doc/api/openapi.yaml +++ b/support/doc/api/openapi.yaml | |||
@@ -330,26 +330,21 @@ x-tagGroups: | |||
330 | - name: Search | 330 | - name: Search |
331 | tags: | 331 | tags: |
332 | - Search | 332 | - Search |
333 | - name: Custom pages | ||
334 | tags: | ||
335 | - Homepage | ||
336 | - name: Moderation | 333 | - name: Moderation |
337 | tags: | 334 | tags: |
338 | - Abuses | 335 | - Abuses |
339 | - Video Blocks | 336 | - Video Blocks |
340 | - Account Blocks | 337 | - Account Blocks |
341 | - Server Blocks | 338 | - Server Blocks |
342 | - name: Instance Configuration | 339 | - name: Instance |
343 | tags: | 340 | tags: |
344 | - Config | 341 | - Config |
342 | - Homepage | ||
345 | - Instance Follows | 343 | - Instance Follows |
346 | - Instance Redundancy | 344 | - Instance Redundancy |
347 | - Plugins | 345 | - Plugins |
348 | - name: Stats | ||
349 | tags: | ||
350 | - Stats | 346 | - Stats |
351 | - name: Jobs | 347 | - Logs |
352 | tags: | ||
353 | - Job | 348 | - Job |
354 | paths: | 349 | paths: |
355 | '/accounts/{name}': | 350 | '/accounts/{name}': |
@@ -4316,6 +4311,58 @@ paths: | |||
4316 | schema: | 4311 | schema: |
4317 | $ref: '#/components/schemas/ServerStats' | 4312 | $ref: '#/components/schemas/ServerStats' |
4318 | 4313 | ||
4314 | /server/logs/client: | ||
4315 | post: | ||
4316 | tags: | ||
4317 | - Logs | ||
4318 | summary: Send client log | ||
4319 | operationId: sendClientLog | ||
4320 | requestBody: | ||
4321 | content: | ||
4322 | application/json: | ||
4323 | schema: | ||
4324 | $ref: '#/components/schemas/SendClientLog' | ||
4325 | responses: | ||
4326 | '204': | ||
4327 | description: successful operation | ||
4328 | |||
4329 | /server/logs: | ||
4330 | get: | ||
4331 | tags: | ||
4332 | - Logs | ||
4333 | summary: Get instance logs | ||
4334 | operationId: getInstanceLogs | ||
4335 | security: | ||
4336 | - OAuth2: | ||
4337 | - admin | ||
4338 | responses: | ||
4339 | '200': | ||
4340 | description: successful operation | ||
4341 | content: | ||
4342 | application/json: | ||
4343 | schema: | ||
4344 | type: array | ||
4345 | items: | ||
4346 | type: string | ||
4347 | |||
4348 | /server/audit-logs: | ||
4349 | get: | ||
4350 | tags: | ||
4351 | - Logs | ||
4352 | summary: Get instance audit logs | ||
4353 | operationId: getInstanceAuditLogs | ||
4354 | security: | ||
4355 | - OAuth2: | ||
4356 | - admin | ||
4357 | responses: | ||
4358 | '200': | ||
4359 | description: successful operation | ||
4360 | content: | ||
4361 | application/json: | ||
4362 | schema: | ||
4363 | type: array | ||
4364 | items: | ||
4365 | type: string | ||
4319 | 4366 | ||
4320 | '/feeds/video-comments.{format}': | 4367 | '/feeds/video-comments.{format}': |
4321 | get: | 4368 | get: |
@@ -6526,6 +6573,31 @@ components: | |||
6526 | enabled: | 6573 | enabled: |
6527 | type: boolean | 6574 | type: boolean |
6528 | 6575 | ||
6576 | SendClientLog: | ||
6577 | properties: | ||
6578 | message: | ||
6579 | type: string | ||
6580 | url: | ||
6581 | type: string | ||
6582 | description: URL of the current user page | ||
6583 | level: | ||
6584 | enum: | ||
6585 | - error | ||
6586 | - warn | ||
6587 | stackTrace: | ||
6588 | type: string | ||
6589 | description: Stack trace of the error if there is one | ||
6590 | userAgent: | ||
6591 | type: string | ||
6592 | description: User agent of the web browser that sends the message | ||
6593 | meta: | ||
6594 | type: string | ||
6595 | description: Additional information regarding this log | ||
6596 | required: | ||
6597 | - message | ||
6598 | - url | ||
6599 | - level | ||
6600 | |||
6529 | ServerStats: | 6601 | ServerStats: |
6530 | properties: | 6602 | properties: |
6531 | totalUsers: | 6603 | totalUsers: |