chore!: remove stdout logging functionality (#37114)

Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
pull/35380/merge
Júlia Jaeger Foresti 3 months ago committed by Guilherme Gazzo
parent bd5edfc299
commit ec0f8b435d
  1. 8
      .changeset/tough-baboons-wash.md
  2. 10
      apps/meteor/app/api/server/v1/misc.ts
  3. 6
      apps/meteor/client/views/admin/routes.tsx
  4. 2
      apps/meteor/client/views/admin/sidebarItems.ts
  5. 223
      apps/meteor/client/views/admin/viewLogs/ServerLogs.tsx
  6. 20
      apps/meteor/client/views/admin/viewLogs/ViewLogsPage.tsx
  7. 8
      apps/meteor/server/configuration/configureLogLevel.ts
  8. 11
      apps/meteor/server/modules/notifications/notifications.module.ts
  9. 3
      apps/meteor/server/settings/logs.ts
  10. 1
      apps/meteor/server/startup/migrations/index.ts
  11. 11
      apps/meteor/server/startup/migrations/v324.ts
  12. 68
      apps/meteor/server/stream/stdout.ts
  13. 2
      apps/meteor/tests/e2e/page-objects/admin.ts
  14. 177
      apps/meteor/tests/end-to-end/api/miscellaneous.ts
  15. 2
      packages/ddp-client/src/types/streams.ts
  16. 1
      packages/i18n/src/locales/af.i18n.json
  17. 1
      packages/i18n/src/locales/ar.i18n.json
  18. 1
      packages/i18n/src/locales/az.i18n.json
  19. 1
      packages/i18n/src/locales/be-BY.i18n.json
  20. 1
      packages/i18n/src/locales/bg.i18n.json
  21. 1
      packages/i18n/src/locales/bs.i18n.json
  22. 1
      packages/i18n/src/locales/ca.i18n.json
  23. 1
      packages/i18n/src/locales/cs.i18n.json
  24. 1
      packages/i18n/src/locales/cy.i18n.json
  25. 1
      packages/i18n/src/locales/da.i18n.json
  26. 1
      packages/i18n/src/locales/de-AT.i18n.json
  27. 1
      packages/i18n/src/locales/de-IN.i18n.json
  28. 1
      packages/i18n/src/locales/de.i18n.json
  29. 1
      packages/i18n/src/locales/el.i18n.json
  30. 1
      packages/i18n/src/locales/en.i18n.json
  31. 1
      packages/i18n/src/locales/eo.i18n.json
  32. 1
      packages/i18n/src/locales/es.i18n.json
  33. 1
      packages/i18n/src/locales/fa.i18n.json
  34. 1
      packages/i18n/src/locales/fi.i18n.json
  35. 1
      packages/i18n/src/locales/fr.i18n.json
  36. 1
      packages/i18n/src/locales/he.i18n.json
  37. 1
      packages/i18n/src/locales/hi-IN.i18n.json
  38. 1
      packages/i18n/src/locales/hr.i18n.json
  39. 1
      packages/i18n/src/locales/hu.i18n.json
  40. 1
      packages/i18n/src/locales/id.i18n.json
  41. 1
      packages/i18n/src/locales/it.i18n.json
  42. 1
      packages/i18n/src/locales/ja.i18n.json
  43. 1
      packages/i18n/src/locales/ka-GE.i18n.json
  44. 1
      packages/i18n/src/locales/km.i18n.json
  45. 1
      packages/i18n/src/locales/ko.i18n.json
  46. 1
      packages/i18n/src/locales/ku.i18n.json
  47. 1
      packages/i18n/src/locales/lo.i18n.json
  48. 1
      packages/i18n/src/locales/lt.i18n.json
  49. 1
      packages/i18n/src/locales/lv.i18n.json
  50. 1
      packages/i18n/src/locales/mn.i18n.json
  51. 1
      packages/i18n/src/locales/ms-MY.i18n.json
  52. 1
      packages/i18n/src/locales/nb.i18n.json
  53. 1
      packages/i18n/src/locales/nl.i18n.json
  54. 1
      packages/i18n/src/locales/nn.i18n.json
  55. 1
      packages/i18n/src/locales/pl.i18n.json
  56. 1
      packages/i18n/src/locales/pt-BR.i18n.json
  57. 1
      packages/i18n/src/locales/pt.i18n.json
  58. 1
      packages/i18n/src/locales/ro.i18n.json
  59. 1
      packages/i18n/src/locales/ru.i18n.json
  60. 1
      packages/i18n/src/locales/sk-SK.i18n.json
  61. 1
      packages/i18n/src/locales/sl-SI.i18n.json
  62. 1
      packages/i18n/src/locales/sq.i18n.json
  63. 1
      packages/i18n/src/locales/sr.i18n.json
  64. 1
      packages/i18n/src/locales/sv.i18n.json
  65. 1
      packages/i18n/src/locales/ta-IN.i18n.json
  66. 1
      packages/i18n/src/locales/th-TH.i18n.json
  67. 1
      packages/i18n/src/locales/tr.i18n.json
  68. 1
      packages/i18n/src/locales/ug.i18n.json
  69. 1
      packages/i18n/src/locales/uk.i18n.json
  70. 1
      packages/i18n/src/locales/vi-VN.i18n.json
  71. 1
      packages/i18n/src/locales/zh-HK.i18n.json
  72. 1
      packages/i18n/src/locales/zh-TW.i18n.json
  73. 1
      packages/i18n/src/locales/zh.i18n.json
  74. 3
      packages/logger/src/getPino.ts
  75. 1
      packages/logger/src/index.ts
  76. 63
      packages/logger/src/logQueue.ts
  77. 10
      packages/rest-typings/src/v1/misc.ts

@ -0,0 +1,8 @@
---
'@rocket.chat/rest-typings': major
'@rocket.chat/ddp-client': major
'@rocket.chat/logger': major
'@rocket.chat/meteor': major
---
Removes stdout logging functionality, related components and settings

@ -23,7 +23,6 @@ import { SystemLogger } from '../../../../server/lib/logger/system';
import { browseChannelsMethod } from '../../../../server/methods/browseChannels';
import { spotlightMethod } from '../../../../server/publications/spotlight';
import { resetAuditedSettingByUser, updateAuditedByUser } from '../../../../server/settings/lib/auditedSettingUpdates';
import { getLogs } from '../../../../server/stream/stdout';
import { passwordPolicy } from '../../../lib/server';
import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener';
import { settings } from '../../../settings/server';
@ -437,15 +436,6 @@ API.v1.addRoute(
* schema:
* $ref: '#/components/schemas/ApiFailureV1'
*/
API.v1.addRoute(
'stdout.queue',
{ authRequired: true, permissionsRequired: ['view-logs'] },
{
async get() {
return API.v1.success({ queue: getLogs() });
},
},
);
declare module '@rocket.chat/rest-typings' {
// eslint-disable-next-line @typescript-eslint/naming-convention

@ -69,8 +69,8 @@ declare module '@rocket.chat/ui-contexts' {
pattern: '/admin/invites';
};
'admin-view-logs': {
pathname: '/admin/reports';
pattern: '/admin/reports';
pathname: '/admin/analytic-reports';
pattern: '/admin/analytic-reports';
};
'admin-permissions': {
pathname: `/admin/permissions${`/${string}` | ''}${`/${string}` | ''}`;
@ -197,7 +197,7 @@ registerAdminRoute('/invites', {
component: lazy(() => import('./invites/InvitesRoute')),
});
registerAdminRoute('/reports', {
registerAdminRoute('/analytic-reports', {
name: 'admin-view-logs',
component: lazy(() => import('./viewLogs/ViewLogsRoute')),
});

@ -114,7 +114,7 @@ export const {
permissionGranted: (): boolean => hasPermission('run-import'),
},
{
href: '/admin/reports',
href: '/admin/analytic-reports',
i18nLabel: 'Reports',
icon: 'post',
permissionGranted: (): boolean => hasPermission('view-logs'),

@ -1,223 +0,0 @@
import type { Serialized } from '@rocket.chat/core-typings';
import { Box, Icon, Scrollable } from '@rocket.chat/fuselage';
import { useToastMessageDispatch, useEndpoint, useStream } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import { useEffect, useRef, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { ansispan } from './ansispan';
type StdOutLogEntry = {
id: string;
string: string;
ts: Date;
};
const compareEntries = (a: StdOutLogEntry, b: StdOutLogEntry): number => a.ts.getTime() - b.ts.getTime();
const unserializeEntry = ({ ts, ...entry }: Serialized<StdOutLogEntry>): StdOutLogEntry => ({
ts: new Date(ts),
...entry,
});
const ServerLogs = (): ReactElement => {
const [entries, setEntries] = useState<StdOutLogEntry[]>([]);
const dispatchToastMessage = useToastMessageDispatch();
const getStdoutQueue = useEndpoint('GET', '/v1/stdout.queue');
const subscribeToStdout = useStream('stdout');
useEffect(() => {
const fetchLines = async (): Promise<void> => {
try {
const { queue } = await getStdoutQueue(undefined);
setEntries(queue.map(unserializeEntry).sort(compareEntries));
} catch (error: unknown) {
dispatchToastMessage({ type: 'error', message: error });
}
};
fetchLines();
}, [dispatchToastMessage, getStdoutQueue]);
useEffect(
() =>
subscribeToStdout('stdout', (entry: StdOutLogEntry) => {
setEntries((entries) => [...entries, entry]);
}),
[subscribeToStdout],
);
const { t } = useTranslation();
const wrapperRef = useRef<HTMLElement>();
const atBottomRef = useRef<boolean>(false);
const [newLogsVisible, setNewLogsVisible] = useState(false);
const isAtBottom = useCallback<(scrollThreshold?: number) => boolean>((scrollThreshold = 0) => {
const wrapper = wrapperRef.current;
if (!wrapper) {
return false;
}
if (wrapper.scrollTop + scrollThreshold >= wrapper.scrollHeight - wrapper.clientHeight) {
setNewLogsVisible(false);
return true;
}
return false;
}, []);
const sendToBottom = useCallback(() => {
const wrapper = wrapperRef.current;
if (!wrapper) {
return;
}
wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight;
setNewLogsVisible(false);
}, []);
const checkIfScrollIsAtBottom = useCallback(() => {
atBottomRef.current = isAtBottom(100);
}, [isAtBottom]);
const sendToBottomIfNecessary = useCallback(() => {
if (atBottomRef.current === true && isAtBottom() !== true) {
sendToBottom();
} else if (atBottomRef.current === false) {
setNewLogsVisible(true);
}
}, [isAtBottom, sendToBottom]);
useEffect(() => {
const wrapper = wrapperRef.current;
if (!wrapper) {
return;
}
if (window.MutationObserver) {
const observer = new MutationObserver((mutations) => {
mutations.forEach(() => {
sendToBottomIfNecessary();
});
});
observer.observe(wrapper, { childList: true });
return (): void => {
observer.disconnect();
};
}
const handleSubtreeModified = (): void => {
sendToBottomIfNecessary();
};
wrapper.addEventListener('DOMSubtreeModified', handleSubtreeModified);
return (): void => {
wrapper.removeEventListener('DOMSubtreeModified', handleSubtreeModified);
};
}, [sendToBottomIfNecessary]);
useEffect(() => {
const handleWindowResize = (): void => {
setTimeout(() => {
sendToBottomIfNecessary();
}, 100);
};
window.addEventListener('resize', handleWindowResize);
return (): void => {
window.removeEventListener('resize', handleWindowResize);
};
}, [sendToBottomIfNecessary]);
const handleWheel = useCallback(() => {
atBottomRef.current = false;
setTimeout(() => {
checkIfScrollIsAtBottom();
}, 100);
}, [checkIfScrollIsAtBottom]);
const handleTouchStart = (): void => {
atBottomRef.current = false;
};
const handleTouchEnd = useCallback(() => {
setTimeout(() => {
checkIfScrollIsAtBottom();
}, 100);
}, [checkIfScrollIsAtBottom]);
const handleScroll = useCallback(() => {
atBottomRef.current = false;
setTimeout(() => {
checkIfScrollIsAtBottom();
}, 100);
}, [checkIfScrollIsAtBottom]);
const handleClick = useCallback(() => {
atBottomRef.current = true;
sendToBottomIfNecessary();
}, [sendToBottomIfNecessary]);
return (
<Box width='full' height='full' overflow='hidden' position='relative' display='flex' mbe={8}>
<Scrollable vertical>
<Box
ref={wrapperRef}
display='flex'
flexDirection='column'
padding={8}
flexGrow={1}
fontFamily='mono'
color='default'
bg='neutral'
style={{ wordBreak: 'break-all' }}
onWheel={handleWheel}
onTouchStart={handleTouchStart}
onTouchEnd={handleTouchEnd}
onScroll={handleScroll}
borderRadius='x4'
>
{entries.sort(compareEntries).map(({ string }, i) => (
<span key={i} dangerouslySetInnerHTML={{ __html: ansispan(string) }} />
))}
</Box>
</Scrollable>
<Box
role='button'
position='absolute'
display='flex'
justifyContent='center'
insetBlockEnd={8}
insetInlineStart='50%'
width='x132'
height='x32'
marginInline='neg-x64'
paddingBlock={8}
fontScale='c2'
borderRadius='full'
elevation='1'
color='default'
bg='light'
onClick={handleClick}
textAlign='center'
style={{
cursor: 'pointer',
transition: 'transform 0.3s ease-out',
transform: newLogsVisible ? 'translateY(0)' : 'translateY(150%)',
}}
>
<Icon name='jump' size='x16' /> {t('New_logs')}
</Box>
</Box>
);
};
export default ServerLogs;

@ -1,30 +1,18 @@
import { Margins, Tabs } from '@rocket.chat/fuselage';
import { Page, PageHeader, PageContent } from '@rocket.chat/ui-client';
import type { ReactElement } from 'react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import AnalyticsReports from './AnalyticsReports';
import ServerLogs from './ServerLogs';
const ViewLogsPage = (): ReactElement => {
const { t } = useTranslation();
const [tab, setTab] = useState('Logs');
return (
<Page background='tint'>
<PageHeader title={t('Reports')} />
<Margins blockEnd={24}>
<Tabs>
<Tabs.Item onClick={() => setTab('Logs')} selected={tab === 'Logs'}>
{t('Logs')}
</Tabs.Item>
<Tabs.Item onClick={() => setTab('Analytics')} selected={tab === 'Analytics'}>
{t('Analytic_reports')}
</Tabs.Item>
</Tabs>
</Margins>
<PageContent>{tab === 'Logs' ? <ServerLogs /> : <AnalyticsReports />}</PageContent>
<PageHeader title={t('Analytic_reports')} />
<PageContent>
<AnalyticsReports />
</PageContent>
</Page>
);
};

@ -1,4 +1,4 @@
import { setQueueLimit, logLevel, type LogLevelSetting } from '@rocket.chat/logger';
import { logLevel, type LogLevelSetting } from '@rocket.chat/logger';
import { Settings } from '@rocket.chat/models';
import type { ICachedSettings } from '../../app/settings/server/CachedSettings';
@ -14,10 +14,4 @@ export async function configureLogLevel(settings: ICachedSettings) {
logLevel.emit('changed', String(value) as LogLevelSetting);
}
});
settings.watch('Log_View_Limit', (value) => {
if (typeof value === 'number') {
setQueueLimit(value);
}
});
}

@ -39,8 +39,6 @@ export class NotificationsModule {
public readonly streamLivechatQueueData: IStreamer<'livechat-inquiry-queue-observer'>;
public readonly streamStdout: IStreamer<'stdout'>;
public readonly streamRoomData: IStreamer<'room-data'>;
public readonly streamLocal: IStreamer<'local'>;
@ -60,7 +58,6 @@ export class NotificationsModule {
this.streamIntegrationHistory = new this.Streamer('integrationHistory');
this.streamLivechatRoom = new this.Streamer('livechat-room');
this.streamLivechatQueueData = new this.Streamer('livechat-inquiry-queue-observer');
this.streamStdout = new this.Streamer('stdout');
this.streamRoomData = new this.Streamer('room-data');
this.streamPresence = StreamPresence.getInstance(Streamer, 'user-presence');
this.streamRoomMessage = new this.Streamer('room-messages');
@ -348,14 +345,6 @@ export class NotificationsModule {
return this.userId ? Authorization.hasPermission(this.userId, 'view-l-room') : false;
});
this.streamStdout.allowWrite('none');
this.streamStdout.allowRead(async function () {
if (!this.userId) {
return false;
}
return Authorization.hasPermission(this.userId, 'view-logs');
});
this.streamRoomData.allowWrite('none');
this.streamRoomData.allowRead(async function (rid) {
if (!this.userId) {

@ -20,9 +20,6 @@ export const createLogSettings = () =>
],
public: true,
});
await this.add('Log_View_Limit', 1000, {
type: 'int',
});
await this.add('Log_Trace_Methods', false, {
type: 'boolean',

@ -28,5 +28,6 @@ import './v319';
import './v320';
import './v321';
import './v322';
import './v324';
export * from './xrun';

@ -0,0 +1,11 @@
import { Settings } from '@rocket.chat/models';
import { addMigration } from '../../lib/migrations';
addMigration({
version: 324,
name: 'Remove Log_View_Limit setting',
async up() {
await Settings.deleteOne({ _id: 'Log_View_Limit' });
},
});

@ -1,68 +0,0 @@
import { performance } from 'perf_hooks';
import { format } from '@rocket.chat/log-format';
import { getQueuedLogs, logEntries } from '@rocket.chat/logger';
import EJSON from 'ejson';
import notifications from '../../app/notifications/server/lib/Notifications';
const processString = (string: string, date: Date): string => {
try {
const obj = EJSON.parse(string);
if (!obj || typeof obj !== 'object') {
throw new TypeError('Invalid JSON');
}
if ('toJSONValue' in obj) {
return format(obj.toJSONValue(), { color: true });
}
if (!Array.isArray(obj) && !(obj instanceof Date) && !(obj instanceof Uint8Array)) {
return format(obj, { color: true });
}
return format(
{
message: string,
time: date,
level: 'info',
},
{ color: true },
);
} catch (e) {
return string;
}
};
const rawTransformLog = (item: any): { id: string; string: string; ts: Date; time?: number } => {
return {
id: item.id,
string: processString(item.data, item.ts),
ts: item.ts,
};
};
const timedTransformLog = (log: any): { id: string; string: string; ts: Date; time?: number } => {
const timeStart = performance.now();
const item = rawTransformLog(log);
const timeEnd = performance.now();
item.time = timeEnd - timeStart;
return item;
};
const transformLog = process.env.STDOUT_METRICS === 'true' ? timedTransformLog : rawTransformLog;
logEntries.on('log', (item) => {
// TODO having this as 'emitWithoutBroadcast' will not sent this data to ddp-streamer, so this data
// won't be available when using micro services.
notifications.streamStdout.emitWithoutBroadcast('stdout', transformLog(item));
});
export function getLogs(): {
id: string;
string: string;
ts: Date;
}[] {
return getQueuedLogs().map(transformLog);
}

@ -19,7 +19,7 @@ export enum AdminSectionsHref {
Third_party_login = '/admin/third-party-login',
Integrations = '/admin/integrations',
Import = '/admin/import',
Reports = '/admin/reports',
Reports = '/admin/analytic-reports',
Sounds = '/admin/sounds',
Emoji = '/admin/emoji',
Settings = '/admin/settings',

@ -5,7 +5,7 @@ import type { IInstance } from '@rocket.chat/rest-typings';
import { AssertionError, expect } from 'chai';
import { after, before, describe, it } from 'mocha';
import { getCredentials, api, request, credentials, methodCall } from '../../data/api-data';
import { getCredentials, api, request, credentials } from '../../data/api-data';
import { updatePermission, updateSetting } from '../../data/permissions.helper';
import { createRoom, deleteRoom } from '../../data/rooms.helper';
import { createTeam, deleteTeam } from '../../data/teams.helper';
@ -686,179 +686,4 @@ describe('miscellaneous', () => {
.end(done);
});
});
describe('[/stdout.queue]', () => {
let testUser: TestUser<IUser>;
let testUsername: string;
let testUserPassword: string;
before(async () => {
testUser = await createUser();
testUsername = testUser.username;
testUserPassword = password;
await updateSetting('Log_Trace_Methods', true);
await updateSetting('Log_Level', '2');
// populate the logs by sending method calls
const populateLogsPromises = [];
populateLogsPromises.push(
request
.post(methodCall('loadHistory'))
.set(credentials)
.set('Cookie', `rc_token=${credentials['X-Auth-Token']}`)
.send({
message: JSON.stringify({
id: 'id',
msg: 'method',
method: 'loadHistory',
params: ['GENERAL'],
}),
}),
);
populateLogsPromises.push(
request
.post(methodCall('private-settings:get'))
.set(credentials)
.send({
message: JSON.stringify({
method: 'private-settings/get',
params: [
{
$date: new Date().getTime(),
},
],
id: 'id',
msg: 'method',
}),
}),
);
populateLogsPromises.push(
request.post(api('login')).send({
user: {
username: testUsername,
},
password: testUserPassword,
}),
);
await Promise.all(populateLogsPromises);
});
after(async () => {
await Promise.all([updateSetting('Log_Trace_Methods', false), updateSetting('Log_Level', '0'), deleteUser(testUser)]);
});
it('if log trace enabled, x-auth-token should be redacted', async () => {
await request
.get(api('stdout.queue'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('queue').that.is.an('array');
const { queue } = res.body;
let foundRedactedToken = false;
for (const log of queue) {
if (log.string.includes("'x-auth-token': '[redacted]'")) {
foundRedactedToken = true;
break;
}
}
expect(foundRedactedToken).to.be.true;
});
});
it('if log trace enabled, rc_token should be redacted', async () => {
await request
.get(api('stdout.queue'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('queue').that.is.an('array');
const { queue } = res.body;
let foundRedactedCookie = false;
for (const log of queue) {
if (log.string.includes('rc_token=[redacted]')) {
foundRedactedCookie = true;
break;
}
}
expect(foundRedactedCookie).to.be.true;
});
});
it('should not return user token anywhere in the log stream', async () => {
await request
.get(api('stdout.queue'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('queue').that.is.an('array');
const { queue } = res.body;
let foundTokenValue = false;
for (const log of queue) {
if (log.string.includes(credentials['X-Auth-Token'])) {
foundTokenValue = true;
break;
}
}
expect(foundTokenValue).to.be.false;
});
});
describe('permissions', () => {
before(async () => {
return updatePermission('view-logs', ['admin']);
});
after(async () => {
return updatePermission('view-logs', ['admin']);
});
it('should return server logs', async () => {
return request
.get(api('stdout.queue'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(200)
.expect((res) => {
expect(res.body).to.have.property('success', true);
expect(res.body).to.have.property('queue').and.to.be.an('array').that.is.not.empty;
expect(res.body.queue[0]).to.be.an('object');
expect(res.body.queue[0]).to.have.property('id').and.to.be.a('string');
expect(res.body.queue[0]).to.have.property('string').and.to.be.a('string');
expect(res.body.queue[0]).to.have.property('ts').and.to.be.a('string');
});
});
it('should not return server logs if user does NOT have the view-logs permission', async () => {
await updatePermission('view-logs', []);
return request
.get(api('stdout.queue'))
.set(credentials)
.expect('Content-Type', 'application/json')
.expect(403)
.expect((res) => {
expect(res.body).to.have.property('success', false);
expect(res.body).to.have.property('error', 'User does not have the permissions required for this action [error-unauthorized]');
});
});
});
});
});

@ -261,8 +261,6 @@ export interface StreamerEvents {
{ key: 'omnichannel.priority-changed'; args: [{ id: string; clientAction: ClientAction; name?: string }] },
];
'stdout': [{ key: 'stdout'; args: [{ id: string; string: string; ts: Date }] }];
'room-data': [{ key: string; args: [IOmnichannelRoom | Pick<IOmnichannelRoom, '_id'>] }];
'notify-room-users': [

@ -1358,7 +1358,6 @@
"Log_Trace_Subscriptions": "Spoor inskrywing oproepe",
"Log_Trace_Subscriptions_Filter": "Trace intekening filter",
"Log_Trace_Subscriptions_Filter_Description": "Die teks hier sal geëvalueer word as RegExp (`nuwe RegExp ('text')`). Hou dit leeg om spoor van elke oproep te wys.",
"Log_View_Limit": "Log View Limit",
"Logged_out_of_other_clients_successfully": "Log uit ander kliënte suksesvol",
"Login": "Teken aan",
"Login_with": "Inloggen met%s",

@ -2322,7 +2322,6 @@
"Log_Trace_Subscriptions": "تتبع مكالمات الاشتراك",
"Log_Trace_Subscriptions_Filter": "تتبع عامل تصفية الاشتراك",
"Log_Trace_Subscriptions_Filter_Description": "سيتم تقييم النص هنا على أنه تعبير نمطي (\"تعبير نمطي جديد (\"نص\")\"). احتفظ به فارغًا لإظهار تتبع كل مكالمة.",
"Log_View_Limit": "حد عرض التسجيل",
"Logged_out_of_other_clients_successfully": "تم تسجيل الخروج من الأجهزة الأخرى بنجاح",
"Login": "تسجيل الدخول",
"Login_Attempts": "محاولات تسجيل الدخول الفاشلة",

@ -1358,7 +1358,6 @@
"Log_Trace_Subscriptions": "Abunə zənglərini izləyin",
"Log_Trace_Subscriptions_Filter": "Abunəliyin filtresini izləyin",
"Log_Trace_Subscriptions_Filter_Description": "Buradaki mətn, RegExp (`yeni RegExp ('text')`) kimi qiymətləndirilir. Hər bir çağırış izini göstərmək üçün boş saxlayın.",
"Log_View_Limit": "Gündəlik Görünüş Limiti",
"Logged_out_of_other_clients_successfully": "Başqa müştərilərdən müvəffəqiyyətlə həyata keçirilir",
"Login": "Daxil ol",
"Login_with": "%s ilə daxil olun",

@ -1376,7 +1376,6 @@
"Log_Trace_Subscriptions": "падпіска трасіроўкі выклікаў",
"Log_Trace_Subscriptions_Filter": "падпіска на фільтр трасіроўкі",
"Log_Trace_Subscriptions_Filter_Description": "Тэкст тут будзе ацэньвацца як RegExp ( `новы RegExp (« тэкст »)`). Трымаеце яго пустым, каб паказаць след кожнага выкліку.",
"Log_View_Limit": "Прагляд часопіса Limit",
"Logged_out_of_other_clients_successfully": "Запісаны з іншых кліентаў паспяхова",
"Login": "Увайсці",
"Login_with": "Увайсці% з",

@ -1355,7 +1355,6 @@
"Log_Trace_Subscriptions": "Проследяване на абонаментните обаждания",
"Log_Trace_Subscriptions_Filter": "Филтър за абонамент за проследяване",
"Log_Trace_Subscriptions_Filter_Description": "Текстът тук ще бъде оценен като RegExp (\"new RegExp ('text')`). Задръжте го празен, за да покажете следа от всяко обаждане.",
"Log_View_Limit": "Грешка при показването на дневника",
"Logged_out_of_other_clients_successfully": "Излезли успешно от други клиенти",
"Login": "Влез",
"Login_with": "Влез с%s",

@ -1353,7 +1353,6 @@
"Log_Trace_Subscriptions": "Tra¾i pretplatne pozive",
"Log_Trace_Subscriptions_Filter": "Filtar za pretplatu u tragovima",
"Log_Trace_Subscriptions_Filter_Description": "Tekst ovdje će biti ocijenjen kao RegExp (`new RegExp ('tekst')`). Zadržite je prazno da biste vidjeli trag svakog poziva.",
"Log_View_Limit": "Ograniči prikaza zabilješki",
"Logged_out_of_other_clients_successfully": "Odjava iz drugih klijenata je uspješna",
"Login": "Prijava",
"Login_with": "Prijavi se sa %s",

@ -2295,7 +2295,6 @@
"Log_Trace_Subscriptions": "Seguiment de trucades de subscripció",
"Log_Trace_Subscriptions_Filter": "Filtre de subscripció de seguiment",
"Log_Trace_Subscriptions_Filter_Description": "El text aquí s'avaluarà com RegExp ( `new RegExp ( 'text')`). Manteniu-buit per mostrar el rastre de cada trucada.",
"Log_View_Limit": "Límit de vista del registre",
"Logged_out_of_other_clients_successfully": "S'han tancat les sessions des d'altres clients correctament",
"Login": "Inicia sessió",
"Login_Attempts": "Intents d’inici de sessió fallits",

@ -1946,7 +1946,6 @@
"Log_Trace_Subscriptions": "Filtr logu přihlášení",
"Log_Trace_Subscriptions_Filter": "Filtr logu přihlášení",
"Log_Trace_Subscriptions_Filter_Description": "Text zde bude vyhodnocen jako RegExp (`new RegExp ('text')`). Nechte ji prázdnou, aby se zobrazil záznam každého volání.",
"Log_View_Limit": "Limit zobrazení logu",
"Logged_out_of_other_clients_successfully": "Odhlášení z ostatních klientů úspěšné",
"Login": "Přihlásit se",
"Login_Attempts": "Neúspěšné pokusy přihlášení",

@ -1353,7 +1353,6 @@
"Log_Trace_Subscriptions": "Galwadau tanysgrifio olrhain",
"Log_Trace_Subscriptions_Filter": "Dilynwch hidlo tanysgrifio",
"Log_Trace_Subscriptions_Filter_Description": "Bydd y testun yma yn cael ei werthuso fel RegExp (`RegExp newydd ('testun')`). Cadwch yn wag i ddangos olrhain pob galwad.",
"Log_View_Limit": "Cyfyngiad Gweld Log",
"Logged_out_of_other_clients_successfully": "Wedi'i gyrraedd allan o gleientiaid eraill yn llwyddiannus",
"Login": "Mewngofnodi",
"Login_with": "Mewngofnodi gyda %s",

@ -2026,7 +2026,6 @@
"Log_Trace_Subscriptions": "Spor abonnements-opkald",
"Log_Trace_Subscriptions_Filter": "Spor abonnementsfilter",
"Log_Trace_Subscriptions_Filter_Description": "Teksten her vil blive vurderet som RegExp ('New RegExp ('text')'). Lad det være tomt for at vise trace fra hvert opkald.",
"Log_View_Limit": "Log View Limit",
"Logged_out_of_other_clients_successfully": "Logget ud af andre klienter med succes",
"Login": "Login",
"Login_Attempts": "Mislykkede loginforsøg",

@ -1359,7 +1359,6 @@
"Log_Trace_Subscriptions": "Abonnement-Anrufe verfolgen",
"Log_Trace_Subscriptions_Filter": "Trace-Abonnementfilter",
"Log_Trace_Subscriptions_Filter_Description": "Der Text hier wird als RegExp (`new RegExp ('text') ') ausgewertet. Lassen Sie es leer, um die Spur jedes Anrufs anzuzeigen.",
"Log_View_Limit": "Begrenzung der Logansicht",
"Logged_out_of_other_clients_successfully": "Sie wurden erfolgreich von anderen Geräten abgemeldet.",
"Login": "Anmelden",
"Login_with": "Anmelden mit %s",

@ -1560,7 +1560,6 @@
"Log_Trace_Subscriptions": "Abonnement-Anrufe verfolgen",
"Log_Trace_Subscriptions_Filter": "Trace-Abonnementfilter",
"Log_Trace_Subscriptions_Filter_Description": "Der Text hier wird als RegExp (`new RegExp ('text') ') ausgewertet. Lass es leer, um eine Trace jedes Anrufs anzuzeigen.",
"Log_View_Limit": "Begrenzung der Log-Ansicht",
"Logged_out_of_other_clients_successfully": "Du wurdest von allen anderen Geräten abgemeldet",
"Login": "Anmelden",
"Login_with": "Anmelden mit %s",

@ -2561,7 +2561,6 @@
"Log_Trace_Subscriptions": "Abonnement-Anrufe verfolgen",
"Log_Trace_Subscriptions_Filter": "Trace-Abonnementfilter",
"Log_Trace_Subscriptions_Filter_Description": "Der Text hier wird als RegExp (`new RegExp ('text') ') ausgewertet. Lassen Sie es leer, um die Spur jedes Anrufs anzuzeigen.",
"Log_View_Limit": "Begrenzung der Protokollansicht",
"Log_out_devices_remotely": "Geräte aus der Ferne abmelden",
"Logged_In_Via": "Eingeloggt über",
"Logged_Out_Banner_Text": "Ihr Arbeitsbereich-Administrator hat Ihre Sitzung auf diesem Gerät beendet. Bitte melden Sie sich erneut an, um fortzufahren.",

@ -1362,7 +1362,6 @@
"Log_Trace_Subscriptions": "Παρακολούθηση κλήσεων συνδρομής",
"Log_Trace_Subscriptions_Filter": "Φιλτράρισμα συνδρομής παρακολούθησης",
"Log_Trace_Subscriptions_Filter_Description": "Το κείμενο εδώ θα αξιολογηθεί ως RegExp (`νέο RegExp ('κείμενο')`). Κρατήστε το κενό για να εμφανίσετε το ίχνος κάθε κλήσης.",
"Log_View_Limit": "Συνδεθείτε Δείτε Όριο",
"Logged_out_of_other_clients_successfully": "Αποσυνδεθεί από άλλους πελάτες με επιτυχία",
"Login": "Είσοδος",
"Login_with": "Είσοδος με %s",

@ -3263,7 +3263,6 @@
"Log_Trace_Subscriptions": "Trace subscription calls",
"Log_Trace_Subscriptions_Filter": "Trace subscription filter",
"Log_Trace_Subscriptions_Filter_Description": "The text here will be evaluated as RegExp (`new RegExp('text')`). Keep it empty to show trace of every call.",
"Log_View_Limit": "Log View Limit",
"Log_in_to_sync": "Log in to sync",
"Log_out_devices_remotely": "Log out devices remotely",
"Logged_In_Via": "Logged in via",

@ -1356,7 +1356,6 @@
"Log_Trace_Subscriptions": "Atentu abonajn alvokojn",
"Log_Trace_Subscriptions_Filter": "Atentu filtrilon de abono",
"Log_Trace_Subscriptions_Filter_Description": "Ĉi tie la teksto estos taksita kiel RegExp ('nova RegExp (' teksto ')'). Konservu ĝin malplena por montri spuron de ĉiu alvoko.",
"Log_View_Limit": "Ŝargu Vida limigo",
"Logged_out_of_other_clients_successfully": "Elŝaltita de aliaj klientoj sukcese",
"Login": "Ensaluti",
"Login_with": "Ensalutu per%s",

@ -2352,7 +2352,6 @@
"Log_Trace_Subscriptions": "Seguimiento de llamadas de suscripción",
"Log_Trace_Subscriptions_Filter": "Seguimiento de filtro de suscripción",
"Log_Trace_Subscriptions_Filter_Description": "El texto de aquí se evaluará como regex (\"new RegExp('text')\"). Dejar vacío para mostrar el rastro de cada llamada.",
"Log_View_Limit": "Límite de vista de registro",
"Logged_out_of_other_clients_successfully": "Sesiones de otros clientes cerradas correctamente",
"Login": "Iniciar sesión",
"Login_Attempts": "Intentos fallidos de inicio de sesión",

@ -1602,7 +1602,6 @@
"Log_Trace_Subscriptions": "ردیابی تماس های اشتراک",
"Log_Trace_Subscriptions_Filter": "ردیابی فیلتر اشتراک",
"Log_Trace_Subscriptions_Filter_Description": "متن در اینجا به عنوان RegExp (`RegExp جدید ('متن')`) ارزیابی می شود. آن را خالی نگه دارید تا ردیابی هر تماس را نشان دهد.",
"Log_View_Limit": "ورود مشخصات محدود",
"Logged_out_of_other_clients_successfully": "از نشست های دیگر با موفقیت خارج شد",
"Login": "ورود",
"Login_with": "ورود با %s",

@ -2627,7 +2627,6 @@
"Log_Trace_Subscriptions": "Jäljitä tilauskutsuja",
"Log_Trace_Subscriptions_Filter": "Jäljitä tilauksen suodatin",
"Log_Trace_Subscriptions_Filter_Description": "Tässä oleva teksti arvioidaan RegExp:nä (`new RegExp('text')`). Jättämällä sen tyhjäksi voit näyttää joka kutsun jäljityksen.",
"Log_View_Limit": "Lokinäkymän raja",
"Log_out_devices_remotely": "Etäkirjaudu ulos laitteista",
"Logged_In_Via": "Kirjautumistapa",
"Logged_Out_Banner_Text": "Työtilan ylläpitäjä lopetti istuntosi tässä laitteessa. Jatka kirjautumalla sisään uudelleen.",

@ -2317,7 +2317,6 @@
"Log_Trace_Subscriptions": "Tracer les appels d'abonnement",
"Log_Trace_Subscriptions_Filter": "Tracer le filtre d'abonnement",
"Log_Trace_Subscriptions_Filter_Description": "Ce texte sera évalué comme expression régulière (`new RegExp ('text')`). Laissez le champ vide pour afficher la trace de chaque appel.",
"Log_View_Limit": "Limite d'affichage du journal",
"Logged_out_of_other_clients_successfully": "Déconnexion des autres clients réussie",
"Login": "Connexion",
"Login_Attempts": "Échecs de tentatives de connexion",

@ -700,7 +700,6 @@
"Log_File": "צג קבצי קו",
"Log_Level": "רמה התחבר",
"Log_Package": "חבילת הצג",
"Log_View_Limit": "הגבלת צפיה בלוג",
"Logged_out_of_other_clients_successfully": "הביקור האחרון מתוך לקוחות אחרים בהצלחה",
"Login": "התחברות",
"Login_with": "כניסה עם %s",

@ -2736,7 +2736,6 @@
"Log_Trace_Subscriptions": "सदसयतल टस कर",
"Log_Trace_Subscriptions_Filter": "सदसयतिटर टस कर",
"Log_Trace_Subscriptions_Filter_Description": "यहट ककन रगएकसप (`नयगएकसप('टट')`) कप मिएग। परतक कल कस दििए इस रख।",
"Log_View_Limit": "लग दय स",
"Log_in_to_sync": "सिक करनिए लग इन कर",
"Log_out_devices_remotely": "डिइसरसथ रप सग आउट कर",
"Logged_In_Via": "कयम सग इन कि गय",

@ -1473,7 +1473,6 @@
"Log_Trace_Subscriptions": "Tra¾i pretplatne pozive",
"Log_Trace_Subscriptions_Filter": "Filtar za pretplatu u tragovima",
"Log_Trace_Subscriptions_Filter_Description": "Tekst ovdje će biti ocijenjen kao RegExp (`new RegExp ('tekst')`). Zadržite je prazno da biste vidjeli trag svakog poziva.",
"Log_View_Limit": "Ograniči prikaza zabilješki",
"Logged_out_of_other_clients_successfully": "Odjava iz drugih klijenata je uspješna",
"Login": "Prijava",
"Login_with": "Prijavi se sa %s",

@ -2503,7 +2503,6 @@
"Log_Trace_Subscriptions": "Feliratkozási hívások nyomon követése",
"Log_Trace_Subscriptions_Filter": "Feliratkozás nyomon követésének szűrője",
"Log_Trace_Subscriptions_Filter_Description": "Az itt lévő szöveg reguláris kifejezésként lesz kiértékelve („new RegExp('text')”). Hagyja üresen az összes hívás nyomon követésének megjelenítéséhez.",
"Log_View_Limit": "Naplónézet korlátja",
"Log_out_devices_remotely": "Eszközök kijelentkeztetése távolról",
"Logged_In_Via": "Bejelentkezés ezen keresztül:",
"Logged_Out_Banner_Text": "A munkaterület adminisztrátora befejezte a munkamenetet ezen az eszközön. Jelentkezzen be újra a folytatáshoz.",

@ -1356,7 +1356,6 @@
"Log_Trace_Subscriptions": "Lacak panggilan berlangganan",
"Log_Trace_Subscriptions_Filter": "Lacak filter langganan",
"Log_Trace_Subscriptions_Filter_Description": "Teks di sini akan dievaluasi sebagai RegExp (`RegExp baru ('teks')`). Tetap kosong untuk menunjukkan jejak setiap panggilan.",
"Log_View_Limit": "Log View Batas",
"Logged_out_of_other_clients_successfully": "Log out dari klien lain berhasil",
"Login": "Login",
"Login_with": "Login menggunakan %s",

@ -1748,7 +1748,6 @@
"Log_Trace_Subscriptions": "Rintraccia chiamate in abbonamento",
"Log_Trace_Subscriptions_Filter": "Traccia filtro di sottoscrizione",
"Log_Trace_Subscriptions_Filter_Description": "Il testo qui verrà valutato come RegExp (`new RegExp ('text')`). Tienilo vuoto per mostrare la traccia di ogni chiamata.",
"Log_View_Limit": "Limite Visione Registro",
"Logged_out_of_other_clients_successfully": "Scollegato da altre postazioni con successo",
"Login": "Login",
"Login_with": "Accedi con %s",

@ -2297,7 +2297,6 @@
"Log_Trace_Subscriptions": "サブスクリプション呼び出しのトレース",
"Log_Trace_Subscriptions_Filter": "サブスクリプションのトレースフィルター",
"Log_Trace_Subscriptions_Filter_Description": "ここのテキストはRegExp(「new RegExp ( 'text')」)として評価されます。すべての通話のトレースを表示するには、空のままにしておきます。",
"Log_View_Limit": "ログ表示制限",
"Logged_out_of_other_clients_successfully": "他のクライアントを正常にログアウトさせました",
"Login": "ログイン",
"Login_Attempts": "失敗したログイン試行",

@ -1848,7 +1848,6 @@
"Log_Trace_Subscriptions": "გამოწერის მოთხოვნების მოძიება",
"Log_Trace_Subscriptions_Filter": "გამოწერის ფილტრის მოძიება",
"Log_Trace_Subscriptions_Filter_Description": "ამ ველის ტექსტი შეფასდება როგორც RegExp (`new RegExp('text')`). დატოვეთ ცარიელი ყველა ზარის კვალის სანახავად",
"Log_View_Limit": "ლოგის ხედვის ზღვარი",
"Logged_out_of_other_clients_successfully": "სხვა კლიენტებთან წარმატებით გამოვიდა",
"Login": "შესვლა",
"Login_with": "შესვლა%s- ით",

@ -1609,7 +1609,6 @@
"Log_Trace_Subscriptions": "តមដនករហមករជវ",
"Log_Trace_Subscriptions_Filter": "តមដនតមរងជវ",
"Log_Trace_Subscriptions_Filter_Description": "អតថបទនងតវបនវយតម RegExp (`បទថ RegExp ('អតថបទ')`) ។ រកយនទទបងញពនររហ។",
"Log_View_Limit": "ចលមលដនកណត",
"Logged_out_of_other_clients_successfully": "បនចញនអតជនផងទតដយជគជយ",
"Login": "ឡល",
"Login_with": "ឡយ %s",

@ -2006,7 +2006,6 @@
"Log_Trace_Subscriptions": "구독 요청 추적",
"Log_Trace_Subscriptions_Filter": "구독 필터 추적",
"Log_Trace_Subscriptions_Filter_Description": "정규식(`new RegExp('text')`)으로 취급됩니다. 모든 요청을 보려면 비워두세요.",
"Log_View_Limit": "표시 제한 로그",
"Logged_out_of_other_clients_successfully": "다른 클라이언트에서 로그아웃 했습니다.",
"Login": "로그인",
"Login_Attempts": "로그인 시도 실패",

@ -1351,7 +1351,6 @@
"Log_Trace_Subscriptions": "Telefonên traceya trace",
"Log_Trace_Subscriptions_Filter": "Parastina fonksiyona trace",
"Log_Trace_Subscriptions_Filter_Description": "Vê nivîsê dê wekî RegExp (`RegExp nû '(' text ')` binirxînin. Vala binivîse ku nîşan bide her telefonê nîşan bide.",
"Log_View_Limit": "Têkeve View Sînora",
"Logged_out_of_other_clients_successfully": "Logged out of din ji mişterî bi serkeftî",
"Login": "چوونەژوور",
"Login_with": "Login bi %s",

@ -1386,7 +1386,6 @@
"Log_Trace_Subscriptions": "ຕດຕາມການໂທຈອງ",
"Log_Trace_Subscriptions_Filter": "ຕດຕາມກວດສອບການກນຕອງ",
"Log_Trace_Subscriptions_Filter_Description": "ຂຄວາມທຈະຖກປະເມນເປນ RegExp (`ໃຫມ RegExp ('ຂຄວາມ')`). ໃຫນຫວາງເພອສະແດງໃຫເຫນການຕດຕາມຂອງທກໆສາຍ.",
"Log_View_Limit": "ເຂາສລະບບເບງຈາກດ",
"Logged_out_of_other_clients_successfully": "ອອກຈາກລະບບຂອງລກຄາອນໆຢາງສາເລດຜນ",
"Login": "ເຂລະບ",
"Login_with": "ເຂາສລະບບ %s",

@ -1406,7 +1406,6 @@
"Log_Trace_Subscriptions": "Trace prenumeratos skambučiai",
"Log_Trace_Subscriptions_Filter": "Trace prenumeratos filtras",
"Log_Trace_Subscriptions_Filter_Description": "Čia tekstas bus vertinamas kaip RegExp (\"naujas RegExp ('tekstas')\"). Laikykite tuščią, kad parodytumėte kiekvieno skambučio pėdsakus.",
"Log_View_Limit": "Log View Limit",
"Logged_out_of_other_clients_successfully": "Sėkmingai atsijungė iš kitų klientų",
"Login": "Prisijungti",
"Login_with": "Prisijunkite naudodami%s",

@ -1372,7 +1372,6 @@
"Log_Trace_Subscriptions": "Izsekot abonētos zvanus",
"Log_Trace_Subscriptions_Filter": "Izsekot abonentus filtrs",
"Log_Trace_Subscriptions_Filter_Description": "Šeit teksts tiks vērtēts kā RegExp (`new RegExp ('text')`). Saglabājiet to tukšu, lai parādītu katra zvana pēdas.",
"Log_View_Limit": "Reģistrēt skatījumu limitu",
"Logged_out_of_other_clients_successfully": "Sekmīgi izrakstījās no citiem klientiem",
"Login": "Pieteikties",
"Login_with": "Pieteikties ar %s",

@ -1356,7 +1356,6 @@
"Log_Trace_Subscriptions": "Захиалгын дуудлагыг дагана",
"Log_Trace_Subscriptions_Filter": "Захиалга оруулах шүүлтүүр",
"Log_Trace_Subscriptions_Filter_Description": "Энд байгаа текстийг RegExp (`new RegExp ('text')`) гэж үнэлнэ. Дуудлага бүрийн ул мөрийг харуулахын тулд хоосон байлга.",
"Log_View_Limit": "Хязгаарын Лог харах",
"Logged_out_of_other_clients_successfully": "Бусад үйлчлүүлэгчид амжилттай ажиллуулав",
"Login": "Нэвтрэх",
"Login_with": "%s-тай нэвтрэх",

@ -1359,7 +1359,6 @@
"Log_Trace_Subscriptions": "Jejaki panggilan langganan",
"Log_Trace_Subscriptions_Filter": "Salurkan penapis langganan",
"Log_Trace_Subscriptions_Filter_Description": "Teks di sini akan dinilai sebagai RegExp (`baru RegExp ('text')`). Pastikan ia kosong untuk menunjukkan jejak setiap panggilan.",
"Log_View_Limit": "Log Lihat Had",
"Logged_out_of_other_clients_successfully": "Log keluar daripada pelanggan lain berjaya",
"Login": "Log masuk",
"Login_with": "Log masuk dengan %s",

@ -3145,7 +3145,6 @@
"Log_Trace_Subscriptions": "Spor abonnementssamtaler",
"Log_Trace_Subscriptions_Filter": "Spor abonnementsfilter",
"Log_Trace_Subscriptions_Filter_Description": "Teksten her vil bli evaluert som RegExp (`new RegExp('text')`). La den være tom for å vise spor etter hvert anrop.",
"Log_View_Limit": "Loggvisningsgrense",
"Log_in_to_sync": "Logg på for å synkronisere",
"Log_out_devices_remotely": "Logg ut enheter eksternt",
"Logged_In_Via": "Logget inn via",

@ -2313,7 +2313,6 @@
"Log_Trace_Subscriptions": "Abonnementsgesprekken traceren",
"Log_Trace_Subscriptions_Filter": "Traceer abonnementsfilter",
"Log_Trace_Subscriptions_Filter_Description": "De tekst hier wordt geëvalueerd als RegExp (`new RegExp ('text)`). Houd het leeg om het spoor van elk gesprek te tonen.",
"Log_View_Limit": "Limiet logboekweergave",
"Logged_out_of_other_clients_successfully": "Met succes afgemeld bij andere clients",
"Login": "Log in",
"Login_Attempts": "Mislukte aanmeldingspogingen",

@ -3039,7 +3039,6 @@
"Log_Trace_Subscriptions": "Spor abonnementssamtaler",
"Log_Trace_Subscriptions_Filter": "Spor abonnement filter",
"Log_Trace_Subscriptions_Filter_Description": "Teksten her vil bli vurdert som RegExp (`ny RegExp ('text')`). Hold det tomt for å vise spor av hver samtale.",
"Log_View_Limit": "Logggrense",
"Log_in_to_sync": "Logg på for å synkronisere",
"Log_out_devices_remotely": "Logg ut enheter eksternt",
"Logged_In_Via": "Logget inn via",

@ -2516,7 +2516,6 @@
"Log_Trace_Subscriptions": "Śledź połączenia subskrypcji",
"Log_Trace_Subscriptions_Filter": "Śledź filtr subskrypcji",
"Log_Trace_Subscriptions_Filter_Description": "Tekst tutaj zostanie oceniony jako RegExp (`new RegExp ('text')`). Pozostaw to puste, aby pokazać ślad każdego połączenia.",
"Log_View_Limit": "Limit przeglądania logów",
"Log_out_devices_remotely": "Zdalne wylogowanie urządzeń",
"Logged_In_Via": "Zalogowano się za pośrednictwem",
"Logged_Out_Banner_Text": "Twój administrator przestrzeni roboczej zakończył sesję na tym urządzeniu. Zaloguj się ponownie, aby kontynuować.",

@ -3083,7 +3083,6 @@
"Log_Trace_Subscriptions": "Chamadas de assinatura de rastreamento",
"Log_Trace_Subscriptions_Filter": "Filtro de assinatura de rastreamento",
"Log_Trace_Subscriptions_Filter_Description": "O texto aqui será avaliado como RegExp (`novo RegExp ('text')`). Mantenha-o vazio para mostrar o rastreamento de todas as chamadas.",
"Log_View_Limit": "Limite de visualização de registro",
"Log_in_to_sync": "Faça login para sincronizar",
"Log_out_devices_remotely": "Logout de dispositivos remotamente",
"Logged_In_Via": "Conectado via",

@ -1597,7 +1597,6 @@
"Log_Trace_Subscriptions": "Chamadas de assinatura de pesquisa",
"Log_Trace_Subscriptions_Filter": "Filtro de assinatura de pesquisa",
"Log_Trace_Subscriptions_Filter_Description": "O texto aqui será avaliado como RegExp (`new RegExp ('text')`). Mantenha-o vazio para mostrar a pesquisa de todas as chamadas.",
"Log_View_Limit": "Limite de Visualização de Log",
"Logged_out_of_other_clients_successfully": "Desconectado de outros clientes com sucesso",
"Login": "Entrar",
"Login_with": "Entrar com %s",

@ -1357,7 +1357,6 @@
"Log_Trace_Subscriptions": "Urmăriți apelurile de abonament",
"Log_Trace_Subscriptions_Filter": "Trace filtrul de abonament",
"Log_Trace_Subscriptions_Filter_Description": "Textul de aici va fi evaluat ca RegExp (`nou RegExp ('text')`). Păstrați-o goală pentru a afișa urmele fiecărui apel.",
"Log_View_Limit": "Limită vizualizare log-uri",
"Logged_out_of_other_clients_successfully": "Delogat cu succes din alți clienți",
"Login": "Autentificare",
"Login_with": "Autentifică-te cu %s",

@ -2433,7 +2433,6 @@
"Log_Trace_Subscriptions": "Запросы подписки на трассировку",
"Log_Trace_Subscriptions_Filter": "Фильтр подписки на трассировку",
"Log_Trace_Subscriptions_Filter_Description": "Текст здесь будет оцениваться как RegExp (`new RegExp ('text')`). Держите его пустым, чтобы показывать след каждого вызова.",
"Log_View_Limit": "Лимит строк",
"Logged_out_of_other_clients_successfully": "Сеансы в других клиентах успешно завершены",
"Login": "Авторизация",
"Login_Attempts": "Неудачные попытки входа",

@ -1363,7 +1363,6 @@
"Log_Trace_Subscriptions": "Trasové odberové hovory",
"Log_Trace_Subscriptions_Filter": "Trasovací odberový filter",
"Log_Trace_Subscriptions_Filter_Description": "Text tu bude hodnotený ako RegExp (`new RegExp ('text')`). Nechajte ju prázdne, aby ste zobrazili stopu každého hovoru.",
"Log_View_Limit": "Limit zobrazenia denníka",
"Logged_out_of_other_clients_successfully": "Odhlásený z iných klientov úspešne",
"Login": "Prihlásiť sa",
"Login_with": "Prihláste sa s%s",

@ -1353,7 +1353,6 @@
"Log_Trace_Subscriptions": "Klici na naročnino",
"Log_Trace_Subscriptions_Filter": "Trace filter naročnine",
"Log_Trace_Subscriptions_Filter_Description": "Besedilo bo ocenjeno kot RegExp (`novi RegExp ('besedilo')`). Naj bo prazno, da prikaže sled vsakega klica.",
"Log_View_Limit": "Omejitev pogleda dnevnika",
"Logged_out_of_other_clients_successfully": "Uspešno odjavljeni iz drugih naprav",
"Login": "Prijava",
"Login_with": "Prijava z %s",

@ -1357,7 +1357,6 @@
"Log_Trace_Subscriptions": "Thërret thirrjet e abonimit",
"Log_Trace_Subscriptions_Filter": "Trajto filtrin e pajtimit",
"Log_Trace_Subscriptions_Filter_Description": "Teksti këtu do të vlerësohet si RegExp (`new RegExp ('text')`). Mbajeni bosh për të treguar gjurmimin e çdo thirrjeje.",
"Log_View_Limit": "Identifikohu Shiko Limit",
"Logged_out_of_other_clients_successfully": "Identifikuar nga klientë të tjerë me sukses",
"Login": "Hyrje",
"Login_with": "Identifikohuni me %s",

@ -1208,7 +1208,6 @@
"Log_Trace_Subscriptions": "Тражити претплатнички позив",
"Log_Trace_Subscriptions_Filter": "Траце претплатнички филтер",
"Log_Trace_Subscriptions_Filter_Description": "Текст ће бити евалуиран као РегЕкп (`нови РегЕкп ('текст')`). Држите празно да бисте приказали траг сваког позива.",
"Log_View_Limit": "Ограничење приказа записа",
"Logged_out_of_other_clients_successfully": "Пријављени од других клијената успешно",
"Login": "Пријава",
"Login_with": "Пријави се са %s",

@ -3096,7 +3096,6 @@
"Log_Trace_Subscriptions": "Spåra prenumerationssamtal",
"Log_Trace_Subscriptions_Filter": "Spåra abonnemangsfilter",
"Log_Trace_Subscriptions_Filter_Description": "Texten här kommer att utvärderas som RegExp (`ny RegExp ('text')`). Håll det tomt för att visa spår av alla samtal.",
"Log_View_Limit": "Gräns för loggvisning",
"Log_in_to_sync": "Logga in för att synkronisera",
"Log_out_devices_remotely": "Logga ut enheter på distans",
"Logged_In_Via": "Loggade in via",

@ -1357,7 +1357,6 @@
"Log_Trace_Subscriptions": "ட சந அழ",
"Log_Trace_Subscriptions_Filter": "ட சந வடி",
"Log_Trace_Subscriptions_Filter_Description": "இங உர RegExp (`பிய RegExp ('உர')` `என மதிிடபபடிறத. ஒவ அழினதவடகளவதறிக வகவ.",
"Log_View_Limit": "ப வரம உளய",
"Logged_out_of_other_clients_successfully": "விகரமக மறற விளரகளிறபபடகள",
"Login": "உள",
"Login_with": "%s க உள",

@ -1352,7 +1352,6 @@
"Log_Trace_Subscriptions": "ตดตามการสมครรบขอมล",
"Log_Trace_Subscriptions_Filter": "ตดตามตวกรองการสมครรบขอมล",
"Log_Trace_Subscriptions_Filter_Description": "ขอความทจะไดบการประเมนเปน RegExp (`RegExp ใหม ('ขอความ')`) ใหนวางเปลาเพอแสดงรองรอยของทกสาย",
"Log_View_Limit": "ขด จำกด มมมองลอก",
"Logged_out_of_other_clients_successfully": "บนทกการตดตอจากลกคารายอนเรยบรอยแลว",
"Login": "เขาสระบบ",
"Login_with": "เขาสระบบดวย%s",

@ -1627,7 +1627,6 @@
"Log_Trace_Subscriptions": "Abonelik aramalarını izleme",
"Log_Trace_Subscriptions_Filter": "İzleme aboneliği filtresi",
"Log_Trace_Subscriptions_Filter_Description": "Buradaki metin RegExp (`new RegExp ('text')`) olarak değerlendirilecektir. Her aramanın izini göstermek için boş tutun.",
"Log_View_Limit": "Görünüm Sınırı Log",
"Logged_out_of_other_clients_successfully": "başarılı bir şekilde diğer müşterilerin oturumu",
"Login": "Oturum aç",
"Login_with": "%s ile oturum aç",

@ -541,7 +541,6 @@
"Log_File": "ھۆججەت ۋە قۇر سانىنى كۆرسىتىش",
"Log_Level": "كۈندىلىك خاتىرە دەرىجىسى",
"Log_Package": "كۈندىلىك خاتىرە سومكىسىنى كۆرسىتىش",
"Log_View_Limit": "كۈندىلىك خاتىرە ئۈستۈنكى چەكنى كۆرسىتىش",
"Logged_out_of_other_clients_successfully": "باشقا ئۈسكىنىلەردىن ئۇتۇقلۇق چىقىپ كېتىش",
"Login": "كىرىش",
"Login_with": "نى ئىشلىتىپ كىرىش%s",

@ -1770,7 +1770,6 @@
"Log_Trace_Subscriptions": "Дзвінки підписки на трасі",
"Log_Trace_Subscriptions_Filter": "Фільтр підписки на трасі",
"Log_Trace_Subscriptions_Filter_Description": "Текст тут буде оцінюватися як RegExp (`new RegExp ('text')`). Тримайте його порожнім, щоб показати сліду кожного дзвінка.",
"Log_View_Limit": "Log View Limit",
"Logged_out_of_other_clients_successfully": "Записаний з інших клієнтів успішно",
"Login": "Логін",
"Login_with": "Вхід з%s",

@ -1448,7 +1448,6 @@
"Log_Trace_Subscriptions": "Theo dõi cuộc gọi đăng ký",
"Log_Trace_Subscriptions_Filter": "Bộ lọc đăng ký theo dõi",
"Log_Trace_Subscriptions_Filter_Description": "Văn bản ở đây sẽ được đánh giá là RegExp (`new RegExp ('text')`). Giữ trống để hiển thị dấu vết của mọi cuộc gọi.",
"Log_View_Limit": "Log giới hạn view",
"Logged_out_of_other_clients_successfully": "Đăng nhập thành công từ các khách hàng khác",
"Login": "Đăng nhập",
"Login_with": "Đăng nhập với%s",

@ -1375,7 +1375,6 @@
"Log_Trace_Subscriptions": "跟踪订阅通话",
"Log_Trace_Subscriptions_Filter": "跟踪订阅过滤器",
"Log_Trace_Subscriptions_Filter_Description": "这里的文本将被评估为RegExp(`new RegExp('text')`)。保持空白以显示每个呼叫的跟踪。",
"Log_View_Limit": "日志视图限制",
"Logged_out_of_other_clients_successfully": "成功退出其他客户端",
"Login": "登录",
"Login_with": "使用%s登录",

@ -2262,7 +2262,6 @@
"Log_Trace_Subscriptions": "追踪訂閱通話",
"Log_Trace_Subscriptions_Filter": "跟踪訂閱過濾器",
"Log_Trace_Subscriptions_Filter_Description": "這裡的文字將被評估為RegExp(`new RegExp('text')`)。保持空白以顯示每個通話的追踪。",
"Log_View_Limit": "日誌檢視限制",
"Logged_out_of_other_clients_successfully": "登出其他客戶端成功",
"Login": "登入",
"Login_Attempts": "嘗試登入失敗",

@ -2036,7 +2036,6 @@
"Log_Trace_Subscriptions": "跟踪订阅调用",
"Log_Trace_Subscriptions_Filter": "跟踪订阅过滤器",
"Log_Trace_Subscriptions_Filter_Description": "这里的文本将被作为正则表达式求值(`new RegExp('text')`)。保持空白以显示每个调用的跟踪。",
"Log_View_Limit": "日志展示上限",
"Logged_out_of_other_clients_successfully": "登出其它设备成功",
"Login": "登录",
"Login_Attempts": "失败的登录尝试",

@ -1,9 +1,6 @@
import { pino } from 'pino';
import type { Logger } from 'pino';
// make sure log queue is set up, so pino uses the overwritten process.stdout.write
import './logQueue';
// add support to multiple params on the log commands, i.e.:
// logger.info('user', await Meteor.userAsync()); // will print: {"level":30,"time":1629814080968,"msg":"user {\"username\": \"foo\"}"}
function logMethod(this: Logger, args: unknown[], method: any): void {

@ -4,7 +4,6 @@ import { logLevel } from './logLevel';
export * from './getPino';
export * from './logLevel';
export * from './logQueue';
const getLevel = (level: LogLevelSetting): string => {
switch (level) {

@ -1,63 +0,0 @@
import EventEmitter from 'events';
const { MOLECULER_LOG_LEVEL, STDOUT_VIEWER_DISABLED = 'false' } = process.env;
type LogQueue = {
id: string;
data: string;
ts: Date;
};
const queue: LogQueue[] = [];
const maxInt = 2147483647;
let queueLimit = 1000;
let queueSize = 0;
export function setQueueLimit(limit: number): void {
queueLimit = limit;
if (queueSize > queueLimit) {
queue.splice(0, queueSize - queueLimit);
}
}
export function getQueuedLogs(): LogQueue[] {
return queue;
}
export const logEntries = new EventEmitter();
const { write } = process.stdout;
function queueWrite(buffer: Uint8Array | string, cb?: (err?: Error) => void): boolean;
function queueWrite(str: Uint8Array | string, encoding?: string, cb?: (err?: Error) => void): boolean;
function queueWrite(...args: any): boolean {
write.apply(process.stdout, args);
const [str] = args;
if (typeof str !== 'string') {
return true;
}
const date = new Date();
const item = {
id: `logid-${queueSize}`,
data: str,
ts: date,
};
queue.push(item);
queueSize = (queueSize + 1) & maxInt;
if (queueSize > queueLimit) {
queue.shift();
}
logEntries.emit('log', item);
return true;
}
if (String(MOLECULER_LOG_LEVEL).toLowerCase() !== 'debug' && STDOUT_VIEWER_DISABLED === 'false') {
process.stdout.write = queueWrite;
}

@ -181,16 +181,6 @@ const FingerprintSchema = {
export const isFingerprintProps = ajv.compile<Fingerprint>(FingerprintSchema);
export type MiscEndpoints = {
'/v1/stdout.queue': {
GET: () => {
queue: {
id: string;
string: string;
ts: Date;
}[];
};
};
'/v1/shield.svg': {
GET: (params: ShieldSvg) => {
svg: string;

Loading…
Cancel
Save