@powersync/service-core 1.10.1 → 1.11.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/CHANGELOG.md +17 -0
- package/dist/api/api-index.d.ts +1 -0
- package/dist/api/api-index.js +1 -0
- package/dist/api/api-index.js.map +1 -1
- package/dist/api/api-metrics.d.ts +11 -0
- package/dist/api/api-metrics.js +30 -0
- package/dist/api/api-metrics.js.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/metrics/MetricsEngine.d.ts +21 -0
- package/dist/metrics/MetricsEngine.js +79 -0
- package/dist/metrics/MetricsEngine.js.map +1 -0
- package/dist/metrics/metrics-index.d.ts +5 -0
- package/dist/metrics/metrics-index.js +6 -0
- package/dist/metrics/metrics-index.js.map +1 -0
- package/dist/metrics/metrics-interfaces.d.ts +36 -0
- package/dist/metrics/metrics-interfaces.js +6 -0
- package/dist/metrics/metrics-interfaces.js.map +1 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.d.ts +10 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js +51 -0
- package/dist/metrics/open-telemetry/OpenTelemetryMetricsFactory.js.map +1 -0
- package/dist/metrics/open-telemetry/util.d.ts +6 -0
- package/dist/metrics/open-telemetry/util.js +62 -0
- package/dist/metrics/open-telemetry/util.js.map +1 -0
- package/dist/metrics/register-metrics.d.ts +11 -0
- package/dist/metrics/register-metrics.js +44 -0
- package/dist/metrics/register-metrics.js.map +1 -0
- package/dist/replication/AbstractReplicationJob.d.ts +2 -0
- package/dist/replication/AbstractReplicationJob.js.map +1 -1
- package/dist/replication/AbstractReplicator.d.ts +3 -0
- package/dist/replication/AbstractReplicator.js +3 -0
- package/dist/replication/AbstractReplicator.js.map +1 -1
- package/dist/replication/ReplicationModule.d.ts +7 -0
- package/dist/replication/ReplicationModule.js +1 -0
- package/dist/replication/ReplicationModule.js.map +1 -1
- package/dist/replication/replication-index.d.ts +1 -0
- package/dist/replication/replication-index.js +1 -0
- package/dist/replication/replication-index.js.map +1 -1
- package/dist/replication/replication-metrics.d.ts +11 -0
- package/dist/replication/replication-metrics.js +39 -0
- package/dist/replication/replication-metrics.js.map +1 -0
- package/dist/routes/endpoints/socket-route.js +5 -5
- package/dist/routes/endpoints/socket-route.js.map +1 -1
- package/dist/routes/endpoints/sync-stream.js +6 -6
- package/dist/routes/endpoints/sync-stream.js.map +1 -1
- package/dist/storage/storage-index.d.ts +1 -0
- package/dist/storage/storage-index.js +1 -0
- package/dist/storage/storage-index.js.map +1 -1
- package/dist/storage/storage-metrics.d.ts +4 -0
- package/dist/storage/storage-metrics.js +56 -0
- package/dist/storage/storage-metrics.js.map +1 -0
- package/dist/sync/RequestTracker.d.ts +3 -0
- package/dist/sync/RequestTracker.js +8 -3
- package/dist/sync/RequestTracker.js.map +1 -1
- package/dist/sync/sync.js +8 -1
- package/dist/sync/sync.js.map +1 -1
- package/dist/system/ServiceContext.d.ts +3 -3
- package/dist/system/ServiceContext.js +7 -3
- package/dist/system/ServiceContext.js.map +1 -1
- package/dist/util/config/compound-config-collector.js +1 -0
- package/dist/util/config/compound-config-collector.js.map +1 -1
- package/dist/util/config/types.d.ts +1 -0
- package/dist/util/env.d.ts +0 -1
- package/dist/util/env.js +0 -4
- package/dist/util/env.js.map +1 -1
- package/package.json +7 -7
- package/src/api/api-index.ts +1 -0
- package/src/api/api-metrics.ts +35 -0
- package/src/index.ts +2 -2
- package/src/metrics/MetricsEngine.ts +98 -0
- package/src/metrics/metrics-index.ts +5 -0
- package/src/metrics/metrics-interfaces.ts +41 -0
- package/src/metrics/open-telemetry/OpenTelemetryMetricsFactory.ts +66 -0
- package/src/metrics/open-telemetry/util.ts +80 -0
- package/src/metrics/register-metrics.ts +56 -0
- package/src/replication/AbstractReplicationJob.ts +2 -0
- package/src/replication/AbstractReplicator.ts +7 -0
- package/src/replication/ReplicationModule.ts +10 -0
- package/src/replication/replication-index.ts +1 -0
- package/src/replication/replication-metrics.ts +45 -0
- package/src/routes/endpoints/socket-route.ts +6 -5
- package/src/routes/endpoints/sync-stream.ts +7 -6
- package/src/storage/storage-index.ts +1 -0
- package/src/storage/storage-metrics.ts +67 -0
- package/src/sync/RequestTracker.ts +9 -3
- package/src/sync/sync.ts +8 -1
- package/src/system/ServiceContext.ts +9 -4
- package/src/util/config/compound-config-collector.ts +1 -0
- package/src/util/config/types.ts +1 -0
- package/src/util/env.ts +0 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/metrics/Metrics.d.ts +0 -30
- package/dist/metrics/Metrics.js +0 -202
- package/dist/metrics/Metrics.js.map +0 -1
- package/src/metrics/Metrics.ts +0 -255
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { MetricsEngine } from '../metrics/MetricsEngine.js';
|
|
2
|
+
import { logger } from '@powersync/lib-services-framework';
|
|
3
|
+
import { BucketStorageFactory, StorageMetrics } from './BucketStorageFactory.js';
|
|
4
|
+
import { StorageMetric } from '@powersync/service-types';
|
|
5
|
+
|
|
6
|
+
export function createCoreStorageMetrics(engine: MetricsEngine): void {
|
|
7
|
+
engine.createObservableGauge({
|
|
8
|
+
name: StorageMetric.REPLICATION_SIZE_BYTES,
|
|
9
|
+
description: 'Size of current data stored in PowerSync',
|
|
10
|
+
unit: 'bytes'
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
engine.createObservableGauge({
|
|
14
|
+
name: StorageMetric.OPERATION_SIZE_BYTES,
|
|
15
|
+
description: 'Size of operations stored in PowerSync',
|
|
16
|
+
unit: 'bytes'
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
engine.createObservableGauge({
|
|
20
|
+
name: StorageMetric.PARAMETER_SIZE_BYTES,
|
|
21
|
+
description: 'Size of parameter data stored in PowerSync',
|
|
22
|
+
unit: 'bytes'
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function initializeCoreStorageMetrics(engine: MetricsEngine, storage: BucketStorageFactory): void {
|
|
27
|
+
const replication_storage_size_bytes = engine.getObservableGauge(StorageMetric.REPLICATION_SIZE_BYTES);
|
|
28
|
+
const operation_storage_size_bytes = engine.getObservableGauge(StorageMetric.OPERATION_SIZE_BYTES);
|
|
29
|
+
const parameter_storage_size_bytes = engine.getObservableGauge(StorageMetric.PARAMETER_SIZE_BYTES);
|
|
30
|
+
|
|
31
|
+
const MINIMUM_INTERVAL = 60_000;
|
|
32
|
+
|
|
33
|
+
let cachedRequest: Promise<StorageMetrics | null> | undefined = undefined;
|
|
34
|
+
let cacheTimestamp = 0;
|
|
35
|
+
|
|
36
|
+
const getMetrics = () => {
|
|
37
|
+
if (cachedRequest == null || Date.now() - cacheTimestamp > MINIMUM_INTERVAL) {
|
|
38
|
+
cachedRequest = storage.getStorageMetrics().catch((e) => {
|
|
39
|
+
logger.error(`Failed to get storage metrics`, e);
|
|
40
|
+
return null;
|
|
41
|
+
});
|
|
42
|
+
cacheTimestamp = Date.now();
|
|
43
|
+
}
|
|
44
|
+
return cachedRequest;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
replication_storage_size_bytes.setValueProvider(async () => {
|
|
48
|
+
const metrics = await getMetrics();
|
|
49
|
+
if (metrics) {
|
|
50
|
+
return metrics.replication_size_bytes;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
operation_storage_size_bytes.setValueProvider(async () => {
|
|
55
|
+
const metrics = await getMetrics();
|
|
56
|
+
if (metrics) {
|
|
57
|
+
return metrics.operations_size_bytes;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
parameter_storage_size_bytes.setValueProvider(async () => {
|
|
62
|
+
const metrics = await getMetrics();
|
|
63
|
+
if (metrics) {
|
|
64
|
+
return metrics.parameters_size_bytes;
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { MetricsEngine } from '../metrics/MetricsEngine.js';
|
|
2
|
+
|
|
3
|
+
import { APIMetric } from '@powersync/service-types';
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Record sync stats per request stream.
|
|
@@ -7,15 +9,19 @@ export class RequestTracker {
|
|
|
7
9
|
operationsSynced = 0;
|
|
8
10
|
dataSyncedBytes = 0;
|
|
9
11
|
|
|
12
|
+
constructor(private metrics: MetricsEngine) {
|
|
13
|
+
this.metrics = metrics;
|
|
14
|
+
}
|
|
15
|
+
|
|
10
16
|
addOperationsSynced(operations: number) {
|
|
11
17
|
this.operationsSynced += operations;
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
this.metrics.getCounter(APIMetric.OPERATIONS_SYNCED).add(operations);
|
|
14
20
|
}
|
|
15
21
|
|
|
16
22
|
addDataSynced(bytes: number) {
|
|
17
23
|
this.dataSyncedBytes += bytes;
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
this.metrics.getCounter(APIMetric.DATA_SYNCED_BYTES).add(bytes);
|
|
20
26
|
}
|
|
21
27
|
}
|
package/src/sync/sync.ts
CHANGED
|
@@ -180,7 +180,14 @@ async function* streamResponseInner(
|
|
|
180
180
|
function markOperationsSent(operations: number) {
|
|
181
181
|
syncedOperations += operations;
|
|
182
182
|
tracker.addOperationsSynced(operations);
|
|
183
|
-
|
|
183
|
+
// Disable interrupting checkpoints for now.
|
|
184
|
+
// There is a bug with interrupting checkpoints where:
|
|
185
|
+
// 1. User is in the middle of syncing a large batch of data (for example initial sync).
|
|
186
|
+
// 2. A new checkpoint comes in, which interrupts the batch.
|
|
187
|
+
// 3. However, the new checkpoint does not contain any new data for this connection, so nothing further is synced.
|
|
188
|
+
// This then causes the client to wait indefinitely for the remaining data or checkpoint_complete message. That is
|
|
189
|
+
// only resolved when a new checkpoint comes in that does have data for this connection, or the connection is restarted.
|
|
190
|
+
// maybeRaceForNewCheckpoint();
|
|
184
191
|
}
|
|
185
192
|
|
|
186
193
|
// This incrementally updates dataBuckets with each individual bucket position.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { LifeCycledSystem, MigrationManager, ServiceIdentifier, container } from '@powersync/lib-services-framework';
|
|
2
2
|
|
|
3
3
|
import { framework } from '../index.js';
|
|
4
|
-
import * as metrics from '../metrics/
|
|
4
|
+
import * as metrics from '../metrics/MetricsEngine.js';
|
|
5
5
|
import { PowerSyncMigrationManager } from '../migrations/PowerSyncMigrationManager.js';
|
|
6
6
|
import * as replication from '../replication/replication-index.js';
|
|
7
7
|
import * as routes from '../routes/routes-index.js';
|
|
@@ -12,7 +12,7 @@ import { SyncContext } from '../sync/SyncContext.js';
|
|
|
12
12
|
export interface ServiceContext {
|
|
13
13
|
configuration: utils.ResolvedPowerSyncConfig;
|
|
14
14
|
lifeCycleEngine: LifeCycledSystem;
|
|
15
|
-
|
|
15
|
+
metricsEngine: metrics.MetricsEngine;
|
|
16
16
|
replicationEngine: replication.ReplicationEngine | null;
|
|
17
17
|
routerEngine: routes.RouterEngine | null;
|
|
18
18
|
storageEngine: storage.StorageEngine;
|
|
@@ -37,6 +37,11 @@ export class ServiceContextContainer implements ServiceContext {
|
|
|
37
37
|
configuration
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
+
this.lifeCycleEngine.withLifecycle(this.storageEngine, {
|
|
41
|
+
start: (storageEngine) => storageEngine.start(),
|
|
42
|
+
stop: (storageEngine) => storageEngine.shutDown()
|
|
43
|
+
});
|
|
44
|
+
|
|
40
45
|
this.syncContext = new SyncContext({
|
|
41
46
|
maxDataFetchConcurrency: configuration.api_parameters.max_data_fetch_concurrency,
|
|
42
47
|
maxBuckets: configuration.api_parameters.max_buckets_per_connection,
|
|
@@ -65,8 +70,8 @@ export class ServiceContextContainer implements ServiceContext {
|
|
|
65
70
|
return container.getOptional(routes.RouterEngine);
|
|
66
71
|
}
|
|
67
72
|
|
|
68
|
-
get
|
|
69
|
-
return container.
|
|
73
|
+
get metricsEngine(): metrics.MetricsEngine {
|
|
74
|
+
return container.getImplementation(metrics.MetricsEngine);
|
|
70
75
|
}
|
|
71
76
|
|
|
72
77
|
get migrations(): PowerSyncMigrationManager {
|
|
@@ -154,6 +154,7 @@ export class CompoundConfigCollector {
|
|
|
154
154
|
metadata: baseConfig.metadata ?? {},
|
|
155
155
|
migrations: baseConfig.migrations,
|
|
156
156
|
telemetry: {
|
|
157
|
+
prometheus_port: baseConfig.telemetry?.prometheus_port,
|
|
157
158
|
disable_telemetry_sharing: baseConfig.telemetry?.disable_telemetry_sharing ?? false,
|
|
158
159
|
internal_service_endpoint:
|
|
159
160
|
baseConfig.telemetry?.internal_service_endpoint ?? 'https://pulse.journeyapps.com/v1/metrics'
|
package/src/util/config/types.ts
CHANGED
package/src/util/env.ts
CHANGED
|
@@ -19,10 +19,6 @@ export const env = utils.collectEnvironmentVariables({
|
|
|
19
19
|
* Runner to be started in this process
|
|
20
20
|
*/
|
|
21
21
|
PS_RUNNER_TYPE: utils.type.string.default(ServiceRunner.UNIFIED),
|
|
22
|
-
/**
|
|
23
|
-
* Port for metrics
|
|
24
|
-
*/
|
|
25
|
-
METRICS_PORT: utils.type.number.optional(),
|
|
26
22
|
|
|
27
23
|
NODE_ENV: utils.type.string.optional()
|
|
28
24
|
});
|