@docx-editor.dev/telemetry 0.0.0-stage → 2.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +121 -0
- package/README.md +94 -2
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/dist/chunk-73YEPWY5.js +1 -0
- package/dist/chunk-7ZXJ6HP2.cjs +1 -0
- package/dist/chunk-DT2KMPUJ.js +1 -0
- package/dist/chunk-DTEVX2XS.js +1 -0
- package/dist/chunk-LFQSY2TD.cjs +1 -0
- package/dist/chunk-LFX65QJG.js +4 -0
- package/dist/chunk-LGNT4I5W.cjs +1 -0
- package/dist/chunk-MJX3ECH3.cjs +4 -0
- package/dist/chunk-NUN46EXH.js +2 -0
- package/dist/chunk-RRYW7EAV.js +1 -0
- package/dist/chunk-S7KBMROA.js +1 -0
- package/dist/chunk-U6ERFNUM.cjs +1 -0
- package/dist/chunk-UK2MNJCG.cjs +2 -0
- package/dist/chunk-WGWKNKUT.cjs +1 -0
- package/dist/hocuspocus/index.cjs +1 -0
- package/dist/hocuspocus/index.d.cts +118 -0
- package/dist/hocuspocus/index.d.ts +118 -0
- package/dist/hocuspocus/index.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +332 -0
- package/dist/index.d.ts +332 -0
- package/dist/index.js +1 -0
- package/dist/ingest/index.cjs +1 -0
- package/dist/ingest/index.d.cts +107 -0
- package/dist/ingest/index.d.ts +107 -0
- package/dist/ingest/index.js +1 -0
- package/dist/otel/index.cjs +1 -0
- package/dist/otel/index.d.cts +57 -0
- package/dist/otel/index.d.ts +57 -0
- package/dist/otel/index.js +1 -0
- package/dist/pipeline-DbVW7S-K.d.cts +223 -0
- package/dist/pipeline-DbVW7S-K.d.ts +223 -0
- package/dist/prometheus/index.cjs +1 -0
- package/dist/prometheus/index.d.cts +88 -0
- package/dist/prometheus/index.d.ts +88 -0
- package/dist/prometheus/index.js +1 -0
- package/dist/sentry/index.cjs +1 -0
- package/dist/sentry/index.d.cts +134 -0
- package/dist/sentry/index.d.ts +134 -0
- package/dist/sentry/index.js +1 -0
- package/dist/server/index.cjs +1 -0
- package/dist/server/index.d.cts +156 -0
- package/dist/server/index.d.ts +156 -0
- package/dist/server/index.js +1 -0
- package/package.json +114 -4
package/LICENSE.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# EigenPal Pro Evaluation License 1.0
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EigenPal, Inc. All rights reserved.
|
|
4
|
+
|
|
5
|
+
By copying, modifying, or using the Software, you agree to these terms.
|
|
6
|
+
|
|
7
|
+
## 1. Covered Software
|
|
8
|
+
|
|
9
|
+
“Software” means all source code, object code, documentation, assets, and other
|
|
10
|
+
materials contained in the “packages/telemetry/” directory of the EigenPal DOCX
|
|
11
|
+
Editor repository, except for any material that expressly states that it is
|
|
12
|
+
subject to a different license.
|
|
13
|
+
|
|
14
|
+
## 2. Evaluation Permission; Modifications
|
|
15
|
+
|
|
16
|
+
Subject to these terms, EigenPal, Inc. grants you a limited, non-exclusive,
|
|
17
|
+
non-transferable, non-sublicensable, royalty-free license to:
|
|
18
|
+
|
|
19
|
+
1. view, clone, and copy the Software;
|
|
20
|
+
2. run the Software internally in a non-production environment solely to
|
|
21
|
+
evaluate its suitability for your intended application; and
|
|
22
|
+
3. modify the Software solely as reasonably necessary for that internal,
|
|
23
|
+
non-production evaluation.
|
|
24
|
+
|
|
25
|
+
For any such modification, the following applies:
|
|
26
|
+
|
|
27
|
+
You may keep any modification to yourself. If you do not disclose it to EigenPal, Inc. or to anyone else, it remains yours
|
|
28
|
+
If you disclose a modification to EigenPal, Inc. or to any third party, in any form, you assign all right, title, and interest in it to EigenPal, Inc. at the moment of disclosure. The same applies to any feedback you give EigenPal, Inc. You will promptly send EigenPal, Inc. the source code of any modification you disclose, and will sign any document needed to record the assignment.
|
|
29
|
+
Disclosing a modification to a third party grants that third party no rights in it or in the Software. You will not license or purport to license any modification to anyone.
|
|
30
|
+
You may continue using an assigned modification for the internal, non-production evaluation permitted by Section 2 for as long as this license is in effect. EigenPal, Inc. is not obliged to use or support any modification or feedback, and owes you nothing for it.
|
|
31
|
+
You confirm that any modification or feedback you disclose is yours to assign and is not subject to any license that would impose obligations on EigenPal, Inc. or grant rights to any third party.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
No other rights are granted.
|
|
35
|
+
|
|
36
|
+
## 3. No Production Use
|
|
37
|
+
|
|
38
|
+
You may not use the Software for Production Use.
|
|
39
|
+
|
|
40
|
+
“Production Use” means any use of the Software:
|
|
41
|
+
|
|
42
|
+
1. in a live, operational, or customer-facing environment;
|
|
43
|
+
2. to provide, operate, support, or enhance a product or service for another
|
|
44
|
+
person or organization;
|
|
45
|
+
3. to process live, customer, or business-operational data; or
|
|
46
|
+
4. as part of your ordinary internal business operations, other than evaluation
|
|
47
|
+
and testing.
|
|
48
|
+
|
|
49
|
+
For the avoidance of doubt, Production Use includes embedding the Software in a product made available to
|
|
50
|
+
others, offering the Software through a hosted or managed service, and using it
|
|
51
|
+
in a customer pilot or paid proof of concept.
|
|
52
|
+
|
|
53
|
+
## 4. No Distribution or Sublicensing
|
|
54
|
+
|
|
55
|
+
You may not sell, sublicense, distribute, publish, transfer, or otherwise make
|
|
56
|
+
the Software or modifications to the Software available to any third party.
|
|
57
|
+
|
|
58
|
+
You may allow your employees and contractors to access the Software solely for
|
|
59
|
+
your evaluation, provided they are bound by restrictions at least as protective
|
|
60
|
+
as these terms. You are responsible for their compliance.
|
|
61
|
+
|
|
62
|
+
## 5. Commercial Rights
|
|
63
|
+
|
|
64
|
+
Production Use and any rights not expressly granted by this license require a
|
|
65
|
+
separate written commercial agreement signed by EigenPal, Inc.
|
|
66
|
+
|
|
67
|
+
Commercial licenses are available by contacting licensing@eigenpal.com.
|
|
68
|
+
|
|
69
|
+
Access to the Software, correspondence with EigenPal, Inc., or payment of an
|
|
70
|
+
invoice does not by itself grant production or commercial rights unless those
|
|
71
|
+
rights are set out in a written agreement signed by EigenPal, Inc.
|
|
72
|
+
|
|
73
|
+
## 6. Ownership
|
|
74
|
+
|
|
75
|
+
EigenPal, Inc. and its licensors retain all rights, title, and interest in the
|
|
76
|
+
Software. This license does not transfer ownership or grant any rights by
|
|
77
|
+
implication.
|
|
78
|
+
|
|
79
|
+
Modifying the Software does not grant you the right to use the Software or those
|
|
80
|
+
modifications in production.
|
|
81
|
+
|
|
82
|
+
## 7. Termination
|
|
83
|
+
|
|
84
|
+
Your rights under this license terminate automatically if you breach these
|
|
85
|
+
terms or if EigenPal terminates this license.
|
|
86
|
+
|
|
87
|
+
Following termination, you must stop using the Software and delete your copies
|
|
88
|
+
and modifications, except for copies that you are legally required to retain.
|
|
89
|
+
EigenPal, Inc. may reinstate your rights in writing.
|
|
90
|
+
|
|
91
|
+
## 8. No Warranty
|
|
92
|
+
|
|
93
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED “AS IS” AND
|
|
94
|
+
WITHOUT WARRANTIES OF ANY KIND, WHETHER EXPRESS, IMPLIED, OR STATUTORY,
|
|
95
|
+
INCLUDING WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
|
|
96
|
+
TITLE, AND NON-INFRINGEMENT.
|
|
97
|
+
|
|
98
|
+
## 9. Limitation of Liability
|
|
99
|
+
|
|
100
|
+
TO THE MAXIMUM EXTENT PERMITTED BY LAW, EIGENPAL, INC. AND ITS LICENSORS WILL NOT BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, EXEMPLARY, OR PUNITIVE DAMAGES, OR FOR ANY LOSS OF DATA, REVENUE, PROFITS, OR BUSINESS, ARISING FROM OR RELATING TO THE SOFTWARE OR THIS LICENSE. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE TOTAL AGGREGATE LIABILITY OF EIGENPAL, INC. AND ITS LICENSORS FOR ALL CLAIMS ARISING FROM OR RELATING TO THE SOFTWARE OR THIS LICENSE, WHETHER IN CONTRACT, TORT, STRICT LIABILITY, OR ANY OTHER THEORY, WILL NOT EXCEED TEN UNITED STATES DOLLARS (US$10). THE FOREGOING LIMITATIONS APPLY EVEN IF EIGENPAL, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND EVEN IF ANY LIMITED REMEDY IS FOUND TO HAVE FAILED OF ITS ESSENTIAL PURPOSE.
|
|
101
|
+
|
|
102
|
+
## 10. Trademarks
|
|
103
|
+
|
|
104
|
+
This license does not grant permission to use the names, trademarks, service
|
|
105
|
+
marks, or logos of EigenPal, Inc., except to identify the origin of an
|
|
106
|
+
unmodified copy of the Software.
|
|
107
|
+
|
|
108
|
+
## 11. Governing Law and Jurisdiction
|
|
109
|
+
|
|
110
|
+
This license is governed by the laws of the State of California, without regard
|
|
111
|
+
to its conflict-of-laws rules.
|
|
112
|
+
|
|
113
|
+
Any dispute arising from or relating to this license will be subject to the
|
|
114
|
+
exclusive jurisdiction of the state and federal courts located in California,
|
|
115
|
+
and you consent to their jurisdiction.
|
|
116
|
+
|
|
117
|
+
## 12. Separate Commercial Agreements
|
|
118
|
+
|
|
119
|
+
If EigenPal, Inc. and you enter into a separate written commercial agreement,
|
|
120
|
+
that agreement controls to the extent it grants additional rights or conflicts
|
|
121
|
+
with this license.
|
package/README.md
CHANGED
|
@@ -1,3 +1,95 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @docx-editor.dev/telemetry
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Anonymous diagnostics, metrics, and error reporting for `@docx-editor.dev` editors and collaboration servers. Send them to OpenTelemetry, Prometheus, Sentry, or your own logger.
|
|
4
|
+
|
|
5
|
+
Built-in diagnostics contain codes, booleans, bucketed sizes and counts, and timings. They exclude document text, file names, author names, font names, and room names. You control any attributes you add and any data your monitoring SDKs collect. The package sends data only through exporters you configure.
|
|
6
|
+
|
|
7
|
+
## Install the package
|
|
8
|
+
|
|
9
|
+
The package is available in version 2.29.0 and later.
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @docx-editor.dev/telemetry @docx-editor.dev/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Add `@opentelemetry/api` or `@hocuspocus/server` only for the exporters and server integrations that you use. The Sentry exporter takes the Sentry SDK your app already loads.
|
|
16
|
+
|
|
17
|
+
## Editors
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { createTelemetry } from '@docx-editor.dev/telemetry';
|
|
21
|
+
import { otelExporter } from '@docx-editor.dev/telemetry/otel';
|
|
22
|
+
import { sentryExporter } from '@docx-editor.dev/telemetry/sentry';
|
|
23
|
+
import * as Sentry from '@sentry/react';
|
|
24
|
+
|
|
25
|
+
export const telemetry = createTelemetry({
|
|
26
|
+
// Sentry for failures, OpenTelemetry for metrics such as typing delay.
|
|
27
|
+
exporters: [sentryExporter(Sentry), otelExporter()],
|
|
28
|
+
include: {
|
|
29
|
+
documentOpen: true,
|
|
30
|
+
trackedChanges: true,
|
|
31
|
+
editing: true,
|
|
32
|
+
performance: true,
|
|
33
|
+
},
|
|
34
|
+
consent: () => consentManager.analytics === true, // your consent manager
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Outside your component, so the array is stable across renders:
|
|
38
|
+
export const MODULES = [telemetry.module];
|
|
39
|
+
// <DocxEditor document={bytes} modules={MODULES} />
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use `consoleExporter()` to view diagnostics during development. For example, the following diagnostic explains why the editing API refused a tracked picture deletion:
|
|
43
|
+
|
|
44
|
+
```text
|
|
45
|
+
[docx-editor] edit refused: edit.tracked-operation-unsupported (automation, tracked)
|
|
46
|
+
This editing API operation cannot be recorded as a tracked change, so nothing was applied. Use text edits such as range.insertText or range.delete, which tracking records. Never switch tracking off to make the edit succeed.
|
|
47
|
+
https://docx-editor.dev/docs/2.x/guides/diagnostics#edit-tracked-operation-unsupported
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The `performance` area measures typing delay and engine layout and paint times. Send it to an exporter that records metrics, such as `otelExporter()`. The Sentry exporter records performance only as breadcrumbs.
|
|
51
|
+
|
|
52
|
+
## Collaboration servers
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { Server } from '@hocuspocus/server';
|
|
56
|
+
import { withCollaborationTelemetry } from '@docx-editor.dev/telemetry/hocuspocus';
|
|
57
|
+
import { metricsHandler, prometheusRegistry } from '@docx-editor.dev/telemetry/prometheus';
|
|
58
|
+
|
|
59
|
+
const metrics = prometheusRegistry();
|
|
60
|
+
const { config, rooms } = withCollaborationTelemetry(
|
|
61
|
+
{ port: 1234, onAuthenticate, onLoadDocument, onStoreDocument },
|
|
62
|
+
{ exporters: [metrics] }
|
|
63
|
+
);
|
|
64
|
+
new Server(config);
|
|
65
|
+
|
|
66
|
+
app.get('/metrics', metricsHandler(metrics));
|
|
67
|
+
app.get('/admin/rooms', requireAdmin, (_request, response) => response.json(rooms.list()));
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
For other Yjs servers, use `roomTelemetry` from `@docx-editor.dev/telemetry/server`.
|
|
71
|
+
|
|
72
|
+
## Dashboards
|
|
73
|
+
|
|
74
|
+
Grafana dashboards show editor input delay, engine timings, document opens, and refused edits. They also show collaboration rooms, people, memory, and refusals.
|
|
75
|
+
|
|
76
|
+

|
|
77
|
+
|
|
78
|
+
Download [`editor-experience.json`](https://raw.githubusercontent.com/eigenpal/docx-editor/main/assets/observability/grafana/editor-experience.json) and [`collaboration.json`](https://raw.githubusercontent.com/eigenpal/docx-editor/main/assets/observability/grafana/collaboration.json), then import them into Grafana. For the setup each one needs, see [Dashboards](https://docx-editor.dev/docs/2.x/telemetry/dashboards).
|
|
79
|
+
|
|
80
|
+
## Entry points
|
|
81
|
+
|
|
82
|
+
| Entry | Contents |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `@docx-editor.dev/telemetry` | `createTelemetry`, `consoleExporter`, `callbackExporter`, `memoryExporter`, `isFailure`, `explainDiagnostic`, the metric catalog |
|
|
85
|
+
| `@docx-editor.dev/telemetry/otel` | `otelExporter`, through your OpenTelemetry SDK |
|
|
86
|
+
| `@docx-editor.dev/telemetry/sentry` | `sentryExporter`, `dropEditorBreadcrumbs`, `EDITOR_SELECTORS` |
|
|
87
|
+
| `@docx-editor.dev/telemetry/prometheus` | `prometheusRegistry`, `metricsHandler`, `fetchMetricsHandler`, for server processes. Browser metrics go through `otelExporter()` and an OpenTelemetry collector. |
|
|
88
|
+
| `@docx-editor.dev/telemetry/server` | `roomTelemetry`, `hmacRoomLabel` |
|
|
89
|
+
| `@docx-editor.dev/telemetry/hocuspocus` | `withCollaborationTelemetry`, `serveMetrics`, `requireBearerToken`, `hmacRoomLabel` |
|
|
90
|
+
|
|
91
|
+
For the full guide, see [Telemetry](https://docx-editor.dev/docs/2.x/telemetry).
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
EigenPal Pro License. See [LICENSE.md](./LICENSE.md).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
`@docx-editor.dev/telemetry` is distributed under LicenseRef-EigenPal-Pro-Evaluation-1.0. Its published bundles also contain
|
|
4
|
+
source from the open-source packages listed below, redistributed here under
|
|
5
|
+
their own licenses, reproduced in full.
|
|
6
|
+
|
|
7
|
+
Those copies are not verbatim. The build inlines, minifies and tree-shakes
|
|
8
|
+
them, and includes only the parts each bundle reaches, so what ships is a
|
|
9
|
+
modified form of the original source.
|
|
10
|
+
|
|
11
|
+
The terms of LicenseRef-EigenPal-Pro-Evaluation-1.0 do not apply to the portions of these bundles
|
|
12
|
+
derived from the packages listed below. Those portions are licensed to you
|
|
13
|
+
under their own terms.
|
|
14
|
+
|
|
15
|
+
This file covers code copied INTO the published bundles. Packages this one
|
|
16
|
+
declares as `dependencies` or `peerDependencies` are installed separately by
|
|
17
|
+
the consumer and are not repeated here.
|
|
18
|
+
|
|
19
|
+
Generated by `bun run notices:generate` from the build's esbuild metafile.
|
|
20
|
+
Do not edit by hand.
|
|
21
|
+
|
|
22
|
+
No third-party code is bundled into this package.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e="docx_editor.version",n=[.005,.01,.025,.05,.1,.25,.5,1,2.5,5,10,30,60],l=[1024,16*1024,64*1024,256*1024,1024*1024,4*1024*1024,16*1024*1024,64*1024*1024,256*1024*1024,1024*1024*1024],i=[.016,.033,.05,.1,.2,.5,1],c=[1,2,3,5,10,20,50,100,250],p=[1e3,1e4,5e4,1e5,25e4,5e5,1e6],g=[.1,.25,.5,.75,.9,.95,1],d=[60,300,900,3600,4*3600,24*3600,168*3600];function o(t,r,a,m,u=[],s){return Object.freeze({name:t,kind:r,unit:a,description:m,labels:u,...s?{buckets:s}:{}})}var b=Object.freeze({documentOpens:o("docx_editor.document.opens","counter","{open}","Documents opened or refused, by outcome, refusal code, engine reason, and part role.",["outcome","code","cause","part",e]),documentOpenDuration:o("docx_editor.document.open.duration","histogram","s","Time from the start of an open to the laid-out document.",[e],n),editRejections:o("docx_editor.edit.rejections","counter","{edit}","Edits, commands, and tracked changes refused, by public code and engine reason.",["code","cause","origin","tracked",e]),reviewSkipped:o("docx_editor.review.skipped","counter","{change}","Tracked changes skipped by accept, reject, or reassign requests, by engine reason, operation, and change kind.",["code","cause","operation","change_kind",e]),fontFailures:o("docx_editor.font.failures","counter","{failure}","Font faces that failed to load and were substituted.",["code",e]),historyDiagnostics:o("docx_editor.history.diagnostics","counter","{event}","Undo steps that did not group as the gesture intended, by code.",["code",e]),customNodeDiagnostics:o("docx_editor.custom_node.diagnostics","counter","{node}","Custom node payloads that could not be read, by code.",["code",e]),collabClientStatusTransitions:o("docx_editor.collab.client.status_transitions","counter","{transition}","Collaboration status changes on clients, by new status and failure code.",["status","code",e]),collabClientConnectDuration:o("docx_editor.collab.client.connect.duration","histogram","s","Time from an editor attaching a room to its first ready status, when the editor attached before the room was ready.",[e],n),collabClientParticipants:o("docx_editor.collab.client.participants","histogram","{participant}","People in the room, as each client sees it when the count changes.",[e],c),editorInteractionDuration:o("docx_editor.editor.interaction.duration","histogram","s","Key presses and pointer presses on the pages, to the next frame on screen, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),editorLayoutDuration:o("docx_editor.editor.layout.duration","histogram","s","Engine layout passes after edits and view changes, background work included, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),editorPaintDuration:o("docx_editor.editor.paint.duration","histogram","s","Engine paints of the pages, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),droppedEvents:o("docx_editor.telemetry.dropped_events","counter","{event}","Events the anonymity guard dropped, by reason. Usually a version mismatch.",["reason",e]),roomsActive:o("docx_editor.collab.rooms.active","gauge","{room}","Rooms loaded."),connectionsActive:o("docx_editor.collab.connections.active","gauge","{connection}","Open client connections. One person with two tabs is two connections."),participantsActive:o("docx_editor.collab.participants.active","gauge","{participant}","People present in all rooms, from awareness states."),roomParticipants:o("docx_editor.collab.room.participants","histogram","{participant}","People present in each room, sampled once per room per interval.",[],c),roomParticipantsMax:o("docx_editor.collab.room.participants.max","gauge","{participant}","People in the fullest room now."),roomMemory:o("docx_editor.collab.room.memory","histogram","By","Bytes each room holds, sampled per room: encoded state, blobs, and updates not yet stored.",["kind"],l),roomsMemory:o("docx_editor.collab.rooms.memory","gauge","By","Bytes all rooms hold together at the last sample.",["kind"]),roomNodes:o("docx_editor.collab.room.nodes","histogram","{node}","Shared document nodes per room, live and tombstoned.",["state"],p),roomResourceUsage:o("docx_editor.collab.room.resource_usage","histogram","1","Share of each room resource limit in use, from 0 to 1.",["resource"],g),roomAge:o("docx_editor.collab.room.age","histogram","s","How long each room has been loaded.",[],d),roomIdle:o("docx_editor.collab.room.idle","histogram","s","Time since each room last changed.",[],d),roomLoadDuration:o("docx_editor.collab.room.load.duration","histogram","s","Time to load a room, by outcome.",["outcome"],n),roomStoreDuration:o("docx_editor.collab.room.store.duration","histogram","s","Time to store a room, by outcome.",["outcome"],n),admissionRejections:o("docx_editor.collab.admission.rejections","counter","{connection}","Connections refused at admission, by reason.",["reason"]),messageRefusals:o("docx_editor.collab.message.refusals","counter","{message}","Messages refused before they applied, by reason, such as room-generation-changed.",["reason"]),updates:o("docx_editor.collab.updates","counter","{update}","Document updates applied to rooms."),updateBytes:o("docx_editor.collab.update.bytes","counter","By","Bytes of document updates applied to rooms."),roomParticipantsByRoom:o("docx_editor.collab.room.participants.current","gauge","{participant}","People in each room, labeled by room. Recorded only with perRoomSeries.",["room"]),roomMemoryByRoom:o("docx_editor.collab.room.memory.current","gauge","By","Bytes each room holds, labeled by room and kind. Recorded only with perRoomSeries.",["room","kind"]),migrations:o("docx_editor.collab.migrations","counter","{room}","Room migrations, by outcome.",["outcome"])}),h={s:"seconds",By:"bytes"};function y(t){let r=t.name.replace(/[^a-zA-Z0-9_]/g,"_"),a=t.unit==="1"?t.kind==="gauge"?"ratio":void 0:h[t.unit];return a&&!r.endsWith(`_${a}`)&&(r+=`_${a}`),t.kind==="counter"&&(r+="_total"),r}export{b as a,y as b};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkU6ERFNUM_cjs=require('./chunk-U6ERFNUM.cjs'),chunkLGNT4I5W_cjs=require('./chunk-LGNT4I5W.cjs'),crypto=require('crypto'),collaboration$1=require('@docx-editor.dev/pro/collaboration'),core=require('@docx-editor.dev/core'),collaboration=require('@docx-editor.dev/core/collaboration'),M=require('yjs');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var M__namespace=/*#__PURE__*/_interopNamespace(M);function X(r){if(typeof r!="string"||r.length===0)throw new TypeError("hmacRoomLabel needs a non-empty secret, such as an environment variable.");let o=c=>`room-${crypto.createHmac("sha256",r).update(c).digest("hex").slice(0,16)}`;return C.add(o),o}var C=new WeakSet;function z(r,o){if(!r)return "permission-denied";let c=r,u=typeof r=="string"?r:typeof r=="object"?c.reason??c.code??(typeof c.message=="string"&&o.has(c.message.toLowerCase())?c.message:void 0):void 0;if(u===void 0)return "other";if(typeof u=="number")return Y[u]??"other";if(typeof u!="string")return "other";if(collaboration.isCollaborationFailureCode(u))return u;let b=u.toLowerCase();return o.has(b)?b:"other"}var Y={4401:"unauthorized",4403:"forbidden"},F=core.diagnosticCodes().map(r=>r.replace(/^collab\./,"")).filter(collaboration.isCollaborationFailureCode),$=["unauthorized","forbidden","permission-denied","unknown-room","rate-limited"];function Z(r){let o=chunkU6ERFNUM_cjs.c(r),c=new Set([...$,...r.reasons??[]].map(e=>e.toLowerCase())),u=r.measureState??true;for(let e of new Set([...c,...F,"other"]))o.declare(chunkLGNT4I5W_cjs.a.admissionRejections,{reason:e}),o.declare(chunkLGNT4I5W_cjs.a.messageRefusals,{reason:e});for(let e of ["success","failure"])o.declare(chunkLGNT4I5W_cjs.a.roomLoadDuration,{outcome:e}),o.declare(chunkLGNT4I5W_cjs.a.roomStoreDuration,{outcome:e});for(let e of ["migrated","unchanged","failed"])o.declare(chunkLGNT4I5W_cjs.a.migrations,{outcome:e});o.declare(chunkLGNT4I5W_cjs.a.updates),o.declare(chunkLGNT4I5W_cjs.a.updateBytes);let b=e=>{try{return z(r.reasonOf?.(e)??e,c)}catch{return "other"}},B=r.perRoomSeries===true;if(B&&r.roomLabel&&!C.has(r.roomLabel))throw new TypeError("perRoomSeries puts the room label into every series, so it accepts only the default label or hmacRoomLabel(secret). A custom roomLabel could put a room name in a metric.");for(let e of r.exporters)e.metric||console.warn(`[docx-editor telemetry] exporter "${e.name}" records no metrics, and room telemetry sends only metrics. Use otelExporter or prometheusRegistry on a server.`);let m=new Set,E=0,_=r.roomLabel??(()=>`room-${E+=1}`),f=()=>Date.now();function g(){let e=0,n=0,t=0;for(let a of m){let l=w(a);e+=a.connections,n+=l,t=Math.max(t,l);}o.metric(chunkLGNT4I5W_cjs.a.roomsActive,m.size),o.metric(chunkLGNT4I5W_cjs.a.connectionsActive,e),o.metric(chunkLGNT4I5W_cjs.a.participantsActive,n),o.metric(chunkLGNT4I5W_cjs.a.roomParticipantsMax,t);}function S(e,n){let t=e==="load"?chunkLGNT4I5W_cjs.a.roomLoadDuration:chunkLGNT4I5W_cjs.a.roomStoreDuration,a=globalThis.performance?.now()??f(),l=n?.pendingBytes??0,y=false;return i=>{y||(y=true,o.metric(t,G(a),{outcome:i}),i==="success"&&e==="store"&&n&&(n.pendingBytes=Math.max(0,n.pendingBytes-l)));}}async function x(e,n,t){let a=S(e,t);try{let l=await n();return a("success"),l}catch(l){throw a("failure"),l}}function O(e,n){try{j(e,n);}catch{e.changed=true;}}function j(e,n){if(e.changed||!e.sampled){e.changed=false,e.sampled=true,u&&(e.stateBytes=M__namespace.encodeStateAsUpdate(e.doc).byteLength);try{let t=collaboration$1.readCollaborationResourceUsage(e.doc);e.blobBytes=t.blobBytes,e.nodes=t.nodes;let a={nodes:t.nodes/t.maxNodes,relationships:t.relationships/t.maxRelationships,parts:t.parts/t.maxParts,blobBytes:t.blobBytes/t.maxBlobBytes};e.limitRatio=Math.max(...Object.values(a)),e.ratios=a,e.nodeStates={live:t.nodes-t.tombstonedNodes,tombstoned:t.tombstonedNodes};}catch{}}for(let[t,a]of Object.entries(e.ratios??{}))o.metric(chunkLGNT4I5W_cjs.a.roomResourceUsage,a,{resource:t});for(let[t,a]of Object.entries(e.nodeStates??{}))o.metric(chunkLGNT4I5W_cjs.a.roomNodes,a,{state:t});if(o.metric(chunkLGNT4I5W_cjs.a.roomParticipants,w(e)),e.stateBytes!==null&&o.metric(chunkLGNT4I5W_cjs.a.roomMemory,e.stateBytes,{kind:"state"}),e.blobBytes!==null&&o.metric(chunkLGNT4I5W_cjs.a.roomMemory,e.blobBytes,{kind:"blobs"}),o.metric(chunkLGNT4I5W_cjs.a.roomMemory,e.pendingBytes,{kind:"pending_updates"}),o.metric(chunkLGNT4I5W_cjs.a.roomAge,(n-e.openedAt)/1e3),o.metric(chunkLGNT4I5W_cjs.a.roomIdle,(n-e.lastChange)/1e3),B){let t=e.handle.label;o.metric(chunkLGNT4I5W_cjs.a.roomParticipantsByRoom,w(e),{room:t});for(let[a,l]of A(e))o.metric(chunkLGNT4I5W_cjs.a.roomMemoryByRoom,l,{room:t,kind:a});}}function h(){let e={state:0,blobs:0,pending_updates:0};for(let n of m)e.state+=n.stateBytes??0,e.blobs+=n.blobBytes??0,e.pending_updates+=n.pendingBytes;for(let[n,t]of Object.entries(e))o.metric(chunkLGNT4I5W_cjs.a.roomsMemory,t,{kind:n});g();}function D(){let e=f();for(let n of m)O(n,e);h();}let v=false;async function H(){if(!v){v=true;try{let e=f();for(let n of [...m])m.has(n)&&O(n,e),await new Promise(t=>setTimeout(t,0));h();}finally{v=false;}}}h();let T=r.sampleInterval??6e4,k=T===false?null:setInterval(()=>{H();},T);return k?.unref?.(),{open(e,n={}){let t=f(),a=(d,p)=>{if(i.changed=true,i.loading>0)return;i.lastChange=f();let R=p?.source;R==="redis"||R==="local"&&p.skipStoreHooks===true||(i.pendingBytes+=d.byteLength,o.metric(chunkLGNT4I5W_cjs.a.updates,1),o.metric(chunkLGNT4I5W_cjs.a.updateBytes,d.byteLength));},l=d=>{let{added:p,removed:R}=d??{};(p?.length??0)+(R?.length??0)>0&&g();};e.on("update",a),n.awareness?.on("change",l);let y={label:_(n.name??""),async time(d,p){d==="load"&&(i.loading+=1);try{return await x(d,p,i)}finally{d==="load"&&(i.loading-=1);}},begin:d=>S(d,i),connected(){i.connections+=1,g();},disconnected(){i.connections=Math.max(0,i.connections-1),g();},close(){if(m.delete(i)){if(i.dispose(),B){let d=y.label;o.forget(chunkLGNT4I5W_cjs.a.roomParticipantsByRoom,{room:d});for(let[p]of A(i))o.forget(chunkLGNT4I5W_cjs.a.roomMemoryByRoom,{room:d,kind:p});}h();}}},i={handle:y,doc:e,awareness:n.awareness,openedAt:t,lastChange:t,connections:0,pendingBytes:0,changed:true,loading:0,sampled:false,stateBytes:null,blobBytes:null,nodes:null,limitRatio:null,dispose(){e.off("update",a),n.awareness?.off("change",l);}};return m.add(i),g(),y},rejected(e){o.metric(chunkLGNT4I5W_cjs.a.admissionRejections,1,{reason:b(e)});},refused(e){o.metric(chunkLGNT4I5W_cjs.a.messageRefusals,1,{reason:b(e)});},migrated(e){o.metric(chunkLGNT4I5W_cjs.a.migrations,1,{outcome:e});},time:(e,n)=>x(e,n),begin:e=>S(e),list(){let e=f();return [...m].map(n=>({room:n.handle.label,participants:w(n),connections:n.connections,stateBytes:n.stateBytes,blobBytes:n.blobBytes,pendingBytes:n.pendingBytes,nodes:n.nodes,limitRatio:n.limitRatio,ageSeconds:Math.round((e-n.openedAt)/1e3),idleSeconds:Math.round((e-n.lastChange)/1e3)}))},sample:D,flush:()=>o.flush(),async shutdown(){k&&clearInterval(k);for(let e of [...m])e.handle.close();await o.shutdown();}}}function A(r){return [["state",r.stateBytes??0],["blobs",r.blobBytes??0],["pending_updates",r.pendingBytes]]}function w(r){if(!r.awareness)return r.connections;try{return r.awareness.getStates().size}catch{return r.connections}}function G(r){return Math.max(0,((globalThis.performance?.now()??Date.now())-r)/1e3)}exports.a=X;exports.b=Z;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function n(){try{return process.env.NODE_ENV}catch{return}}export{n as a};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a as a$1}from'./chunk-DT2KMPUJ.js';import {diagnosticCodes,diagnosticCauses,diagnosticCommands,explainDiagnostic}from'@docx-editor.dev/core';var w=new Set(diagnosticCodes());function u(t){return new Set(Object.keys(t))}var N=u({package:true,"content-types":true,relationships:true,"main-document":true,glossary:true,styles:true,numbering:true,settings:true,"web-settings":true,"font-table":true,theme:true,header:true,footer:true,footnotes:true,endnotes:true,comments:true,people:true,"custom-xml":true,"document-properties":true,media:true,embedding:true,other:true}),C=u({Error:true,TypeError:true,RangeError:true,ReferenceError:true,SyntaxError:true,other:true}),j=u({accept:true,reject:true,reassign:true}),M=u({"open-mount":true,"open-layout":true,command:true,"review-item":true,automation:true}),T=u({insert:true,delete:true,replace:true,moveFrom:true,moveTo:true,format:true,paragraphMark:true,structural:true}),D=u({rPrChange:true,pPrChange:true,sectPrChange:true,tblPrChange:true,tblPrExChange:true,tblGridChange:true,trPrChange:true,tcPrChange:true,numberingChange:true,other:true}),c={kind:new Set(["document.open","edit.rejected","review.skipped","font.failed","history","custom-node","collab.status","collab.participants","performance"]),code:w,outcome:new Set(["opened","rejected"]),origin:new Set(["command","input","automation"]),command:new Set(diagnosticCommands()),sizeBucket:/^(?:\d+(?:KiB|MiB)?-\d+(?:KiB|MiB)|512MiB\+)$/,pagesBucket:new Set(["0","1","2-9","10-99","100-999","1000+"]),editorSessionId:/^e_(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{16,64}|[0-9a-z]{6,12}_[0-9a-z]{1,8})$/,engineVersion:/^(?:development|\d{1,4}\.\d{1,4}\.\d{1,4}(?:-[0-9A-Za-z.]{1,20})?)$/,status:new Set(["initializing","ready","disconnected","error","destroyed"]),previous:new Set(["none","initializing","ready","disconnected","error","destroyed"]),cause:new Set(diagnosticCauses()),part:N,errorName:C,stage:M,operation:j,changeKind:T,formattingKind:D},l=new Set(["schemaVersion","time","durationMs","count","repeated","connectMs","participants","windowMs"]),g=new Set(["tracked","recovering"]),m=new Set;function a(t,n=t){m.has(n)||a$1()==="production"||(m.add(n),console.warn(`[docx-editor telemetry] ${t}`));}function f(t,n){let i=Object.hasOwn(c,t)?c[t]:void 0;return i?i instanceof RegExp?i.test(n):i.has(n):false}function B(t){let n=t;if(typeof n.kind!="string"||!f("kind",n.kind))return a("dropped an event of an unknown kind; core and telemetry versions may differ","kind"),{dropped:"unknown-kind"};let i=typeof n.code=="string"?n.code:void 0;if(i!==void 0&&!w.has(i))return a("dropped an event with an unknown code; core and telemetry versions may differ","code"),{dropped:"unknown-code"};let o=i?explainDiagnostic(i):void 0,r={};for(let[e,s]of Object.entries(n)){if(e==="resource"||e==="attributes")continue;if(e==="shape"){let d=K(s);if(!d)return a('dropped an event whose "shape" is not a valid document shape',"shape"),{dropped:"invalid-field"};r.shape=d;continue}if(I.has(e)){let d=x(s);if(!d)return a(`dropped an event whose "${e}" is not a valid timing summary`,`timing:${e}`),{dropped:"invalid-field"};r[e]=d;continue}if(e==="hint"||e==="docs"){o&&s===o[e]&&(r[e]=s);continue}let R=Object.hasOwn(c,e)||l.has(e)||g.has(e);if(typeof s=="number"&&l.has(e)&&Number.isFinite(s))r[e]=s;else if(typeof s=="boolean"&&g.has(e))r[e]=s;else if(typeof s=="string"&&f(e,s))r[e]=s;else {if(R)return a(`dropped an event whose "${e}" is not a valid value`,`field:${e}`),{dropped:"invalid-field"};a(`dropped the field "${e}", which is not an anonymous diagnostic field`,`extra:${e}`);}}return r.resource=t.resource,r.attributes=t.attributes??{},{event:Object.freeze(r)}}var I=new Set(["interaction","layout","paint"]),y=["count","p50Ms","p95Ms","maxMs"],$=8,h=t=>typeof t=="number"&&Number.isFinite(t)&&t>=0;function x(t){if(!t||typeof t!="object")return null;let n=t,i=[...y,"bands"];if(Object.keys(n).some(e=>!i.includes(e)))return null;let o={};for(let e of y){if(!h(n[e]))return null;o[e]=n[e];}let r=n.bands;return !Array.isArray(r)||r.length!==$||!r.every(h)?null:(o.bands=Object.freeze([...r]),Object.freeze(o))}var b=["parts","paragraphs","reviewItems","embeddedFonts"];function K(t){if(!t||typeof t!="object")return null;let n=t;if(Object.keys(n).some(o=>!b.includes(o)))return null;let i={};for(let o of b){let r=n[o];if(typeof r!="string"||!f("pagesBucket",r))return null;i[o]=r;}return Object.freeze(i)}var k=/^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/,S=/^[A-Za-z0-9_.:+-]{0,64}$/;function F(t,n,i){let o={};for(let[r,e]of Object.entries(t)){if(!k.test(r)||i&&!i.includes(r)){a(`dropped the attribute "${r.slice(0,40)}" on ${n}`,`attribute:${n}:${r}`);continue}typeof e=="number"||typeof e=="boolean"?o[r]=e:typeof e=="string"&&(o[r]=i&&!S.test(e)?"other":e.slice(0,256));}return o}function P(t){if(!t||typeof t!="object"||Array.isArray(t))return;let n={};for(let[i,o]of Object.entries(t))k.test(i)&&(typeof o=="boolean"||typeof o=="number"&&Number.isFinite(o)||typeof o=="string"&&o&&S.test(o))&&(n[i]=o);return Object.keys(n).length?n:void 0}export{B as a,F as b,P as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkWGWKNKUT_cjs=require('./chunk-WGWKNKUT.cjs'),core=require('@docx-editor.dev/core');var w=new Set(core.diagnosticCodes());function u(t){return new Set(Object.keys(t))}var N=u({package:true,"content-types":true,relationships:true,"main-document":true,glossary:true,styles:true,numbering:true,settings:true,"web-settings":true,"font-table":true,theme:true,header:true,footer:true,footnotes:true,endnotes:true,comments:true,people:true,"custom-xml":true,"document-properties":true,media:true,embedding:true,other:true}),C=u({Error:true,TypeError:true,RangeError:true,ReferenceError:true,SyntaxError:true,other:true}),j=u({accept:true,reject:true,reassign:true}),M=u({"open-mount":true,"open-layout":true,command:true,"review-item":true,automation:true}),T=u({insert:true,delete:true,replace:true,moveFrom:true,moveTo:true,format:true,paragraphMark:true,structural:true}),D=u({rPrChange:true,pPrChange:true,sectPrChange:true,tblPrChange:true,tblPrExChange:true,tblGridChange:true,trPrChange:true,tcPrChange:true,numberingChange:true,other:true}),c={kind:new Set(["document.open","edit.rejected","review.skipped","font.failed","history","custom-node","collab.status","collab.participants","performance"]),code:w,outcome:new Set(["opened","rejected"]),origin:new Set(["command","input","automation"]),command:new Set(core.diagnosticCommands()),sizeBucket:/^(?:\d+(?:KiB|MiB)?-\d+(?:KiB|MiB)|512MiB\+)$/,pagesBucket:new Set(["0","1","2-9","10-99","100-999","1000+"]),editorSessionId:/^e_(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{16,64}|[0-9a-z]{6,12}_[0-9a-z]{1,8})$/,engineVersion:/^(?:development|\d{1,4}\.\d{1,4}\.\d{1,4}(?:-[0-9A-Za-z.]{1,20})?)$/,status:new Set(["initializing","ready","disconnected","error","destroyed"]),previous:new Set(["none","initializing","ready","disconnected","error","destroyed"]),cause:new Set(core.diagnosticCauses()),part:N,errorName:C,stage:M,operation:j,changeKind:T,formattingKind:D},l=new Set(["schemaVersion","time","durationMs","count","repeated","connectMs","participants","windowMs"]),g=new Set(["tracked","recovering"]),m=new Set;function a(t,n=t){m.has(n)||chunkWGWKNKUT_cjs.a()==="production"||(m.add(n),console.warn(`[docx-editor telemetry] ${t}`));}function f(t,n){let i=Object.hasOwn(c,t)?c[t]:void 0;return i?i instanceof RegExp?i.test(n):i.has(n):false}function B(t){let n=t;if(typeof n.kind!="string"||!f("kind",n.kind))return a("dropped an event of an unknown kind; core and telemetry versions may differ","kind"),{dropped:"unknown-kind"};let i=typeof n.code=="string"?n.code:void 0;if(i!==void 0&&!w.has(i))return a("dropped an event with an unknown code; core and telemetry versions may differ","code"),{dropped:"unknown-code"};let o=i?core.explainDiagnostic(i):void 0,r={};for(let[e,s]of Object.entries(n)){if(e==="resource"||e==="attributes")continue;if(e==="shape"){let d=K(s);if(!d)return a('dropped an event whose "shape" is not a valid document shape',"shape"),{dropped:"invalid-field"};r.shape=d;continue}if(I.has(e)){let d=x(s);if(!d)return a(`dropped an event whose "${e}" is not a valid timing summary`,`timing:${e}`),{dropped:"invalid-field"};r[e]=d;continue}if(e==="hint"||e==="docs"){o&&s===o[e]&&(r[e]=s);continue}let R=Object.hasOwn(c,e)||l.has(e)||g.has(e);if(typeof s=="number"&&l.has(e)&&Number.isFinite(s))r[e]=s;else if(typeof s=="boolean"&&g.has(e))r[e]=s;else if(typeof s=="string"&&f(e,s))r[e]=s;else {if(R)return a(`dropped an event whose "${e}" is not a valid value`,`field:${e}`),{dropped:"invalid-field"};a(`dropped the field "${e}", which is not an anonymous diagnostic field`,`extra:${e}`);}}return r.resource=t.resource,r.attributes=t.attributes??{},{event:Object.freeze(r)}}var I=new Set(["interaction","layout","paint"]),y=["count","p50Ms","p95Ms","maxMs"],$=8,h=t=>typeof t=="number"&&Number.isFinite(t)&&t>=0;function x(t){if(!t||typeof t!="object")return null;let n=t,i=[...y,"bands"];if(Object.keys(n).some(e=>!i.includes(e)))return null;let o={};for(let e of y){if(!h(n[e]))return null;o[e]=n[e];}let r=n.bands;return !Array.isArray(r)||r.length!==$||!r.every(h)?null:(o.bands=Object.freeze([...r]),Object.freeze(o))}var b=["parts","paragraphs","reviewItems","embeddedFonts"];function K(t){if(!t||typeof t!="object")return null;let n=t;if(Object.keys(n).some(o=>!b.includes(o)))return null;let i={};for(let o of b){let r=n[o];if(typeof r!="string"||!f("pagesBucket",r))return null;i[o]=r;}return Object.freeze(i)}var k=/^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/,S=/^[A-Za-z0-9_.:+-]{0,64}$/;function F(t,n,i){let o={};for(let[r,e]of Object.entries(t)){if(!k.test(r)||i&&!i.includes(r)){a(`dropped the attribute "${r.slice(0,40)}" on ${n}`,`attribute:${n}:${r}`);continue}typeof e=="number"||typeof e=="boolean"?o[r]=e:typeof e=="string"&&(o[r]=i&&!S.test(e)?"other":e.slice(0,256));}return o}function P(t){if(!t||typeof t!="object"||Array.isArray(t))return;let n={};for(let[i,o]of Object.entries(t))k.test(i)&&(typeof o=="boolean"||typeof o=="number"&&Number.isFinite(o)||typeof o=="string"&&o&&S.test(o))&&(n[i]=o);return Object.keys(n).length?n:void 0}exports.a=B;exports.b=F;exports.c=P;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import {b as b$1}from'./chunk-73YEPWY5.js';var f="text/plain; version=0.0.4; charset=utf-8";function b(r){return r.replace(/\\/g,"\\\\").replace(/\n/g,"\\n").replace(/"/g,'\\"')}function u(r,i){let t=Object.keys(r).sort().map(e=>`${e.replace(/[^a-zA-Z0-9_]/g,"_")}="${b(String(r[e]))}"`);return i&&t.push(i),t.length?`{${t.join(",")}}`:""}function p(r){return Object.keys(r).sort().map(i=>`${i}\0${String(r[i])}`).join("")}function l(r){return r===1/0?"+Inf":r===-1/0?"-Inf":Number.isNaN(r)?"NaN":String(r)}function y(){let r=new Map,i=(t,e)=>{let s=r.get(t.name);s||(s={definition:t,series:new Map},r.set(t.name,s));let o=p(e),n=s.series.get(o);return n||(n={labels:e,value:0},t.kind==="histogram"&&(n.buckets=new Array((t.buckets??[]).length).fill(0),n.sum=0),s.series.set(o,n)),n};return {name:"prometheus",metric(t){let{definition:e,value:s,attributes:o}=t,n=i(e,o);e.kind==="counter"?n.value+=Math.max(0,s):e.kind==="gauge"?n.value=s:(n.value+=1,n.sum+=s,(e.buckets??[]).forEach((a,c)=>{s<=a&&(n.buckets[c]+=1);}));},declare(t,e){i(t,e);},forget(t,e){r.get(t.name)?.series.delete(p(e));},metrics(){let t=[];for(let{definition:e,series:s}of r.values()){let o=b$1(e);t.push(`# HELP ${o} ${e.description.replace(/\n/g," ")}`),t.push(`# TYPE ${o} ${e.kind}`);for(let n of s.values()){if(e.kind!=="histogram"){t.push(`${o}${u(n.labels)} ${l(n.value)}`);continue}(e.buckets??[]).forEach((a,c)=>{let d=`le="${l(a)}"`;t.push(`${o}_bucket${u(n.labels,d)} ${n.buckets[c]}`);}),t.push(`${o}_bucket${u(n.labels,'le="+Inf"')} ${n.value}`),t.push(`${o}_sum${u(n.labels)} ${l(n.sum)}`),t.push(`${o}_count${u(n.labels)} ${n.value}`);}}return t.length?`${t.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`:""},reset(){r.clear();}}}async function g(r,i){return (await Promise.all([r,...i.merge??[]].map(e=>e.metrics()))).filter(Boolean).join(`
|
|
4
|
+
`)}function $(r,i={}){return async(t,e)=>{let s;try{s=await g(r,i);}catch{e.statusCode=500,e.end("metrics unavailable");return}e.statusCode=200,e.setHeader("Content-Type",f),e.end(s);}}function x(r,i={}){return async()=>{try{return new Response(await g(r,i),{headers:{"Content-Type":f}})}catch{return new Response("metrics unavailable",{status:500})}}}export{f as a,y as b,$ as c,x as d};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var e="docx_editor.version",n=[.005,.01,.025,.05,.1,.25,.5,1,2.5,5,10,30,60],l=[1024,16*1024,64*1024,256*1024,1024*1024,4*1024*1024,16*1024*1024,64*1024*1024,256*1024*1024,1024*1024*1024],i=[.016,.033,.05,.1,.2,.5,1],c=[1,2,3,5,10,20,50,100,250],p=[1e3,1e4,5e4,1e5,25e4,5e5,1e6],g=[.1,.25,.5,.75,.9,.95,1],d=[60,300,900,3600,4*3600,24*3600,168*3600];function o(t,r,a,m,u=[],s){return Object.freeze({name:t,kind:r,unit:a,description:m,labels:u,...s?{buckets:s}:{}})}var b=Object.freeze({documentOpens:o("docx_editor.document.opens","counter","{open}","Documents opened or refused, by outcome, refusal code, engine reason, and part role.",["outcome","code","cause","part",e]),documentOpenDuration:o("docx_editor.document.open.duration","histogram","s","Time from the start of an open to the laid-out document.",[e],n),editRejections:o("docx_editor.edit.rejections","counter","{edit}","Edits, commands, and tracked changes refused, by public code and engine reason.",["code","cause","origin","tracked",e]),reviewSkipped:o("docx_editor.review.skipped","counter","{change}","Tracked changes skipped by accept, reject, or reassign requests, by engine reason, operation, and change kind.",["code","cause","operation","change_kind",e]),fontFailures:o("docx_editor.font.failures","counter","{failure}","Font faces that failed to load and were substituted.",["code",e]),historyDiagnostics:o("docx_editor.history.diagnostics","counter","{event}","Undo steps that did not group as the gesture intended, by code.",["code",e]),customNodeDiagnostics:o("docx_editor.custom_node.diagnostics","counter","{node}","Custom node payloads that could not be read, by code.",["code",e]),collabClientStatusTransitions:o("docx_editor.collab.client.status_transitions","counter","{transition}","Collaboration status changes on clients, by new status and failure code.",["status","code",e]),collabClientConnectDuration:o("docx_editor.collab.client.connect.duration","histogram","s","Time from an editor attaching a room to its first ready status, when the editor attached before the room was ready.",[e],n),collabClientParticipants:o("docx_editor.collab.client.participants","histogram","{participant}","People in the room, as each client sees it when the count changes.",[e],c),editorInteractionDuration:o("docx_editor.editor.interaction.duration","histogram","s","Key presses and pointer presses on the pages, to the next frame on screen, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),editorLayoutDuration:o("docx_editor.editor.layout.duration","histogram","s","Engine layout passes after edits and view changes, background work included, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),editorPaintDuration:o("docx_editor.editor.paint.duration","histogram","s","Engine paints of the pages, by page count bucket. Bucket counts are exact; the sum is estimated from the bands.",["pages",e],i),droppedEvents:o("docx_editor.telemetry.dropped_events","counter","{event}","Events the anonymity guard dropped, by reason. Usually a version mismatch.",["reason",e]),roomsActive:o("docx_editor.collab.rooms.active","gauge","{room}","Rooms loaded."),connectionsActive:o("docx_editor.collab.connections.active","gauge","{connection}","Open client connections. One person with two tabs is two connections."),participantsActive:o("docx_editor.collab.participants.active","gauge","{participant}","People present in all rooms, from awareness states."),roomParticipants:o("docx_editor.collab.room.participants","histogram","{participant}","People present in each room, sampled once per room per interval.",[],c),roomParticipantsMax:o("docx_editor.collab.room.participants.max","gauge","{participant}","People in the fullest room now."),roomMemory:o("docx_editor.collab.room.memory","histogram","By","Bytes each room holds, sampled per room: encoded state, blobs, and updates not yet stored.",["kind"],l),roomsMemory:o("docx_editor.collab.rooms.memory","gauge","By","Bytes all rooms hold together at the last sample.",["kind"]),roomNodes:o("docx_editor.collab.room.nodes","histogram","{node}","Shared document nodes per room, live and tombstoned.",["state"],p),roomResourceUsage:o("docx_editor.collab.room.resource_usage","histogram","1","Share of each room resource limit in use, from 0 to 1.",["resource"],g),roomAge:o("docx_editor.collab.room.age","histogram","s","How long each room has been loaded.",[],d),roomIdle:o("docx_editor.collab.room.idle","histogram","s","Time since each room last changed.",[],d),roomLoadDuration:o("docx_editor.collab.room.load.duration","histogram","s","Time to load a room, by outcome.",["outcome"],n),roomStoreDuration:o("docx_editor.collab.room.store.duration","histogram","s","Time to store a room, by outcome.",["outcome"],n),admissionRejections:o("docx_editor.collab.admission.rejections","counter","{connection}","Connections refused at admission, by reason.",["reason"]),messageRefusals:o("docx_editor.collab.message.refusals","counter","{message}","Messages refused before they applied, by reason, such as room-generation-changed.",["reason"]),updates:o("docx_editor.collab.updates","counter","{update}","Document updates applied to rooms."),updateBytes:o("docx_editor.collab.update.bytes","counter","By","Bytes of document updates applied to rooms."),roomParticipantsByRoom:o("docx_editor.collab.room.participants.current","gauge","{participant}","People in each room, labeled by room. Recorded only with perRoomSeries.",["room"]),roomMemoryByRoom:o("docx_editor.collab.room.memory.current","gauge","By","Bytes each room holds, labeled by room and kind. Recorded only with perRoomSeries.",["room","kind"]),migrations:o("docx_editor.collab.migrations","counter","{room}","Room migrations, by outcome.",["outcome"])}),h={s:"seconds",By:"bytes"};function y(t){let r=t.name.replace(/[^a-zA-Z0-9_]/g,"_"),a=t.unit==="1"?t.kind==="gauge"?"ratio":void 0:h[t.unit];return a&&!r.endsWith(`_${a}`)&&(r+=`_${a}`),t.kind==="counter"&&(r+="_total"),r}exports.a=b;exports.b=y;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
'use strict';var chunkLGNT4I5W_cjs=require('./chunk-LGNT4I5W.cjs');var f="text/plain; version=0.0.4; charset=utf-8";function b(r){return r.replace(/\\/g,"\\\\").replace(/\n/g,"\\n").replace(/"/g,'\\"')}function u(r,i){let t=Object.keys(r).sort().map(e=>`${e.replace(/[^a-zA-Z0-9_]/g,"_")}="${b(String(r[e]))}"`);return i&&t.push(i),t.length?`{${t.join(",")}}`:""}function p(r){return Object.keys(r).sort().map(i=>`${i}\0${String(r[i])}`).join("")}function l(r){return r===1/0?"+Inf":r===-1/0?"-Inf":Number.isNaN(r)?"NaN":String(r)}function y(){let r=new Map,i=(t,e)=>{let s=r.get(t.name);s||(s={definition:t,series:new Map},r.set(t.name,s));let o=p(e),n=s.series.get(o);return n||(n={labels:e,value:0},t.kind==="histogram"&&(n.buckets=new Array((t.buckets??[]).length).fill(0),n.sum=0),s.series.set(o,n)),n};return {name:"prometheus",metric(t){let{definition:e,value:s,attributes:o}=t,n=i(e,o);e.kind==="counter"?n.value+=Math.max(0,s):e.kind==="gauge"?n.value=s:(n.value+=1,n.sum+=s,(e.buckets??[]).forEach((a,c)=>{s<=a&&(n.buckets[c]+=1);}));},declare(t,e){i(t,e);},forget(t,e){r.get(t.name)?.series.delete(p(e));},metrics(){let t=[];for(let{definition:e,series:s}of r.values()){let o=chunkLGNT4I5W_cjs.b(e);t.push(`# HELP ${o} ${e.description.replace(/\n/g," ")}`),t.push(`# TYPE ${o} ${e.kind}`);for(let n of s.values()){if(e.kind!=="histogram"){t.push(`${o}${u(n.labels)} ${l(n.value)}`);continue}(e.buckets??[]).forEach((a,c)=>{let d=`le="${l(a)}"`;t.push(`${o}_bucket${u(n.labels,d)} ${n.buckets[c]}`);}),t.push(`${o}_bucket${u(n.labels,'le="+Inf"')} ${n.value}`),t.push(`${o}_sum${u(n.labels)} ${l(n.sum)}`),t.push(`${o}_count${u(n.labels)} ${n.value}`);}}return t.length?`${t.join(`
|
|
2
|
+
`)}
|
|
3
|
+
`:""},reset(){r.clear();}}}async function g(r,i){return (await Promise.all([r,...i.merge??[]].map(e=>e.metrics()))).filter(Boolean).join(`
|
|
4
|
+
`)}function $(r,i={}){return async(t,e)=>{let s;try{s=await g(r,i);}catch{e.statusCode=500,e.end("metrics unavailable");return}e.statusCode=200,e.setHeader("Content-Type",f),e.end(s);}}function x(r,i={}){return async()=>{try{return new Response(await g(r,i),{headers:{"Content-Type":f}})}catch{return new Response("metrics unavailable",{status:500})}}}exports.a=f;exports.b=y;exports.c=$;exports.d=x;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
function u(e,o){return {name:"callback",event:e,...o?{metric:o}:{}}}function n(e){let o=e,r=["operation","changeKind","formattingKind","cause","errorName","stage","part"].map(t=>o[t]).filter(t=>typeof t=="string");return r.length?` [${r.join(", ")}]`:""}function i(e){let o=e.repeated?` (and ${e.repeated} more)`:"";switch(e.kind){case "document.open":return e.outcome==="rejected"?`document refused: ${e.code}${n(e)}`:e.pagesBucket===void 0?`document opened: ${e.sizeBucket}, ${e.durationMs} ms`:`document opened: ${e.pagesBucket} pages, ${e.sizeBucket}, ${e.durationMs} ms`;case "edit.rejected":{let r=e.command?`${e.origin} ${e.command}`:e.origin;return `edit refused: ${e.code}${n(e)} (${r}, ${e.tracked?"tracked":"untracked"})${o}`}case "review.skipped":return `tracked changes skipped: ${e.code}${n(e)} x${e.count}`;case "font.failed":return `font substituted: ${e.code}${o}`;case "history":return `undo history: ${e.code}${o}`;case "custom-node":return `custom node payload unreadable: ${e.code}${o}`;case "collab.participants":return `collaboration: ${e.count} ${e.count===1?"person":"people"} in the room`;case "collab.status":{let r=e.code?`: ${e.code}`:"",t=e.connectMs!==void 0?` after ${e.connectMs} ms`:"";return `collaboration ${e.status}${r}${e.recovering?" (recovering)":""}${t}`}case "performance":{let r=[c("key presses and clicks",e.interaction),c("layout",e.layout),c("paint",e.paint)].filter(Boolean),t=e.pagesBucket===void 0?"":`, ${e.pagesBucket} pages`;return `performance over ${Math.round(e.windowMs/1e3)} s${t}: ${r.join("; ")}`}}}function c(e,o){return o?`${e} p50 ${o.p50Ms} ms, p95 ${o.p95Ms} ms, max ${o.maxMs} ms (x${o.count})`:""}function a(e){if(e.repeated!==void 0)return false;switch(e.kind){case "document.open":return e.outcome==="rejected";case "collab.participants":case "history":case "performance":return false;case "collab.status":return e.status==="error"&&e.code!=="collab.authentication-failed"&&e.code!=="collab.room-generation-changed";case "edit.rejected":return !s.has(e.code);case "font.failed":return e.code!=="font.missing";case "review.skipped":return e.code!=="review.stale-revision";default:return true}}var s=new Set(["edit.stale-target","edit.read-only","edit.protected-content","edit.refresh-in-progress","edit.collaboration-not-ready"]);function l(e={}){let o=e.console??console;return {name:"console",event(r){let t=[`[docx-editor] ${i(r)}`];r.hint&&t.push(` ${r.hint}`),r.docs&&t.push(` ${r.docs}`),(a(r)||r.kind==="performance"&&r.code!==void 0?o.warn:o.info).call(o,t.join(`
|
|
2
|
+
`));},...e.metrics?{metric(r){o.info(`[docx-editor] ${r.definition.name} ${r.value}`,r.attributes);}}:{}}}function p(){let e=[],o=[];return {name:"memory",events:e,metrics:o,event:r=>{e.push(r);},metric:r=>{o.push(r);},clear(){e.length=0,o.length=0;}}}export{u as a,i as b,a as c,l as d,p as e};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {c}from'./chunk-S7KBMROA.js';import {a}from'./chunk-73YEPWY5.js';import {createHmac}from'crypto';import {readCollaborationResourceUsage}from'@docx-editor.dev/pro/collaboration';import {diagnosticCodes}from'@docx-editor.dev/core';import {isCollaborationFailureCode}from'@docx-editor.dev/core/collaboration';import*as M from'yjs';function X(r){if(typeof r!="string"||r.length===0)throw new TypeError("hmacRoomLabel needs a non-empty secret, such as an environment variable.");let o=c=>`room-${createHmac("sha256",r).update(c).digest("hex").slice(0,16)}`;return C.add(o),o}var C=new WeakSet;function z(r,o){if(!r)return "permission-denied";let c=r,u=typeof r=="string"?r:typeof r=="object"?c.reason??c.code??(typeof c.message=="string"&&o.has(c.message.toLowerCase())?c.message:void 0):void 0;if(u===void 0)return "other";if(typeof u=="number")return Y[u]??"other";if(typeof u!="string")return "other";if(isCollaborationFailureCode(u))return u;let b=u.toLowerCase();return o.has(b)?b:"other"}var Y={4401:"unauthorized",4403:"forbidden"},F=diagnosticCodes().map(r=>r.replace(/^collab\./,"")).filter(isCollaborationFailureCode),$=["unauthorized","forbidden","permission-denied","unknown-room","rate-limited"];function Z(r){let o=c(r),c$1=new Set([...$,...r.reasons??[]].map(e=>e.toLowerCase())),u=r.measureState??true;for(let e of new Set([...c$1,...F,"other"]))o.declare(a.admissionRejections,{reason:e}),o.declare(a.messageRefusals,{reason:e});for(let e of ["success","failure"])o.declare(a.roomLoadDuration,{outcome:e}),o.declare(a.roomStoreDuration,{outcome:e});for(let e of ["migrated","unchanged","failed"])o.declare(a.migrations,{outcome:e});o.declare(a.updates),o.declare(a.updateBytes);let b=e=>{try{return z(r.reasonOf?.(e)??e,c$1)}catch{return "other"}},B=r.perRoomSeries===true;if(B&&r.roomLabel&&!C.has(r.roomLabel))throw new TypeError("perRoomSeries puts the room label into every series, so it accepts only the default label or hmacRoomLabel(secret). A custom roomLabel could put a room name in a metric.");for(let e of r.exporters)e.metric||console.warn(`[docx-editor telemetry] exporter "${e.name}" records no metrics, and room telemetry sends only metrics. Use otelExporter or prometheusRegistry on a server.`);let m=new Set,E=0,_=r.roomLabel??(()=>`room-${E+=1}`),f=()=>Date.now();function g(){let e=0,n=0,t=0;for(let a of m){let l=w(a);e+=a.connections,n+=l,t=Math.max(t,l);}o.metric(a.roomsActive,m.size),o.metric(a.connectionsActive,e),o.metric(a.participantsActive,n),o.metric(a.roomParticipantsMax,t);}function S(e,n){let t=e==="load"?a.roomLoadDuration:a.roomStoreDuration,a$1=globalThis.performance?.now()??f(),l=n?.pendingBytes??0,y=false;return i=>{y||(y=true,o.metric(t,G(a$1),{outcome:i}),i==="success"&&e==="store"&&n&&(n.pendingBytes=Math.max(0,n.pendingBytes-l)));}}async function x(e,n,t){let a=S(e,t);try{let l=await n();return a("success"),l}catch(l){throw a("failure"),l}}function O(e,n){try{j(e,n);}catch{e.changed=true;}}function j(e,n){if(e.changed||!e.sampled){e.changed=false,e.sampled=true,u&&(e.stateBytes=M.encodeStateAsUpdate(e.doc).byteLength);try{let t=readCollaborationResourceUsage(e.doc);e.blobBytes=t.blobBytes,e.nodes=t.nodes;let a={nodes:t.nodes/t.maxNodes,relationships:t.relationships/t.maxRelationships,parts:t.parts/t.maxParts,blobBytes:t.blobBytes/t.maxBlobBytes};e.limitRatio=Math.max(...Object.values(a)),e.ratios=a,e.nodeStates={live:t.nodes-t.tombstonedNodes,tombstoned:t.tombstonedNodes};}catch{}}for(let[t,a$1]of Object.entries(e.ratios??{}))o.metric(a.roomResourceUsage,a$1,{resource:t});for(let[t,a$1]of Object.entries(e.nodeStates??{}))o.metric(a.roomNodes,a$1,{state:t});if(o.metric(a.roomParticipants,w(e)),e.stateBytes!==null&&o.metric(a.roomMemory,e.stateBytes,{kind:"state"}),e.blobBytes!==null&&o.metric(a.roomMemory,e.blobBytes,{kind:"blobs"}),o.metric(a.roomMemory,e.pendingBytes,{kind:"pending_updates"}),o.metric(a.roomAge,(n-e.openedAt)/1e3),o.metric(a.roomIdle,(n-e.lastChange)/1e3),B){let t=e.handle.label;o.metric(a.roomParticipantsByRoom,w(e),{room:t});for(let[a$1,l]of A(e))o.metric(a.roomMemoryByRoom,l,{room:t,kind:a$1});}}function h(){let e={state:0,blobs:0,pending_updates:0};for(let n of m)e.state+=n.stateBytes??0,e.blobs+=n.blobBytes??0,e.pending_updates+=n.pendingBytes;for(let[n,t]of Object.entries(e))o.metric(a.roomsMemory,t,{kind:n});g();}function D(){let e=f();for(let n of m)O(n,e);h();}let v=false;async function H(){if(!v){v=true;try{let e=f();for(let n of [...m])m.has(n)&&O(n,e),await new Promise(t=>setTimeout(t,0));h();}finally{v=false;}}}h();let T=r.sampleInterval??6e4,k=T===false?null:setInterval(()=>{H();},T);return k?.unref?.(),{open(e,n={}){let t=f(),a$1=(d,p)=>{if(i.changed=true,i.loading>0)return;i.lastChange=f();let R=p?.source;R==="redis"||R==="local"&&p.skipStoreHooks===true||(i.pendingBytes+=d.byteLength,o.metric(a.updates,1),o.metric(a.updateBytes,d.byteLength));},l=d=>{let{added:p,removed:R}=d??{};(p?.length??0)+(R?.length??0)>0&&g();};e.on("update",a$1),n.awareness?.on("change",l);let y={label:_(n.name??""),async time(d,p){d==="load"&&(i.loading+=1);try{return await x(d,p,i)}finally{d==="load"&&(i.loading-=1);}},begin:d=>S(d,i),connected(){i.connections+=1,g();},disconnected(){i.connections=Math.max(0,i.connections-1),g();},close(){if(m.delete(i)){if(i.dispose(),B){let d=y.label;o.forget(a.roomParticipantsByRoom,{room:d});for(let[p]of A(i))o.forget(a.roomMemoryByRoom,{room:d,kind:p});}h();}}},i={handle:y,doc:e,awareness:n.awareness,openedAt:t,lastChange:t,connections:0,pendingBytes:0,changed:true,loading:0,sampled:false,stateBytes:null,blobBytes:null,nodes:null,limitRatio:null,dispose(){e.off("update",a$1),n.awareness?.off("change",l);}};return m.add(i),g(),y},rejected(e){o.metric(a.admissionRejections,1,{reason:b(e)});},refused(e){o.metric(a.messageRefusals,1,{reason:b(e)});},migrated(e){o.metric(a.migrations,1,{outcome:e});},time:(e,n)=>x(e,n),begin:e=>S(e),list(){let e=f();return [...m].map(n=>({room:n.handle.label,participants:w(n),connections:n.connections,stateBytes:n.stateBytes,blobBytes:n.blobBytes,pendingBytes:n.pendingBytes,nodes:n.nodes,limitRatio:n.limitRatio,ageSeconds:Math.round((e-n.openedAt)/1e3),idleSeconds:Math.round((e-n.lastChange)/1e3)}))},sample:D,flush:()=>o.flush(),async shutdown(){k&&clearInterval(k);for(let e of [...m])e.handle.close();await o.shutdown();}}}function A(r){return [["state",r.stateBytes??0],["blobs",r.blobBytes??0],["pending_updates",r.pendingBytes]]}function w(r){if(!r.awareness)return r.connections;try{return r.awareness.getStates().size}catch{return r.connections}}function G(r){return Math.max(0,((globalThis.performance?.now()??Date.now())-r)/1e3)}export{X as a,Z as b};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import {a as a$1}from'./chunk-73YEPWY5.js';import {b,a}from'./chunk-DTEVX2XS.js';var A=50,R="2.29.0";function M(o){let i=[...o.exporters],T=Object.freeze({...b(o.resource??{},"resource")}),d=[...o.metricLabels??[]],m=new Map,b$1=new Set;function y(e){if(d.length===0)return e;let r={...e};for(let t of d){let n=r[t];if(n===void 0)continue;let s=String(n),a=m.get(t);if(a||m.set(t,a=new Set),!a.has(s)){if(a.size>=A){r[t]="other";continue}a.add(s);}}return r}let f=false;function p(e,r){if(!b$1.has(r)){b$1.add(r);try{if(o.onExporterError){let t=o.onExporterError(e,r);t&&typeof t.then=="function"&&Promise.resolve(t).catch(()=>{});}else console.warn(`[docx-editor telemetry] exporter "${r}" failed`,e);}catch{}}}function c(e,r){try{let t=r();if(!t||typeof t.then!="function")return;Promise.resolve(t).then(void 0,n=>p(n,e.name));}catch(t){p(t,e.name);}}function v(){let e=o.consent??true;if(typeof e=="boolean")return e;try{return e()===!0}catch{return false}}function u(){return !f&&v()}let E=false,_=()=>E||globalThis.document?.visibilityState==="hidden";for(let e of i)c(e,()=>e.attach?.({consented:v,pageClosing:_}));async function g(e){await Promise.all(i.map(async r=>{try{await e(r);}catch(t){p(t,r.name);}}));}return {resource:T,consented:u,event(e){if(!u())return;let r=a(e);if("dropped"in r){this.metric(a$1.droppedEvents,1,{reason:r.dropped});return}for(let t of i)t.event&&c(t,()=>t.event(r.event));},metric(e,r,t={}){if(!u()||!Number.isFinite(r))return;let n={definition:e,value:r,attributes:y(b(t,e.name,[...e.labels,...d]))};for(let s of i)s.metric&&c(s,()=>s.metric(n));},forget(e,r){let t=b(r,e.name,e.labels);for(let n of i)n.forget&&c(n,()=>n.forget(e,t));},declare(e,r={}){if(!u())return;let t=y(b(r,e.name,[...e.labels,...d]));for(let n of i)n.declare&&c(n,()=>n.declare(e,t));},flush:()=>g(e=>e.flush?.()),setPageClosing(e){E=e;},async shutdown(){f||(f=true,await g(e=>e.shutdown?e.shutdown():e.flush?.()));}}}export{A as a,R as b,M as c};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkLGNT4I5W_cjs=require('./chunk-LGNT4I5W.cjs'),chunkLFQSY2TD_cjs=require('./chunk-LFQSY2TD.cjs');var A=50,R="2.29.0";function M(o){let i=[...o.exporters],T=Object.freeze({...chunkLFQSY2TD_cjs.b(o.resource??{},"resource")}),d=[...o.metricLabels??[]],m=new Map,b=new Set;function y(e){if(d.length===0)return e;let r={...e};for(let t of d){let n=r[t];if(n===void 0)continue;let s=String(n),a=m.get(t);if(a||m.set(t,a=new Set),!a.has(s)){if(a.size>=A){r[t]="other";continue}a.add(s);}}return r}let f=false;function p(e,r){if(!b.has(r)){b.add(r);try{if(o.onExporterError){let t=o.onExporterError(e,r);t&&typeof t.then=="function"&&Promise.resolve(t).catch(()=>{});}else console.warn(`[docx-editor telemetry] exporter "${r}" failed`,e);}catch{}}}function c(e,r){try{let t=r();if(!t||typeof t.then!="function")return;Promise.resolve(t).then(void 0,n=>p(n,e.name));}catch(t){p(t,e.name);}}function v(){let e=o.consent??true;if(typeof e=="boolean")return e;try{return e()===!0}catch{return false}}function u(){return !f&&v()}let E=false,_=()=>E||globalThis.document?.visibilityState==="hidden";for(let e of i)c(e,()=>e.attach?.({consented:v,pageClosing:_}));async function g(e){await Promise.all(i.map(async r=>{try{await e(r);}catch(t){p(t,r.name);}}));}return {resource:T,consented:u,event(e){if(!u())return;let r=chunkLFQSY2TD_cjs.a(e);if("dropped"in r){this.metric(chunkLGNT4I5W_cjs.a.droppedEvents,1,{reason:r.dropped});return}for(let t of i)t.event&&c(t,()=>t.event(r.event));},metric(e,r,t={}){if(!u()||!Number.isFinite(r))return;let n={definition:e,value:r,attributes:y(chunkLFQSY2TD_cjs.b(t,e.name,[...e.labels,...d]))};for(let s of i)s.metric&&c(s,()=>s.metric(n));},forget(e,r){let t=chunkLFQSY2TD_cjs.b(r,e.name,e.labels);for(let n of i)n.forget&&c(n,()=>n.forget(e,t));},declare(e,r={}){if(!u())return;let t=y(chunkLFQSY2TD_cjs.b(r,e.name,[...e.labels,...d]));for(let n of i)n.declare&&c(n,()=>n.declare(e,t));},flush:()=>g(e=>e.flush?.()),setPageClosing(e){E=e;},async shutdown(){f||(f=true,await g(e=>e.shutdown?e.shutdown():e.flush?.()));}}}exports.a=A;exports.b=R;exports.c=M;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';function u(e,o){return {name:"callback",event:e,...o?{metric:o}:{}}}function n(e){let o=e,r=["operation","changeKind","formattingKind","cause","errorName","stage","part"].map(t=>o[t]).filter(t=>typeof t=="string");return r.length?` [${r.join(", ")}]`:""}function i(e){let o=e.repeated?` (and ${e.repeated} more)`:"";switch(e.kind){case "document.open":return e.outcome==="rejected"?`document refused: ${e.code}${n(e)}`:e.pagesBucket===void 0?`document opened: ${e.sizeBucket}, ${e.durationMs} ms`:`document opened: ${e.pagesBucket} pages, ${e.sizeBucket}, ${e.durationMs} ms`;case "edit.rejected":{let r=e.command?`${e.origin} ${e.command}`:e.origin;return `edit refused: ${e.code}${n(e)} (${r}, ${e.tracked?"tracked":"untracked"})${o}`}case "review.skipped":return `tracked changes skipped: ${e.code}${n(e)} x${e.count}`;case "font.failed":return `font substituted: ${e.code}${o}`;case "history":return `undo history: ${e.code}${o}`;case "custom-node":return `custom node payload unreadable: ${e.code}${o}`;case "collab.participants":return `collaboration: ${e.count} ${e.count===1?"person":"people"} in the room`;case "collab.status":{let r=e.code?`: ${e.code}`:"",t=e.connectMs!==void 0?` after ${e.connectMs} ms`:"";return `collaboration ${e.status}${r}${e.recovering?" (recovering)":""}${t}`}case "performance":{let r=[c("key presses and clicks",e.interaction),c("layout",e.layout),c("paint",e.paint)].filter(Boolean),t=e.pagesBucket===void 0?"":`, ${e.pagesBucket} pages`;return `performance over ${Math.round(e.windowMs/1e3)} s${t}: ${r.join("; ")}`}}}function c(e,o){return o?`${e} p50 ${o.p50Ms} ms, p95 ${o.p95Ms} ms, max ${o.maxMs} ms (x${o.count})`:""}function a(e){if(e.repeated!==void 0)return false;switch(e.kind){case "document.open":return e.outcome==="rejected";case "collab.participants":case "history":case "performance":return false;case "collab.status":return e.status==="error"&&e.code!=="collab.authentication-failed"&&e.code!=="collab.room-generation-changed";case "edit.rejected":return !s.has(e.code);case "font.failed":return e.code!=="font.missing";case "review.skipped":return e.code!=="review.stale-revision";default:return true}}var s=new Set(["edit.stale-target","edit.read-only","edit.protected-content","edit.refresh-in-progress","edit.collaboration-not-ready"]);function l(e={}){let o=e.console??console;return {name:"console",event(r){let t=[`[docx-editor] ${i(r)}`];r.hint&&t.push(` ${r.hint}`),r.docs&&t.push(` ${r.docs}`),(a(r)||r.kind==="performance"&&r.code!==void 0?o.warn:o.info).call(o,t.join(`
|
|
2
|
+
`));},...e.metrics?{metric(r){o.info(`[docx-editor] ${r.definition.name} ${r.value}`,r.attributes);}}:{}}}function p(){let e=[],o=[];return {name:"memory",events:e,metrics:o,event:r=>{e.push(r);},metric:r=>{o.push(r);},clear(){e.length=0,o.length=0;}}}exports.a=u;exports.b=i;exports.c=a;exports.d=l;exports.e=p;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function n(){try{return process.env.NODE_ENV}catch{return}}exports.a=n;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';var chunkMJX3ECH3_cjs=require('../chunk-MJX3ECH3.cjs'),chunk7ZXJ6HP2_cjs=require('../chunk-7ZXJ6HP2.cjs');require('../chunk-U6ERFNUM.cjs'),require('../chunk-LGNT4I5W.cjs'),require('../chunk-LFQSY2TD.cjs'),require('../chunk-WGWKNKUT.cjs');var crypto=require('crypto');function U(a){if(typeof a!="string"||a.length===0)throw new TypeError("requireBearerToken needs a non-empty secret, such as METRICS_TOKEN.");let n=Buffer.from(`Bearer ${a}`);return c=>{let l=c.headers?.authorization,i=Buffer.from(typeof l=="string"?l:"");return i.length===n.length&&crypto.timingSafeEqual(i,n)}}function $(a,n={}){if(n.rooms&&!n.authorize)throw new TypeError("serveMetrics needs authorize when it serves rooms: the list is private.");let c=n.path??"/metrics",l=chunkMJX3ECH3_cjs.c(a,n.merge?{merge:n.merge}:{}),i=0;return async({request:u,response:f})=>{let g=(u.url??"").split("?")[0],w=n.rooms?.path;if(g!==c&&g!==w){await n.next?.({request:u,response:f});return}throw n.authorize&&!A(n.authorize,u)?(f.writeHead(403),f.end()):g===c?(n.sampleBeforeScrape&&Date.now()-i>=5e3&&(i=Date.now(),n.sampleBeforeScrape.sample()),await l(u,f)):(f.writeHead(200,{"Content-Type":"application/json"}),f.end(JSON.stringify(n.rooms.telemetry.list()))),null}}function I(a,n){let c=chunk7ZXJ6HP2_cjs.b(n),l=new Map,i=new Map,u=new Map,f=e=>typeof e.afterLoadDocument=="function",g=1+(a.extensions??[]).filter(e=>f(e)).length+(f(a)?1:0),w=e=>{let r=(u.get(e)??0)+1;u.set(e,r),!(r<g)&&(u.delete(e),y(i,e,"success"));},p=new Map,R=e=>typeof e.afterStoreDocument=="function",M=1+(a.extensions??[]).filter(e=>R(e)).length+(R(a)?1:0),D=e=>{let r=(p.get(e)??0)+1;p.set(e,r),!(r<M)&&(p.delete(e),y(m,e,"success"));},v=e=>{u.delete(e),y(i,e,"failure"),l.get(e)?.close(),l.delete(e);},m=new Map,h=new Map,P=(e,r)=>`${e}\0${r}`,y=(e,r,s)=>{e.get(r)?.(s),e.delete(r);},q={extensionName:"docx-editor-telemetry",priority:Number.MAX_SAFE_INTEGER,async onLoadDocument({documentName:e}){y(i,e,"failure"),i.set(e,c.begin("load"));},async afterLoadDocument({documentName:e,document:r}){l.get(e)?.close(),l.set(e,c.open(r,{name:e,awareness:r.awareness})),u.set(e,0),w(e);},async onStoreDocument({documentName:e}){m.delete(e),p.delete(e);let r=l.get(e);m.set(e,r?r.begin("store"):c.begin("store"));},async afterStoreDocument({documentName:e}){p.set(e,0),D(e);},async connected({documentName:e,socketId:r}){let s=l.get(e),o=P(r,e);if(!s)return;let t=h.get(o);t?t.count+=1:h.set(o,{room:s,count:1}),s.connected();},async onDisconnect({documentName:e,socketId:r}){let s=P(r,e),o=h.get(s);o&&(o.room.disconnected(),o.count-=1,o.count===0&&h.delete(s));},async afterUnloadDocument({documentName:e}){u.delete(e),p.delete(e),y(i,e,"failure"),m.delete(e),l.get(e)?.close(),l.delete(e);},async onDestroy(){await c.shutdown();}},T=e=>{let r=e,s={},o=(t,d,j)=>{let b=r[t];typeof b=="function"&&(s[t]=async S=>{let k;try{k=await b.call(e,S);}catch(O){throw d(O,S),O}return j?.(S),k});};return o("onConnect",t=>c.rejected(t)),o("onAuthenticate",t=>c.rejected(t)),o("onTokenSync",t=>c.rejected(t)),o("beforeHandleMessage",t=>c.refused(t)),o("onLoadDocument",(t,{documentName:d})=>y(i,d??"","failure")),o("afterLoadDocument",(t,{documentName:d})=>v(d??""),({documentName:t})=>w(t??"")),o("afterStoreDocument",(t,{documentName:d})=>{p.delete(d??""),y(m,d??"",L(t)?"success":"failure");},({documentName:t})=>D(t??"")),o("onStoreDocument",(t,{documentName:d})=>{L(t)?m.delete(d??""):y(m,d??"","failure");}),s},C=T(a),E=(a.extensions??[]).map(e=>{let r=T(e);return new Proxy(Object.create(Object.getPrototypeOf(e)),{get(s,o){if(Object.hasOwn(r,o))return r[o];let t=Reflect.get(e,o,e);return typeof t=="function"&&o!=="constructor"?t.bind(e):t},set(s,o,t){return Reflect.set(e,o,t,e)},has:(s,o)=>Reflect.has(e,o),ownKeys:()=>Reflect.ownKeys(e),getOwnPropertyDescriptor(s,o){let t=Reflect.getOwnPropertyDescriptor(e,o);return t?{...t,configurable:true}:void 0}})});return {config:{...a,...C,extensions:[q,...E]},rooms:c}}function A(a,n){try{return a(n)===!0}catch{return false}}function L(a){return a?.name==="SkipFurtherHooksError"}Object.defineProperty(exports,"hmacRoomLabel",{enumerable:true,get:function(){return chunk7ZXJ6HP2_cjs.a}});exports.requireBearerToken=U;exports.serveMetrics=$;exports.withCollaborationTelemetry=I;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hocuspocus: room telemetry in one call. It adds one extension that runs before all others
|
|
3
|
+
* and times each load and store from the first hook to the last, and it observes your hooks
|
|
4
|
+
* and the extensions you pass in `extensions`, so a refusal any of them throws is counted.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
import { onRequestPayload, ServerConfiguration } from '@hocuspocus/server';
|
|
9
|
+
import { MetricsHandlerOptions, PrometheusTextSource } from '../prometheus/index.cjs';
|
|
10
|
+
import { RoomTelemetry, RoomTelemetryOptions } from '../server/index.cjs';
|
|
11
|
+
export { AwarenessLike, RoomHandle, RoomOperation, RoomStats, SettleOperation, hmacRoomLabel } from '../server/index.cjs';
|
|
12
|
+
export { b as TelemetryExporter, T as TelemetryPipelineOptions } from '../pipeline-DbVW7S-K.cjs';
|
|
13
|
+
import 'yjs';
|
|
14
|
+
import '@docx-editor.dev/core';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Hocuspocus: room telemetry in one call. It adds one extension that runs before all others
|
|
18
|
+
* and times each load and store from the first hook to the last, and it observes your hooks
|
|
19
|
+
* and the extensions you pass in `extensions`, so a refusal any of them throws is counted.
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/** Options for {@link serveMetrics}. @public */
|
|
25
|
+
interface ServeMetricsOptions extends MetricsHandlerOptions {
|
|
26
|
+
/** The path Prometheus scrapes. Defaults to `/metrics`. */
|
|
27
|
+
readonly path?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Also serve `rooms.list()` as JSON at this path. It lists every room, so `authorize` is
|
|
30
|
+
* required with it.
|
|
31
|
+
*/
|
|
32
|
+
readonly rooms?: {
|
|
33
|
+
readonly telemetry: RoomTelemetry;
|
|
34
|
+
readonly path: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Return false to answer 403. Use {@link requireBearerToken} for a shared scrape token.
|
|
38
|
+
* Applies to both paths.
|
|
39
|
+
*/
|
|
40
|
+
readonly authorize?: (request: onRequestPayload['request']) => boolean;
|
|
41
|
+
/** Your own `onRequest`, called for every request this hook does not answer. */
|
|
42
|
+
readonly next?: (payload: onRequestPayload) => Promise<unknown>;
|
|
43
|
+
/**
|
|
44
|
+
* Sample this room telemetry before a scrape, for a server that sets `sampleInterval: false`.
|
|
45
|
+
* At most one sample is taken every 5 seconds, so several scrapers do not add extra samples.
|
|
46
|
+
*/
|
|
47
|
+
readonly sampleBeforeScrape?: RoomTelemetry;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* An `authorize` check for a shared token, sent as `Authorization: Bearer <token>`. The
|
|
51
|
+
* comparison takes the same time whatever the token, and an empty secret throws at startup
|
|
52
|
+
* rather than letting every request in.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* serveMetrics(metrics, { authorize: requireBearerToken(process.env.METRICS_TOKEN) });
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
declare function requireBearerToken(secret: string | undefined): (request: onRequestPayload['request']) => boolean;
|
|
62
|
+
/**
|
|
63
|
+
* An `onRequest` hook that serves Prometheus metrics from the Hocuspocus HTTP server itself,
|
|
64
|
+
* for a deployment without a separate web framework. Other requests fall through to the
|
|
65
|
+
* default handler.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* new Server({
|
|
70
|
+
* ...config,
|
|
71
|
+
* onRequest: serveMetrics(metrics, {
|
|
72
|
+
* rooms: { telemetry: rooms, path: '/rooms' },
|
|
73
|
+
* authorize: requireBearerToken(process.env.METRICS_TOKEN),
|
|
74
|
+
* }),
|
|
75
|
+
* });
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
declare function serveMetrics(registry: PrometheusTextSource, options?: ServeMetricsOptions): (payload: onRequestPayload) => Promise<void>;
|
|
81
|
+
/** What {@link withCollaborationTelemetry} returns. @public */
|
|
82
|
+
interface CollaborationTelemetry<C> {
|
|
83
|
+
/** Your configuration with observed hooks. Pass it to `new Server(config)`. */
|
|
84
|
+
readonly config: C;
|
|
85
|
+
/** The room telemetry, for `list()`, `sample()`, and `shutdown()`. */
|
|
86
|
+
readonly rooms: RoomTelemetry;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Add room telemetry to a Hocuspocus configuration.
|
|
90
|
+
*
|
|
91
|
+
* It records rooms, connections, the people in each room (from awareness), room memory and
|
|
92
|
+
* size, load and store times, and why connections and messages were refused. Your hooks and
|
|
93
|
+
* your `extensions` run exactly as before, with the same arguments, return values, and `this`;
|
|
94
|
+
* their errors are rethrown. Extensions added later with `server.configure` are not observed.
|
|
95
|
+
* Requires `@hocuspocus/server` 4.6 or later.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { Server } from '@hocuspocus/server';
|
|
100
|
+
* import { withCollaborationTelemetry } from '@docx-editor.dev/telemetry/hocuspocus';
|
|
101
|
+
* import { prometheusRegistry, metricsHandler } from '@docx-editor.dev/telemetry/prometheus';
|
|
102
|
+
*
|
|
103
|
+
* const metrics = prometheusRegistry();
|
|
104
|
+
* const { config, rooms } = withCollaborationTelemetry(
|
|
105
|
+
* { port: 1234, onAuthenticate, extensions: [new Database({ fetch, store })] },
|
|
106
|
+
* { exporters: [metrics] }
|
|
107
|
+
* );
|
|
108
|
+
* const server = new Server(config); // telemetry flushes when the server is destroyed
|
|
109
|
+
*
|
|
110
|
+
* app.get('/metrics', metricsHandler(metrics));
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @public
|
|
114
|
+
*/
|
|
115
|
+
declare function withCollaborationTelemetry<C extends Partial<ServerConfiguration>>(config: C, options: RoomTelemetryOptions): CollaborationTelemetry<C>;
|
|
116
|
+
|
|
117
|
+
export { MetricsHandlerOptions, PrometheusTextSource, RoomTelemetry, RoomTelemetryOptions, requireBearerToken, serveMetrics, withCollaborationTelemetry };
|
|
118
|
+
export type { CollaborationTelemetry, ServeMetricsOptions };
|