2 Commits

Author SHA1 Message Date
gorbenko.pavel 4b09833bc4 Пакет @tnsu/monitoring-web 0.3.0 из реестра tansu
Tests / frontend-test (pull_request) Successful in 4m26s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:21:23 +05:00
gorbenko.pavel ee78449131 Мониторинг: логи, ошибки и запись экрана портала заявок в monitoring.tnsu.kz
initMonitoring в onInit веб-части (один раз на страницу), service.name = requestPortal, токен — молча
через AAD веб-части (spfxTokenProvider). В package-solution.json запрос Logs.Write к регистрации
мониторинга. Хэш коммита сборки — патч webpack (config/webpack-patch.json): GIT_COMMIT, GITHUB_SHA или git.
Пакет @tnsu/monitoring-web ставится отдельно.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 16:16:55 +05:00
6 changed files with 145 additions and 3 deletions
+4
View File
@@ -30,6 +30,10 @@
"resource": "9232d9e2-9807-4753-808f-07250e5474b0", "resource": "9232d9e2-9807-4753-808f-07250e5474b0",
"scope": "Reports.Read" "scope": "Reports.Read"
}, },
{
"resource": "9232d9e2-9807-4753-808f-07250e5474b0",
"scope": "Logs.Write"
},
{ {
"resource": "Microsoft Flow Service", "resource": "Microsoft Flow Service",
"scope": "Flows.Read.All" "scope": "Flows.Read.All"
+4
View File
@@ -0,0 +1,4 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/spfx-build/webpack-patch.schema.json",
"patchFiles": ["./config/webpack-patch/monitoring.js"]
}
+20
View File
@@ -0,0 +1,20 @@
// Хэш коммита сборки — в логи (git.commit) и записи экрана мониторинга: @tnsu/monitoring-web читает
// __TNSU_GIT_COMMIT__, а webpack подставляет его при сборке. Хэш — GIT_COMMIT или GITHUB_SHA пайплайна, иначе git.
const { execSync } = require('node:child_process');
const webpack = require('webpack');
function gitCommit() {
const fromEnv = process.env.GIT_COMMIT || process.env.GITHUB_SHA;
if (fromEnv) return fromEnv;
try {
return execSync('git rev-parse HEAD', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim();
} catch {
return '';
}
}
module.exports = function monitoringPatch(config) {
config.plugins = config.plugins || [];
config.plugins.push(new webpack.DefinePlugin({ __TNSU_GIT_COMMIT__: JSON.stringify(gitCommit()) }));
return config;
};
+106 -3
View File
@@ -17,6 +17,7 @@
"@microsoft/sp-webpart-base": "1.22.1", "@microsoft/sp-webpart-base": "1.22.1",
"@pnp/sp": "^4.20.0", "@pnp/sp": "^4.20.0",
"@pnp/spfx-controls-react": "^3.25.0", "@pnp/spfx-controls-react": "^3.25.0",
"@tnsu/monitoring-web": "^0.3.0",
"@tnsu/ui-kit": "^0.15.0", "@tnsu/ui-kit": "^0.15.0",
"jszip": "~3.8.0", "jszip": "~3.8.0",
"react": "17.0.1", "react": "17.0.1",
@@ -8726,6 +8727,28 @@
"url": "https://opencollective.com/popperjs" "url": "https://opencollective.com/popperjs"
} }
}, },
"node_modules/@rrweb/rrweb-plugin-console-record": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@rrweb/rrweb-plugin-console-record/-/rrweb-plugin-console-record-2.2.0.tgz",
"integrity": "sha512-2c6LEsoH3+1NFcHckcwuErg7bkpFadt9++uKJh2x9BtWUDxoVKzLp+qLCq6f90MLTjSIABDkAiCswVskENZT3g==",
"license": "MIT",
"peerDependencies": {
"@rrweb/utils": "^2.1.1",
"rrweb": "^2.1.1"
}
},
"node_modules/@rrweb/types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@rrweb/types/-/types-2.2.0.tgz",
"integrity": "sha512-2gTA/pRpIbuET123oSdX5ZUDZfWCOIMYBvpSai3fr5pk9LcbccPqqaXflX+roP4oKenLjNtJPGpFK3BfYeBKnA==",
"license": "MIT"
},
"node_modules/@rrweb/utils": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@rrweb/utils/-/utils-2.2.0.tgz",
"integrity": "sha512-e8FEp8wLswqgjDHpQNUUVfEXeDsrRMOVouvqIGKvnPxKYonjLlh0mU3O/17QNvCixFG5eUFR1B2jgTdiLlZxeQ==",
"license": "MIT"
},
"node_modules/@rushstack/debug-certificate-manager": { "node_modules/@rushstack/debug-certificate-manager": {
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/@rushstack/debug-certificate-manager/-/debug-certificate-manager-1.6.2.tgz", "resolved": "https://registry.npmjs.org/@rushstack/debug-certificate-manager/-/debug-certificate-manager-1.6.2.tgz",
@@ -9885,6 +9908,28 @@
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/@tnsu/monitoring-web": {
"version": "0.3.0",
"resolved": "https://git.tnsu.kz/api/packages/tansu/npm/%40tnsu%2Fmonitoring-web/-/0.3.0/monitoring-web-0.3.0.tgz",
"integrity": "sha512-4b9H643hl/KyWvugmuHW6lxk10wLRqfzeBTtEW4hZ2X7dfB4K7djESudurtwZibsWlfHibQNT2wqWgUznZ1DjA==",
"license": "UNLICENSED",
"dependencies": {
"@rrweb/rrweb-plugin-console-record": "^2.2.0",
"rrweb": "^2.2.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"vue": "^3.0.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"vue": {
"optional": true
}
}
},
"node_modules/@tnsu/ui-kit": { "node_modules/@tnsu/ui-kit": {
"version": "0.15.0", "version": "0.15.0",
"resolved": "https://git.tnsu.kz/api/packages/tansu/npm/%40tnsu%2Fui-kit/-/0.15.0/ui-kit-0.15.0.tgz", "resolved": "https://git.tnsu.kz/api/packages/tansu/npm/%40tnsu%2Fui-kit/-/0.15.0/ui-kit-0.15.0.tgz",
@@ -10022,6 +10067,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/css-font-loading-module": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/@types/css-font-loading-module/-/css-font-loading-module-0.0.7.tgz",
"integrity": "sha512-nl09VhutdjINdWyXxHWN/w9zlNCfr60JUqJbd24YXUuCwgeL0TpFSdElCwb6cxfB6ybE19Gjj4g0jsgkXxKv1Q==",
"license": "MIT"
},
"node_modules/@types/ejs": { "node_modules/@types/ejs": {
"version": "3.1.5", "version": "3.1.5",
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.5.tgz",
@@ -11627,6 +11678,12 @@
"node": ">=10.0.0" "node": ">=10.0.0"
} }
}, },
"node_modules/@xstate/fsm": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@xstate/fsm/-/fsm-1.6.5.tgz",
"integrity": "sha512-b5o1I6aLNeYlU/3CPlj/Z91ybk1gUsKT+5NAJI+2W4UjvS5KLG28K9v5UvNoFVjHV8PajVZ00RH3vnjyQO7ZAw==",
"license": "MIT"
},
"node_modules/@xtuc/ieee754": { "node_modules/@xtuc/ieee754": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
@@ -12513,6 +12570,15 @@
} }
} }
}, },
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/base64-js": { "node_modules/base64-js": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@@ -19813,6 +19879,12 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/mitt": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
"license": "MIT"
},
"node_modules/mkdirp": { "node_modules/mkdirp": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -19935,7 +20007,6 @@
"version": "3.3.16", "version": "3.3.16",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz",
"integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -20742,7 +20813,6 @@
"version": "8.5.25", "version": "8.5.25",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz",
"integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -22018,6 +22088,40 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/rrdom": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/rrdom/-/rrdom-2.2.0.tgz",
"integrity": "sha512-gxcBJWVtS/Xz+Ys8xcjPoWqr+C7wz/MS8NgmKw136I47Xygy17FYOGZqoGwEyvBn724jRDK1ljS+8w9FsZStOg==",
"license": "MIT",
"dependencies": {
"rrweb-snapshot": "^2.2.0"
}
},
"node_modules/rrweb": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/rrweb/-/rrweb-2.2.0.tgz",
"integrity": "sha512-ofVzPq11/yIQ7WhVb++rJGI2LoPPrxdqu0QAvRA4KGeXJ7LH52jQ0VlRH4+VXn5PA/7pz85/rRkQyBUqT1LraQ==",
"license": "MIT",
"dependencies": {
"@rrweb/types": "^2.2.0",
"@rrweb/utils": "^2.2.0",
"@types/css-font-loading-module": "0.0.7",
"@xstate/fsm": "^1.4.0",
"base64-arraybuffer": "^1.0.1",
"mitt": "^3.0.0",
"rrdom": "^2.2.0",
"rrweb-snapshot": "^2.2.0"
}
},
"node_modules/rrweb-snapshot": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-2.2.0.tgz",
"integrity": "sha512-Tg/PiCLy+zV9C0Jfb4IAGABtt5l/UOvwW5xjFk41ZQhBfUjeqPP1rZ9HMDrFPc7cawCUEenWw54+g/4vluO5lg==",
"license": "MIT",
"dependencies": {
"postcss": "^8.4.38"
}
},
"node_modules/rtl-css-js": { "node_modules/rtl-css-js": {
"version": "1.16.1", "version": "1.16.1",
"resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz",
@@ -23127,7 +23231,6 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
+1
View File
@@ -21,6 +21,7 @@
"@microsoft/sp-webpart-base": "1.22.1", "@microsoft/sp-webpart-base": "1.22.1",
"@pnp/sp": "^4.20.0", "@pnp/sp": "^4.20.0",
"@pnp/spfx-controls-react": "^3.25.0", "@pnp/spfx-controls-react": "^3.25.0",
"@tnsu/monitoring-web": "^0.3.0",
"@tnsu/ui-kit": "^0.15.0", "@tnsu/ui-kit": "^0.15.0",
"jszip": "~3.8.0", "jszip": "~3.8.0",
"react": "17.0.1", "react": "17.0.1",
@@ -9,6 +9,7 @@ import {
} from '@microsoft/sp-property-pane'; } from '@microsoft/sp-property-pane';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { IReadonlyTheme } from '@microsoft/sp-component-base'; import { IReadonlyTheme } from '@microsoft/sp-component-base';
import { initMonitoring, spfxTokenProvider } from '@tnsu/monitoring-web';
import * as strings from 'RequestPortalWebPartStrings'; import * as strings from 'RequestPortalWebPartStrings';
import RequestPortal from './components/RequestPortal'; import RequestPortal from './components/RequestPortal';
@@ -62,6 +63,9 @@ export interface IRequestPortalWebPartProps {
chatSelfNotify?: boolean; chatSelfNotify?: boolean;
} }
// Мониторинг — один на страницу: экземпляров веб-части на странице может быть несколько.
let monitoringStarted = false;
export default class RequestPortalWebPart extends BaseClientSideWebPart<IRequestPortalWebPartProps> { export default class RequestPortalWebPart extends BaseClientSideWebPart<IRequestPortalWebPartProps> {
private _isDarkTheme: boolean = false; private _isDarkTheme: boolean = false;
@@ -98,6 +102,12 @@ export default class RequestPortalWebPart extends BaseClientSideWebPart<IRequest
} }
protected onInit(): Promise<void> { protected onInit(): Promise<void> {
// Логи, ошибки, console.error и запись экрана в мониторинг (monitoring.tnsu.kz). Токен — молча через
// AAD веб-части (разрешение Logs.Write в package-solution.json); при отладке в workbench окружение — development.
if (!monitoringStarted) {
monitoringStarted = true;
initMonitoring({ service: 'requestPortal', getAccessToken: spfxTokenProvider(this.context.aadTokenProviderFactory) });
}
installErrorLogging(); // до всего остального — чтобы поймать и ранние отклонения installErrorLogging(); // до всего остального — чтобы поймать и ранние отклонения
initSP(this.context); // единый клиент PnPjs для записи в списки initSP(this.context); // единый клиент PnPjs для записи в списки