mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
OpenTelemetry support (#9584)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Vendored
+2
-1
@@ -202,8 +202,9 @@
|
||||
// "WORKSPACE_LIMIT_PER_USER": "1",
|
||||
"MINIO_ACCESS_KEY": "minioadmin",
|
||||
"MINIO_SECRET_KEY": "minioadmin",
|
||||
"MINIO_ENDPOINT": "localhost"
|
||||
"MINIO_ENDPOINT": "localhost",
|
||||
// "DISABLE_SIGNUP": "true",
|
||||
"OTLP_ENDPOINT": "http://huly.local:4318/v1/traces"
|
||||
},
|
||||
"runtimeVersion": "20",
|
||||
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
|
||||
|
||||
Generated
+1434
-6
File diff suppressed because it is too large
Load Diff
+33
-1
@@ -160,6 +160,7 @@ services:
|
||||
- ACCOUNTS_URL=http://huly.local:3000
|
||||
- BRANDING_PATH=/var/cfg/branding.json
|
||||
# - DISABLE_SIGNUP=true
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
stats:
|
||||
image: hardcoreeng/stats
|
||||
@@ -170,6 +171,7 @@ services:
|
||||
environment:
|
||||
- PORT=4900
|
||||
- SERVER_SECRET=secret
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
workspace_cockroach:
|
||||
image: hardcoreeng/workspace
|
||||
@@ -198,6 +200,7 @@ services:
|
||||
- BACKUP_BUCKET=${BACKUP_BUCKET_NAME}
|
||||
- MAIL_URL=
|
||||
# - INIT_WORKSPACE=staging-dev
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
collaborator:
|
||||
image: hardcoreeng/collaborator
|
||||
@@ -215,6 +218,7 @@ services:
|
||||
- ACCOUNTS_URL=http://huly.local:3000
|
||||
- STORAGE_CONFIG=${STORAGE_CONFIG}
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
front:
|
||||
image: hardcoreeng/front
|
||||
@@ -246,7 +250,7 @@ services:
|
||||
- GITHUB_URL=http://huly.local:3500
|
||||
- PRINT_URL=http://huly.local:4005
|
||||
- SIGN_URL=http://huly.local:4006
|
||||
# - ANALYTICS_COLLECTOR_URL=http://huly.local:4017
|
||||
# - ANALYTICS_COLLECTOR_URL=http://huly.local:4017
|
||||
- DESKTOP_UPDATES_URL=https://dist.huly.io
|
||||
- DESKTOP_UPDATES_CHANNEL=dev
|
||||
- BRANDING_URL=http://huly.local:8087/branding.json
|
||||
@@ -255,6 +259,7 @@ services:
|
||||
- BACKUP_URL=http://huly.local:4039/api/backup,
|
||||
- EXCLUDED_APPLICATIONS_FOR_ANONYMOUS=["chunter", "notification"]
|
||||
# - DISABLE_SIGNUP=true
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
transactor_cockroach:
|
||||
image: hardcoreeng/transactor
|
||||
@@ -296,6 +301,7 @@ services:
|
||||
- RATE_LIMIT_WINDOW=30000
|
||||
- FILES_URL=http://huly.local:4030/blob/:workspace/:blobId/:filename
|
||||
- COMMUNICATION_API_ENABLED=true
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
rekoni:
|
||||
image: hardcoreeng/rekoni-service
|
||||
@@ -306,6 +312,7 @@ services:
|
||||
- 4004:4004
|
||||
environment:
|
||||
- STATS_URL=http://huly.local:4901
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
fulltext_cockroach:
|
||||
image: hardcoreeng/fulltext
|
||||
extra_hosts:
|
||||
@@ -332,6 +339,7 @@ services:
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- REKONI_URL=http://huly.local:4004
|
||||
- ACCOUNTS_URL=http://huly.local:3000
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
print:
|
||||
image: hardcoreeng/print
|
||||
extra_hosts:
|
||||
@@ -346,6 +354,7 @@ services:
|
||||
- STORAGE_CONFIG=${STORAGE_CONFIG}
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- ACCOUNTS_URL=http://huly.local:3000
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
sign:
|
||||
image: hardcoreeng/sign
|
||||
extra_hosts:
|
||||
@@ -368,6 +377,7 @@ services:
|
||||
- SERVICE_ID=sign-service
|
||||
- BRANDING_PATH=/var/cfg/branding.json
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
# aiBot:
|
||||
# image: hardcoreeng/ai-bot
|
||||
# ports:
|
||||
@@ -418,6 +428,7 @@ services:
|
||||
- SECRET=secret
|
||||
- SERVICE_ID=msg2file-service
|
||||
- STORAGE_CONFIG=${STORAGE_CONFIG}
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
export:
|
||||
image: hardcoreeng/export
|
||||
extra_hosts:
|
||||
@@ -435,6 +446,7 @@ services:
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- STORAGE_CONFIG=${STORAGE_CONFIG}
|
||||
- ACCOUNTS_URL=http://huly.local:3000
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
datalake:
|
||||
image: hardcoreeng/datalake
|
||||
extra_hosts:
|
||||
@@ -459,6 +471,7 @@ services:
|
||||
- BUCKETS=blobs,eu|http://minio:9000?accessKey=minioadmin&secretKey=minioadmin
|
||||
- REGION=cockroach
|
||||
- QUEUE_CONFIG=${QUEUE_CONFIG}
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
hulykvs:
|
||||
image: hardcoreeng/hulykvs
|
||||
@@ -511,6 +524,7 @@ services:
|
||||
- INTERVAL=60
|
||||
- STORAGE=minio|minio?accessKey=minioadmin&secretKey=minioadmin
|
||||
- WORKSPACE_STORAGE=${STORAGE_CONFIG}
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
backup-api:
|
||||
image: hardcoreeng/backup-api
|
||||
@@ -532,6 +546,23 @@ services:
|
||||
- STATS_URL=http://huly.local:4900
|
||||
- BUCKET_NAME=backups
|
||||
- STORAGE=minio|minio?accessKey=minioadmin&secretKey=minioadmin
|
||||
- OTEL_EXPORTER_OTLP_ENDPOINT=http://jaeger:4318/v1/traces
|
||||
restart: unless-stopped
|
||||
jaeger:
|
||||
image: jaegertracing/all-in-one:latest
|
||||
extra_hosts:
|
||||
- 'huly.local:host-gateway'
|
||||
ports:
|
||||
- 16686:16686 # Web UI
|
||||
- 4317:4317
|
||||
- 4318:4318
|
||||
volumes:
|
||||
- telemetry:/badger
|
||||
environment:
|
||||
- COLLECTOR_OTLP_ENABLED=true
|
||||
- SPAN_STORAGE_TYPE=badger
|
||||
- BADGER_DIRECTORY_VALUE=/badger/data
|
||||
- BADGER_DIRECTORY_KEY=/badger/key
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
db:
|
||||
@@ -540,3 +571,4 @@ volumes:
|
||||
elastic:
|
||||
cockroach_db:
|
||||
redpanda:
|
||||
telemetry:
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -41,6 +41,7 @@
|
||||
"@hcengineering/platform": "^0.6.11",
|
||||
"@hcengineering/core": "^0.6.32",
|
||||
"@hcengineering/analytics": "^0.6.0",
|
||||
"@hcengineering/measurements-otlp": "^0.6.0",
|
||||
"winston": "^3.11.0",
|
||||
"winston-daily-rotate-file": "^5.0.0",
|
||||
"@sentry/node": "^9.22.0"
|
||||
|
||||
@@ -7,6 +7,7 @@ import { SentryAnalyticProvider } from './sentry'
|
||||
|
||||
export * from './logging'
|
||||
export * from './sentry'
|
||||
export * from '@hcengineering/measurements-otlp'
|
||||
|
||||
export function configureAnalytics (sentryDSN: string | undefined, config?: Record<string, any>): void {
|
||||
const providers: AnalyticProvider[] = []
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"dependencies": {
|
||||
"@hcengineering/platform": "^0.6.11",
|
||||
"@hcengineering/analytics": "^0.6.0",
|
||||
"@hcengineering/measurements": "^0.6.0",
|
||||
"fast-equals": "^5.2.2"
|
||||
},
|
||||
"repository": "https://github.com/hcengineering/platform",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MeasureMetricsContext } from '../measurements'
|
||||
import { MeasureMetricsContext } from '@hcengineering/measurements'
|
||||
|
||||
describe('context tests', () => {
|
||||
it('check withLog proper catch', async () => {
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
} from './classes'
|
||||
import core from './component'
|
||||
import { Hierarchy } from './hierarchy'
|
||||
import { type MeasureContext, MeasureMetricsContext } from './measurements'
|
||||
import { type MeasureContext, MeasureMetricsContext } from '@hcengineering/measurements'
|
||||
import { ModelDb } from './memdb'
|
||||
import type {
|
||||
DocumentQuery,
|
||||
|
||||
@@ -26,7 +26,7 @@ export {
|
||||
configUserAccountUuid
|
||||
} from './component'
|
||||
export * from './hierarchy'
|
||||
export * from './measurements'
|
||||
export * from '@hcengineering/measurements'
|
||||
export * from './memdb'
|
||||
export * from './objvalue'
|
||||
export * from './operations'
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './context'
|
||||
export * from './metrics'
|
||||
export * from './types'
|
||||
@@ -14,7 +14,7 @@
|
||||
//
|
||||
|
||||
import type { Account, AccountRole, AccountUuid, Doc, Domain, PersonId, Ref } from './classes'
|
||||
import { type MeasureContext } from './measurements'
|
||||
import { type MeasureContext } from '@hcengineering/measurements'
|
||||
import { type DocumentQuery, type FindOptions } from './storage'
|
||||
import type { DocumentUpdate, Tx } from './tx'
|
||||
import { type WorkspaceIds } from './utils'
|
||||
|
||||
@@ -968,13 +968,4 @@ export function unique<T> (arr: T[]): T[] {
|
||||
export function uniqueNotEmpty<T extends NonNullable<unknown>> (arr: Array<T | undefined | null>): T[] {
|
||||
return unique(arr).filter(notEmpty)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a current performance timestamp
|
||||
*/
|
||||
export const platformNow: () => number = () => performance.now()
|
||||
|
||||
/**
|
||||
* Return a diff with previous performance snapshot with 2 digits after . max.
|
||||
*/
|
||||
export const platformNowDiff = (old: number): number => Math.round((performance.now() - old) * 100) / 100
|
||||
export { platformNow, platformNowDiff } from '@hcengineering/measurements'
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "@hcengineering/measurements-otlp",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"lib/**/*",
|
||||
"types/**/*",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"format": "format src",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"simplytyped": "^3.3.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.8.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hcengineering/measurements": "^0.6.0",
|
||||
"@sentry/node": "^9.22.0",
|
||||
"@opentelemetry/sdk-node": "^0.203.0",
|
||||
"@opentelemetry/sdk-logs": "^0.203.0",
|
||||
"@opentelemetry/auto-instrumentations-node": "^0.62.0",
|
||||
"@opentelemetry/resources": "^2.0.1",
|
||||
"@opentelemetry/sdk-trace-node": "^2.0.1",
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/core": "^2.0.1",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.203.0",
|
||||
"@opentelemetry/exporter-logs-otlp-http": "^0.203.0",
|
||||
"@opentelemetry/otlp-exporter-base": "^0.203.0",
|
||||
"@opentelemetry/id-generator-aws-xray": "^2.0.0",
|
||||
"@opentelemetry/exporter-metrics-otlp-http": "^0.203.0"
|
||||
},
|
||||
"repository": "https://github.com/hcengineering/platform",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './telemetry'
|
||||
@@ -0,0 +1,355 @@
|
||||
import {
|
||||
childMetrics,
|
||||
consoleLogger,
|
||||
MeasureContext,
|
||||
MeasureMetricsContext,
|
||||
newMetrics,
|
||||
noParamsLogger,
|
||||
nullPromise,
|
||||
platformNow,
|
||||
platformNowDiff,
|
||||
updateMeasure,
|
||||
type FullParamsType,
|
||||
type MeasureLogger,
|
||||
type Metrics,
|
||||
type ParamsType
|
||||
} from '@hcengineering/measurements'
|
||||
import { context, Span, trace, type Context, type Tracer } from '@opentelemetry/api'
|
||||
import { suppressTracing } from '@opentelemetry/core'
|
||||
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node'
|
||||
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'
|
||||
import { AWSXRayIdGenerator } from '@opentelemetry/id-generator-aws-xray'
|
||||
import { CompressionAlgorithm } from '@opentelemetry/otlp-exporter-base'
|
||||
import { NodeSDK } from '@opentelemetry/sdk-node'
|
||||
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-node'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class OpenTelemetryMetricsContext implements MeasureContext {
|
||||
private readonly name: string
|
||||
private readonly params: ParamsType
|
||||
|
||||
private readonly fullParams: FullParamsType | (() => FullParamsType) = {}
|
||||
logger: MeasureLogger
|
||||
metrics: Metrics
|
||||
id?: string
|
||||
|
||||
st = platformNow()
|
||||
contextData: object = {}
|
||||
private done (value?: number, override?: boolean): void {
|
||||
updateMeasure(this.metrics, this.st, this.params, this.fullParams, (spend) => {}, value, override)
|
||||
this.span?.end()
|
||||
}
|
||||
|
||||
constructor (
|
||||
name: string,
|
||||
readonly tracer: Tracer,
|
||||
readonly context: Context,
|
||||
readonly span: Span | undefined,
|
||||
params: ParamsType,
|
||||
fullParams: FullParamsType | (() => FullParamsType) = {},
|
||||
metrics: Metrics = newMetrics(),
|
||||
logger?: MeasureLogger,
|
||||
readonly parent?: MeasureContext,
|
||||
readonly logParams?: ParamsType
|
||||
) {
|
||||
this.name = name
|
||||
this.params = params
|
||||
this.fullParams = fullParams
|
||||
this.metrics = metrics
|
||||
this.metrics.namedParams = this.metrics.namedParams ?? {}
|
||||
for (const [k, v] of Object.entries(params)) {
|
||||
if (this.metrics.namedParams[k] !== v) {
|
||||
this.metrics.namedParams[k] = v
|
||||
} else {
|
||||
this.metrics.namedParams[k] = '*'
|
||||
}
|
||||
}
|
||||
|
||||
this.logger = logger ?? (this.logParams != null ? consoleLogger(this.logParams ?? {}) : noParamsLogger)
|
||||
}
|
||||
|
||||
measure (name: string, value: number, override?: boolean): void {
|
||||
this.span?.addEvent(name, value)
|
||||
}
|
||||
|
||||
newChild (
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
fullParams?: FullParamsType | (() => FullParamsType),
|
||||
logger?: MeasureLogger,
|
||||
useContextParent: boolean = true
|
||||
): MeasureContext {
|
||||
const childContext = useContextParent
|
||||
? context.active()
|
||||
: this.span !== undefined
|
||||
? trace.setSpan(this.context, this.span)
|
||||
: this.context
|
||||
const span = this.tracer.startSpan(name, undefined, childContext)
|
||||
|
||||
const spanParams = [...Object.entries(params)]
|
||||
for (const [k, v] of spanParams) {
|
||||
span?.setAttribute(k, v as any)
|
||||
}
|
||||
|
||||
const result = new OpenTelemetryMetricsContext(
|
||||
name,
|
||||
this.tracer,
|
||||
childContext,
|
||||
span,
|
||||
params,
|
||||
fullParams ?? {},
|
||||
childMetrics(this.metrics, [name]),
|
||||
logger ?? this.logger,
|
||||
this,
|
||||
this.logParams
|
||||
)
|
||||
result.id = this.id
|
||||
result.contextData = this.contextData
|
||||
return result
|
||||
}
|
||||
|
||||
with<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType | (() => FullParamsType)
|
||||
): Promise<T> {
|
||||
const c = this.newChild(name, params, fullParams, this.logger, false)
|
||||
let needFinally = true
|
||||
try {
|
||||
const _context = (c as OpenTelemetryMetricsContext).context ?? context.active()
|
||||
|
||||
const span = (c as OpenTelemetryMetricsContext).span
|
||||
|
||||
const value = context.with(_context, () => op(c))
|
||||
if (value instanceof Promise) {
|
||||
needFinally = false
|
||||
if (span !== undefined) {
|
||||
void value.catch((err) => {
|
||||
span?.recordException(err)
|
||||
})
|
||||
}
|
||||
return value.finally(() => {
|
||||
if (span !== undefined) {
|
||||
const fParams = typeof fullParams === 'function' ? fullParams() : fullParams
|
||||
const spanParams = [...Object.entries(fParams ?? {})]
|
||||
for (const [k, v] of spanParams) {
|
||||
span?.setAttribute(k, v)
|
||||
}
|
||||
}
|
||||
c.end()
|
||||
})
|
||||
} else {
|
||||
if (value == null) {
|
||||
return nullPromise as Promise<T>
|
||||
}
|
||||
return Promise.resolve(value)
|
||||
}
|
||||
} finally {
|
||||
if (needFinally) {
|
||||
c.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
withoutTracing<T>(op: () => T): T {
|
||||
return context.with(suppressTracing(this.context), op)
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T,
|
||||
fullParams?: ParamsType | (() => FullParamsType)
|
||||
): T {
|
||||
const c = this.newChild(name, params, fullParams, this.logger, false)
|
||||
const _context = (c as OpenTelemetryMetricsContext).context ?? context.active()
|
||||
|
||||
const span = (c as OpenTelemetryMetricsContext).span
|
||||
|
||||
try {
|
||||
return context.with(_context, () => op(c))
|
||||
} catch (err: any) {
|
||||
if (span !== undefined) {
|
||||
span.recordException(err)
|
||||
}
|
||||
throw err
|
||||
} finally {
|
||||
c.end()
|
||||
}
|
||||
}
|
||||
|
||||
withLog<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
op: (ctx: MeasureContext) => T | Promise<T>,
|
||||
fullParams?: ParamsType
|
||||
): Promise<T> {
|
||||
const st = platformNow()
|
||||
const r = this.with(name, params, op, fullParams)
|
||||
r.catch(() => {
|
||||
// Ignore logging errors to prevent unhandled rejections
|
||||
}).finally(() => {
|
||||
this.logger.logOperation(name, platformNowDiff(st), { ...params, ...fullParams })
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
error (message: string, args?: Record<string, any>): void {
|
||||
this.logger.error(message, { ...this.params, ...args, ...(this.logParams ?? {}) })
|
||||
}
|
||||
|
||||
info (message: string, args?: Record<string, any>): void {
|
||||
this.logger.info(message, { ...this.params, ...args, ...(this.logParams ?? {}) })
|
||||
}
|
||||
|
||||
warn (message: string, args?: Record<string, any>): void {
|
||||
this.logger.warn(message, { ...this.params, ...args, ...(this.logParams ?? {}) })
|
||||
}
|
||||
|
||||
end (): void {
|
||||
this.done()
|
||||
}
|
||||
|
||||
getParams (): ParamsType {
|
||||
return this.params
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse W3C baggage header format to Record<string, string>
|
||||
*
|
||||
* W3C baggage format: "key1=value1,key2=value2;property=value,key3=value3"
|
||||
* Returns only the key-value pairs, ignoring properties
|
||||
*/
|
||||
function parseBaggage (baggageHeader?: string): Record<string, string> {
|
||||
if (baggageHeader == null || typeof baggageHeader !== 'string') {
|
||||
return {}
|
||||
}
|
||||
|
||||
const result: Record<string, string> = {}
|
||||
|
||||
// Split by comma to get individual baggage members
|
||||
const members = baggageHeader.split(',')
|
||||
|
||||
for (const member of members) {
|
||||
const trimmedMember = member.trim()
|
||||
if (trimmedMember === '') continue
|
||||
|
||||
// Split by semicolon to separate key=value from properties
|
||||
const parts = trimmedMember.split(';')
|
||||
const keyValuePart = parts[0]?.trim()
|
||||
|
||||
if (keyValuePart == null) continue
|
||||
|
||||
// Split by equals to get key and value
|
||||
const equalIndex = keyValuePart.indexOf('=')
|
||||
if (equalIndex === -1) continue
|
||||
|
||||
const key = keyValuePart.substring(0, equalIndex).trim()
|
||||
const value = keyValuePart.substring(equalIndex + 1).trim()
|
||||
|
||||
if (key != null) {
|
||||
// URL decode the key and value
|
||||
try {
|
||||
const decodedKey = decodeURIComponent(key)
|
||||
const decodedValue = decodeURIComponent(value)
|
||||
result[decodedKey] = decodedValue
|
||||
} catch (error) {
|
||||
// If decoding fails, use the original values
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export function createOpenTelemetryMetricsContext (
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
fullParams: FullParamsType | (() => FullParamsType) = {},
|
||||
metrics: Metrics = newMetrics(),
|
||||
logger?: MeasureLogger
|
||||
): MeasureContext {
|
||||
let url = process.env.OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ?? process.env.OTEL_EXPORTER_OTLP_ENDPOINT
|
||||
|
||||
if (url !== undefined && !url.endsWith('/v1/traces')) {
|
||||
if (url.endsWith('/')) {
|
||||
url += 'v1/traces'
|
||||
} else {
|
||||
url += '/v1/traces'
|
||||
}
|
||||
}
|
||||
|
||||
if (url === undefined) {
|
||||
console.warn('OTEL_EXPORTER_OTLP_TRACES_ENDPOINT is not set, OpenTelemetry metrics will not be sent')
|
||||
return new MeasureMetricsContext(name, params, fullParams, metrics, logger)
|
||||
}
|
||||
|
||||
const headers: Record<string, string> = parseBaggage(process.env.OTEL_EXPORTER_OTLP_HEADERS) ?? {}
|
||||
|
||||
if (process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS !== undefined) {
|
||||
const extraHeaders = parseBaggage(process.env.OTEL_EXPORTER_OTLP_TRACES_HEADERS)
|
||||
for (const [key, value] of Object.entries(extraHeaders)) {
|
||||
headers[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
const exporter = new OTLPTraceExporter({
|
||||
url,
|
||||
headers,
|
||||
compression:
|
||||
(process.env.OTEL_EXPORTER_OTLP_COMPRESSION as CompressionAlgorithm) ??
|
||||
(process.env.OTEL_EXPORTER_OTLP_TRACES_COMPRESSION as CompressionAlgorithm) ??
|
||||
CompressionAlgorithm.GZIP,
|
||||
keepAlive: true
|
||||
})
|
||||
|
||||
const bsp = new BatchSpanProcessor(exporter, {
|
||||
maxExportBatchSize: parseInt(process.env.OTEL_EXPORTER_OTLP_TRACES_MAX_EXPORT_BATCH_SIZE ?? '1000'),
|
||||
maxQueueSize: parseInt(process.env.OTEL_EXPORTER_OTLP_TRACES_MAX_QUEUE_SIZE ?? '1000')
|
||||
})
|
||||
|
||||
const sdk = new NodeSDK({
|
||||
spanProcessor: bsp,
|
||||
serviceName: name,
|
||||
traceExporter: exporter,
|
||||
instrumentations: [getNodeAutoInstrumentations()],
|
||||
idGenerator: new AWSXRayIdGenerator()
|
||||
})
|
||||
|
||||
sdk.start()
|
||||
|
||||
// Graceful shutdown
|
||||
process.on('SIGTERM', () => {
|
||||
sdk
|
||||
.shutdown()
|
||||
.then(() => {
|
||||
console.log('Tracing terminated')
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log('Error terminating tracing', error)
|
||||
})
|
||||
.finally(() => process.exit(0))
|
||||
})
|
||||
|
||||
const tracer = trace.getTracer(name)
|
||||
const currentConext = context.active()
|
||||
const ctx = new OpenTelemetryMetricsContext(
|
||||
name,
|
||||
tracer,
|
||||
currentConext,
|
||||
undefined,
|
||||
params,
|
||||
fullParams,
|
||||
metrics,
|
||||
logger
|
||||
)
|
||||
ctx.info('Using open telemetry metrics context', {
|
||||
endpoint: url
|
||||
})
|
||||
return ctx
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "lib", "dist", "types", "bundle"]
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
extends: ['./node_modules/@hcengineering/platform-rig/profiles/default/eslint.config.json'],
|
||||
parserOptions: {
|
||||
tsconfigRootDir: __dirname,
|
||||
project: './tsconfig.json'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
*
|
||||
!/lib/**
|
||||
!CHANGELOG.md
|
||||
/lib/**/__tests__/
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
|
||||
"rigPackageName": "@hcengineering/platform-rig"
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testMatch: ['**/?(*.)+(spec|test).[jt]s?(x)'],
|
||||
roots: ["./src"],
|
||||
coverageReporters: ["text-summary", "html"]
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"name": "@hcengineering/measurements",
|
||||
"version": "0.6.0",
|
||||
"main": "lib/index.js",
|
||||
"svelte": "src/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"lib/**/*",
|
||||
"types/**/*",
|
||||
"tsconfig.json"
|
||||
],
|
||||
"author": "Anticrm Platform Contributors",
|
||||
"license": "EPL-2.0",
|
||||
"scripts": {
|
||||
"build": "compile",
|
||||
"build:watch": "compile",
|
||||
"test": "jest --passWithNoTests --silent",
|
||||
"format": "format src",
|
||||
"_phase:build": "compile transpile src",
|
||||
"_phase:test": "jest --passWithNoTests --silent",
|
||||
"_phase:format": "format src",
|
||||
"_phase:validate": "compile validate"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@hcengineering/platform-rig": "^0.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.11.0",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-n": "^15.4.0",
|
||||
"eslint": "^8.54.0",
|
||||
"simplytyped": "^3.3.0",
|
||||
"@typescript-eslint/parser": "^6.11.0",
|
||||
"eslint-config-standard-with-typescript": "^40.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.8.3",
|
||||
"jest": "^29.7.0",
|
||||
"ts-jest": "^29.1.1",
|
||||
"@types/jest": "^29.5.5"
|
||||
},
|
||||
"dependencies": {},
|
||||
"repository": "https://github.com/hcengineering/platform",
|
||||
"publishConfig": {
|
||||
"registry": "https://npm.pkg.github.com"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./types/index.d.ts",
|
||||
"require": "./lib/index.js",
|
||||
"import": "./lib/index.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// Basic performance metrics suite.
|
||||
|
||||
import { generateId, platformNow, platformNowDiff } from '../utils'
|
||||
import { platformNow, platformNowDiff } from '.'
|
||||
import { childMetrics, newMetrics, updateMeasure } from './metrics'
|
||||
import {
|
||||
type FullParamsType,
|
||||
@@ -21,7 +21,7 @@ function replacer (value: any): any {
|
||||
return value instanceof Error ? errorPrinter(value) : value
|
||||
}
|
||||
|
||||
const consoleLogger = (logParams: Record<string, any>): MeasureLogger => ({
|
||||
export const consoleLogger = (logParams: Record<string, any>): MeasureLogger => ({
|
||||
info: (msg, args) => {
|
||||
console.info(
|
||||
msg,
|
||||
@@ -45,9 +45,9 @@ const consoleLogger = (logParams: Record<string, any>): MeasureLogger => ({
|
||||
logOperation: (operation, time, params) => {}
|
||||
})
|
||||
|
||||
const noParamsLogger = consoleLogger({})
|
||||
export const noParamsLogger = consoleLogger({})
|
||||
|
||||
const nullPromise = Promise.resolve()
|
||||
export const nullPromise = Promise.resolve()
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -146,6 +146,10 @@ export class MeasureMetricsContext implements MeasureContext {
|
||||
}
|
||||
}
|
||||
|
||||
withoutTracing<T>(op: () => T): T {
|
||||
return op()
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
@@ -231,6 +235,10 @@ export class NoMetricsContext implements MeasureContext {
|
||||
return r instanceof Promise ? r : Promise.resolve(r)
|
||||
}
|
||||
|
||||
withoutTracing<T>(op: () => T): T {
|
||||
return op()
|
||||
}
|
||||
|
||||
withSync<T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
@@ -290,6 +298,8 @@ export function setOperationLogProfiling (value: boolean): void {
|
||||
operationProfiling = value
|
||||
}
|
||||
|
||||
let globalId: number = 0
|
||||
|
||||
export function registerOperationLog (ctx: MeasureContext): { opLogMetrics?: Metrics, op?: OperationLog } {
|
||||
if (!operationProfiling) {
|
||||
return {}
|
||||
@@ -298,7 +308,7 @@ export function registerOperationLog (ctx: MeasureContext): { opLogMetrics?: Met
|
||||
let opLogMetrics: Metrics | undefined
|
||||
|
||||
if (ctx.id === undefined) {
|
||||
ctx.id = 'op_' + generateId()
|
||||
ctx.id = 'op_' + (++globalId).toString(16)
|
||||
}
|
||||
if (ctx.metrics !== undefined) {
|
||||
if (ctx.metrics.opLog === undefined) {
|
||||
@@ -0,0 +1,13 @@
|
||||
export * from './context'
|
||||
export * from './metrics'
|
||||
export * from './types'
|
||||
|
||||
/**
|
||||
* Return a current performance timestamp
|
||||
*/
|
||||
export const platformNow: () => number = () => performance.now()
|
||||
|
||||
/**
|
||||
* Return a diff with previous performance snapshot with 2 digits after . max.
|
||||
*/
|
||||
export const platformNowDiff = (old: number): number => Math.round((performance.now() - old) * 100) / 100
|
||||
@@ -1,7 +1,6 @@
|
||||
// Basic performance metrics suite.
|
||||
|
||||
import { type MetricsData } from '.'
|
||||
import { platformNow } from '../utils'
|
||||
import { platformNow, type MetricsData } from '.'
|
||||
import { type FullParamsType, type Metrics, type ParamsType } from './types'
|
||||
|
||||
/**
|
||||
@@ -84,6 +84,8 @@ export interface MeasureContext<Q = any> {
|
||||
fullParams?: FullParamsType | (() => FullParamsType)
|
||||
) => Promise<T>
|
||||
|
||||
withoutTracing: <T>(op: () => T) => T
|
||||
|
||||
withSync: <T>(
|
||||
name: string,
|
||||
params: ParamsType,
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"extends": "./node_modules/@hcengineering/platform-rig/profiles/default/tsconfig.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib",
|
||||
"declarationDir": "./types",
|
||||
"tsBuildInfoFile": ".build/build.tsbuildinfo"
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "lib", "dist", "types", "bundle"]
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
//
|
||||
import { serveAccount } from '@hcengineering/account-service'
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { initStatisticsContext, loadBrandingMap } from '@hcengineering/server-core'
|
||||
import { join } from 'path'
|
||||
|
||||
@@ -13,7 +13,7 @@ Analytics.setTag('application', 'account')
|
||||
|
||||
const metricsContext = initStatisticsContext('account', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'account',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { startBackup } from '@hcengineering/backup-service'
|
||||
import { MeasureMetricsContext, newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { initStatisticsContext, type PipelineFactory } from '@hcengineering/server-core'
|
||||
import {
|
||||
createBackupPipeline,
|
||||
@@ -56,7 +56,7 @@ process.on('exit', () => {
|
||||
|
||||
const metricsContext = initStatisticsContext('backup', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'backup',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { startCollaborator } from '@hcengineering/collaborator'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import { join } from 'path'
|
||||
|
||||
@@ -25,7 +25,7 @@ Analytics.setTag('application', 'collaborator')
|
||||
|
||||
const metricsContext = initStatisticsContext('collaborator', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'collaborator',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { startFront } from '@hcengineering/front/src/starter'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import { join } from 'path'
|
||||
@@ -14,7 +14,7 @@ Analytics.setTag('application', 'front')
|
||||
|
||||
const metricsContext = initStatisticsContext('front', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'front',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { initStatisticsContext, type StorageConfiguration } from '@hcengineering/server-core'
|
||||
import { join } from 'path'
|
||||
|
||||
@@ -41,7 +41,7 @@ setMetadata(serverToken.metadata.Service, 'fulltext')
|
||||
|
||||
const metricsContext = initStatisticsContext('fulltext', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'fulltext',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { Doc, MeasureMetricsContext, TxCUD, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { Doc, newMetrics, TxCUD } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
@@ -46,7 +46,7 @@ async function main (): Promise<void> {
|
||||
|
||||
const ctx = initStatisticsContext(application, {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
application,
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
// Add this to the VERY top of the first file loaded in your app
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import contactPlugin from '@hcengineering/contact'
|
||||
import { MeasureMetricsContext, newMetrics, setOperationLogProfiling } from '@hcengineering/core'
|
||||
import { newMetrics, setOperationLogProfiling } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { setDBExtraOptions } from '@hcengineering/postgres'
|
||||
@@ -50,7 +50,7 @@ const metricsContext = initStatisticsContext('transactor', {
|
||||
return getStats()
|
||||
},
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'server',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Copyright © 2023 Hardcore Engineering Inc.
|
||||
//
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics, type Tx } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import builder, { getModelVersion, migrateOperations } from '@hcengineering/model-all'
|
||||
import { initStatisticsContext, loadBrandingMap } from '@hcengineering/server-core'
|
||||
@@ -18,7 +18,7 @@ Analytics.setTag('application', 'workspace')
|
||||
// Force create server metrics context with proper logging
|
||||
const metricsContext = initStatisticsContext('workspace', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'workspace',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -422,6 +422,16 @@
|
||||
"projectFolder": "packages/platform",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/measurements",
|
||||
"projectFolder": "packages/measurements",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/measurements-otlp",
|
||||
"projectFolder": "packages/measurements-otlp",
|
||||
"shouldPublish": true
|
||||
},
|
||||
{
|
||||
"packageName": "@hcengineering/core",
|
||||
"projectFolder": "packages/core",
|
||||
|
||||
@@ -385,7 +385,9 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
|
||||
// Ignore
|
||||
}
|
||||
|
||||
const result = await measureCtx.with(request.method, { source }, (mctx) => {
|
||||
const userCtx = measureCtx.newChild(request.method, { source })
|
||||
|
||||
try {
|
||||
if (method === undefined || typeof method !== 'function') {
|
||||
const response = {
|
||||
id: request.id,
|
||||
@@ -396,12 +398,14 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
|
||||
return
|
||||
}
|
||||
|
||||
return method(mctx, db, branding, request, token, meta)
|
||||
})
|
||||
const result = await method(userCtx, db, branding, request, token, meta)
|
||||
|
||||
const body = JSON.stringify(result)
|
||||
ctx.res.writeHead(200, KEEP_ALIVE_HEADERS)
|
||||
ctx.res.end(body)
|
||||
const body = JSON.stringify(result)
|
||||
ctx.res.writeHead(200, KEEP_ALIVE_HEADERS)
|
||||
ctx.res.end(body)
|
||||
} finally {
|
||||
userCtx.end()
|
||||
}
|
||||
})
|
||||
|
||||
app.use(router.routes()).use(router.allowedMethods())
|
||||
|
||||
+15
-34
@@ -1,7 +1,6 @@
|
||||
import type { MeasureContext, Metrics } from '@hcengineering/core'
|
||||
import { concatLink, MeasureMetricsContext, metricsToString, newMetrics, systemAccountUuid } from '@hcengineering/core'
|
||||
import { concatLink, MeasureMetricsContext, newMetrics, systemAccountUuid } from '@hcengineering/core'
|
||||
import { generateToken } from '@hcengineering/server-token'
|
||||
import { writeFile } from 'fs/promises'
|
||||
import os from 'os'
|
||||
|
||||
export interface MemoryStatistics {
|
||||
@@ -79,14 +78,13 @@ export function initStatisticsContext (
|
||||
serviceName: string,
|
||||
ops?: {
|
||||
logFile?: string
|
||||
logConsole?: boolean
|
||||
factory?: () => MeasureMetricsContext
|
||||
factory?: () => MeasureContext
|
||||
getStats?: () => WorkspaceStatistics[]
|
||||
statsUrl?: string
|
||||
serviceName?: () => string
|
||||
}
|
||||
): MeasureContext {
|
||||
let metricsContext: MeasureMetricsContext
|
||||
let metricsContext: MeasureContext
|
||||
if (ops?.factory !== undefined) {
|
||||
metricsContext = ops.factory()
|
||||
} else {
|
||||
@@ -95,16 +93,10 @@ export function initStatisticsContext (
|
||||
|
||||
const statsUrl = ops?.statsUrl ?? process.env.STATS_URL
|
||||
|
||||
const metricsFile = ops?.logFile
|
||||
|
||||
let errorToSend = 0
|
||||
|
||||
if (metricsFile !== undefined || ops?.logConsole === true || statsUrl !== undefined) {
|
||||
if (statsUrl !== undefined) {
|
||||
metricsContext.info('using stats url', { statsUrl, service: serviceName ?? '' })
|
||||
if (metricsFile !== undefined) {
|
||||
console.info('storing measurements into local file', metricsFile)
|
||||
}
|
||||
let oldMetricsValue = ''
|
||||
const serviceId = encodeURIComponent(os.hostname() + '-' + serviceName)
|
||||
|
||||
let prev: Promise<void> | Promise<any> | undefined
|
||||
@@ -120,20 +112,6 @@ export function initStatisticsContext (
|
||||
|
||||
const intTimer = setInterval(() => {
|
||||
try {
|
||||
if (metricsFile !== undefined || ops?.logConsole === true) {
|
||||
const val = metricsToString(metricsContext.metrics, serviceName, 140)
|
||||
if (val !== oldMetricsValue) {
|
||||
oldMetricsValue = val
|
||||
if (metricsFile !== undefined) {
|
||||
void writeFile(metricsFile, val).catch((err) => {
|
||||
console.error(err)
|
||||
})
|
||||
}
|
||||
if (ops?.logConsole === true) {
|
||||
console.info('METRICS:', val)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prev !== undefined) {
|
||||
// In case of high load, skip
|
||||
return
|
||||
@@ -150,14 +128,17 @@ export function initStatisticsContext (
|
||||
|
||||
const statData = JSON.stringify(data)
|
||||
|
||||
prev = fetch(concatLink(statsUrl, '/api/v1/statistics') + `/?name=${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
authorization: `Bearer ${token}`
|
||||
},
|
||||
body: statData
|
||||
})
|
||||
prev = metricsContext
|
||||
.withoutTracing(() =>
|
||||
fetch(concatLink(statsUrl, '/api/v1/statistics') + `/?name=${serviceId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
authorization: `Bearer ${token}`
|
||||
},
|
||||
body: statData
|
||||
})
|
||||
)
|
||||
.finally(() => {
|
||||
prev = undefined
|
||||
})
|
||||
|
||||
@@ -18,8 +18,8 @@ import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken, { generateToken } from '@hcengineering/server-token'
|
||||
|
||||
import { getClient as getAccountClient } from '@hcengineering/account-client'
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics, type SocialId } from '@hcengineering/core'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics, type SocialId } from '@hcengineering/core'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { AIControl } from './controller'
|
||||
@@ -38,7 +38,7 @@ export const start = async (): Promise<void> => {
|
||||
|
||||
const ctx = initStatisticsContext('ai-bot-service', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'ai-bot-service',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
//
|
||||
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { SplitLogger, configureAnalytics } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { SplitLogger, configureAnalytics, createOpenTelemetryMetricsContext } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { join } from 'path'
|
||||
|
||||
import config from './config'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import config from './config'
|
||||
import { createServer, listen } from './server'
|
||||
|
||||
const ctx = initStatisticsContext('analytics-collector', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'analytics-collector-service',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
@@ -37,7 +37,7 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
const metricsContext = initStatisticsContext('backup-api', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'backup-api',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -13,16 +13,16 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { createServer, listen } from './server'
|
||||
import config from './config'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { join } from 'path'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { createServer, listen } from './server'
|
||||
|
||||
const setupMetadata = (): void => {
|
||||
setMetadata(serverToken.metadata.Secret, config.Secret)
|
||||
@@ -38,7 +38,7 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
const metricsContext = initStatisticsContext('billing', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'billing',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -13,22 +13,22 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { join } from 'path'
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { SplitLogger, configureAnalytics } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext, QueueTopic } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { eventCreated, eventDeleted, eventMixin, eventUpdated } from './handlers'
|
||||
import { EventCUDMessage } from './types'
|
||||
import { eventCreated, eventUpdated, eventDeleted, eventMixin } from './handlers'
|
||||
|
||||
async function main (): Promise<void> {
|
||||
const ctx = initStatisticsContext('calendar-mailer', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'calendar-mailer',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
//
|
||||
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { createOpenTelemetryMetricsContext } from '@hcengineering/analytics-service/src'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient, { getAccountClient } from '@hcengineering/server-client'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
@@ -43,7 +44,7 @@ const extractToken = (header: IncomingHttpHeaders): any => {
|
||||
export const main = async (): Promise<void> => {
|
||||
const ctx = initStatisticsContext(CALENDAR_INTEGRATION, {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'calendar',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
@@ -38,7 +38,7 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
const metricsContext = initStatisticsContext('datalake', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'datalake',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { SplitLogger, configureAnalytics } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { SplitLogger, configureAnalytics, createOpenTelemetryMetricsContext } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext, loadBrandingMap } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { start } from './server'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
|
||||
// Load and inc startID, to have easy logs.
|
||||
|
||||
@@ -19,7 +19,7 @@ setMetadata(serverToken.metadata.Service, 'github')
|
||||
|
||||
const metricsContext = initStatisticsContext('github', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'github',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -28,6 +28,7 @@ describe('AttachmentHandler', () => {
|
||||
with: jest.fn(),
|
||||
withSync: jest.fn(),
|
||||
withLog: jest.fn(),
|
||||
withoutTracing: jest.fn(),
|
||||
logger: {
|
||||
info: jest.fn(),
|
||||
error: jest.fn(),
|
||||
|
||||
@@ -15,15 +15,15 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { isWorkspaceLoginInfo } from '@hcengineering/account-client'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { closeQueue, initQueue } from '@hcengineering/mail-common'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient, { getAccountClient } from '@hcengineering/server-client'
|
||||
import { isWorkspaceLoginInfo } from '@hcengineering/account-client'
|
||||
import { initStatisticsContext, type StorageConfiguration } from '@hcengineering/server-core'
|
||||
import { buildStorageFromConfig, storageConfigFromEnv } from '@hcengineering/server-storage'
|
||||
import serverToken, { decodeToken } from '@hcengineering/server-token'
|
||||
import { initQueue, closeQueue } from '@hcengineering/mail-common'
|
||||
import { type IncomingHttpHeaders } from 'http'
|
||||
import { join } from 'path'
|
||||
|
||||
@@ -44,7 +44,7 @@ const extractToken = (header: IncomingHttpHeaders): any => {
|
||||
export const main = async (): Promise<void> => {
|
||||
const ctx = initStatisticsContext('gmail', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'gmail',
|
||||
{},
|
||||
{},
|
||||
|
||||
+10
-10
@@ -12,19 +12,19 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureContext, MeasureMetricsContext, newMetrics, Ref, WorkspaceIds } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import { initStatisticsContext, StorageConfig, StorageConfiguration } from '@hcengineering/server-core'
|
||||
import { storageConfigFromEnv } from '@hcengineering/server-storage'
|
||||
import serverToken, { decodeToken, Token } from '@hcengineering/server-token'
|
||||
import {
|
||||
getClient as getAccountClientRaw,
|
||||
isWorkspaceLoginInfo,
|
||||
type AccountClient
|
||||
} from '@hcengineering/account-client'
|
||||
import { RoomMetadata, TranscriptionStatus, MeetingMinutes } from '@hcengineering/love'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureContext, newMetrics, Ref, WorkspaceIds } from '@hcengineering/core'
|
||||
import { MeetingMinutes, RoomMetadata, TranscriptionStatus } from '@hcengineering/love'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import { initStatisticsContext, StorageConfig, StorageConfiguration } from '@hcengineering/server-core'
|
||||
import { storageConfigFromEnv } from '@hcengineering/server-storage'
|
||||
import serverToken, { decodeToken, Token } from '@hcengineering/server-token'
|
||||
import cors from 'cors'
|
||||
import express, { type Request } from 'express'
|
||||
import { IncomingHttpHeaders } from 'http'
|
||||
@@ -38,8 +38,8 @@ import {
|
||||
WebhookReceiver
|
||||
} from 'livekit-server-sdk'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { saveLiveKitEgressBilling, updateLiveKitSessions } from './billing'
|
||||
import config from './config'
|
||||
import { getRecordingPreset } from './preset'
|
||||
import { getS3UploadParams, saveFile } from './storage'
|
||||
import { WorkspaceClient } from './workspaceClient'
|
||||
@@ -68,7 +68,7 @@ export const main = async (): Promise<void> => {
|
||||
|
||||
const ctx = initStatisticsContext('love', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'love',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -13,26 +13,26 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import cors from 'cors'
|
||||
import express, { NextFunction, Request, Response } from 'express'
|
||||
import { join } from 'path'
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureContext, MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureContext, newMetrics } from '@hcengineering/core'
|
||||
import { closeQueue, initQueue } from '@hcengineering/mail-common'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { initQueue, closeQueue } from '@hcengineering/mail-common'
|
||||
import cors from 'cors'
|
||||
import express, { NextFunction, Request, Response } from 'express'
|
||||
import { join } from 'path'
|
||||
|
||||
import { handleMtaHook } from './handlerMta'
|
||||
import config from './config'
|
||||
import { baseConfig } from './client'
|
||||
import config from './config'
|
||||
import { handleMtaHook } from './handlerMta'
|
||||
|
||||
type RequestHandler = (req: Request, res: Response, ctx: MeasureContext, next?: NextFunction) => Promise<void>
|
||||
|
||||
async function main (): Promise<void> {
|
||||
const ctx = initStatisticsContext('inbound-mail', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'inbound-mail',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { type SendMailOptions } from 'nodemailer'
|
||||
import { Request, Response } from 'express'
|
||||
import { join } from 'path'
|
||||
import { type SendMailOptions } from 'nodemailer'
|
||||
import Mail from 'nodemailer/lib/mailer'
|
||||
import { join } from 'path'
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { MeasureContext, newMetrics } from '@hcengineering/core'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import { MeasureContext, MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, SplitLogger } from '@hcengineering/analytics-service'
|
||||
|
||||
import config from './config'
|
||||
import { createServer, listen } from './server'
|
||||
import { MailClient } from './mail'
|
||||
import { createServer, listen } from './server'
|
||||
import { Endpoint } from './types'
|
||||
|
||||
export const main = async (): Promise<void> => {
|
||||
@@ -33,7 +33,7 @@ export const main = async (): Promise<void> => {
|
||||
Analytics.setTag('application', 'mail')
|
||||
const measureCtx = initStatisticsContext('mail', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'mail',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -13,7 +13,11 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { initStatisticsContext } from '@hcengineering/server-core'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import bodyParser from 'body-parser'
|
||||
import cors from 'cors'
|
||||
import express from 'express'
|
||||
@@ -21,6 +25,7 @@ import formData from 'express-form-data'
|
||||
import { type IncomingHttpHeaders, type Server } from 'http'
|
||||
import morgan from 'morgan'
|
||||
import os from 'os'
|
||||
import { join } from 'path'
|
||||
import { type Readable } from 'stream'
|
||||
import config from './config'
|
||||
import { ApiError } from './error'
|
||||
@@ -29,11 +34,6 @@ import { parseGenericResume } from './generic'
|
||||
import { decode } from './jwt'
|
||||
import { extractDocument } from './process'
|
||||
import { type ReconiDocument } from './types'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { join } from 'path'
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
|
||||
const extractToken = (header: IncomingHttpHeaders): any => {
|
||||
@@ -51,7 +51,7 @@ export const startServer = async (): Promise<void> => {
|
||||
setMetadata(serverToken.metadata.Service, 'rekoni')
|
||||
const ctx = initStatisticsContext('rekoni', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'rekoni',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { generateId, MeasureMetricsContext, newMetrics, type WorkspaceIds } from '@hcengineering/core'
|
||||
import { AccountClient, getClient as getAccountClientRaw, isWorkspaceLoginInfo } from '@hcengineering/account-client'
|
||||
import { generateId, newMetrics, type WorkspaceIds } from '@hcengineering/core'
|
||||
import { initStatisticsContext, StorageConfiguration } from '@hcengineering/server-core'
|
||||
import { buildStorageFromConfig } from '@hcengineering/server-storage'
|
||||
import { getClient as getAccountClientRaw, AccountClient, isWorkspaceLoginInfo } from '@hcengineering/account-client'
|
||||
import cors from 'cors'
|
||||
import express, { type Express, type NextFunction, type Request, type Response } from 'express'
|
||||
import { type Server } from 'http'
|
||||
|
||||
import { type Branding, type BrandingMap, extractBranding } from './branding'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { join } from 'path'
|
||||
import { extractBranding, type Branding, type BrandingMap } from './branding'
|
||||
import config from './config'
|
||||
import { ApiError } from './error'
|
||||
import { signPDF } from './sign'
|
||||
import { extractToken } from './token'
|
||||
import { join } from 'path'
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
|
||||
function getAccountClient (token: string): AccountClient {
|
||||
return getAccountClientRaw(config.AccountsUrl, token)
|
||||
@@ -77,7 +77,7 @@ export function createServer (storageConfig: StorageConfiguration, brandings: Br
|
||||
const storageAdapter = buildStorageFromConfig(storageConfig)
|
||||
const measureCtx = initStatisticsContext('sign', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'sign',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
//
|
||||
|
||||
import { Analytics } from '@hcengineering/analytics'
|
||||
import { SplitLogger, configureAnalytics } from '@hcengineering/analytics-service'
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { configureAnalytics, createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import { initStatisticsContext, QueueTopic } from '@hcengineering/server-core'
|
||||
import { TelegramQueueMessage, TelegramQueueMessageType } from '@hcengineering/server-telegram'
|
||||
import serverToken from '@hcengineering/server-token'
|
||||
import { join } from 'path'
|
||||
import { getPlatformQueue } from '@hcengineering/kafka'
|
||||
import { TelegramQueueMessage, TelegramQueueMessageType } from '@hcengineering/server-telegram'
|
||||
|
||||
import config from './config'
|
||||
import { registerLoaders } from './loaders'
|
||||
@@ -32,7 +32,7 @@ import { PlatformWorker } from './worker'
|
||||
|
||||
const ctx = initStatisticsContext('telegram-bot', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'telegram-bot-service',
|
||||
{},
|
||||
{},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { MeasureMetricsContext, newMetrics } from '@hcengineering/core'
|
||||
import { newMetrics } from '@hcengineering/core'
|
||||
import { setMetadata } from '@hcengineering/platform'
|
||||
import serverClient from '@hcengineering/server-client'
|
||||
import { initStatisticsContext, type StorageConfiguration } from '@hcengineering/server-core'
|
||||
@@ -7,7 +7,7 @@ import { buildStorageFromConfig, storageConfigFromEnv } from '@hcengineering/ser
|
||||
import serverToken, { decodeToken, type Token } from '@hcengineering/server-token'
|
||||
import { IncomingHttpHeaders } from 'http'
|
||||
|
||||
import { SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { createOpenTelemetryMetricsContext, SplitLogger } from '@hcengineering/analytics-service'
|
||||
import { join } from 'path'
|
||||
import config from './config'
|
||||
import { PlatformWorker } from './platform'
|
||||
@@ -28,7 +28,7 @@ const extractToken = (headers: IncomingHttpHeaders): Token | undefined => {
|
||||
export const main = async (): Promise<void> => {
|
||||
const ctx = initStatisticsContext('telegram', {
|
||||
factory: () =>
|
||||
new MeasureMetricsContext(
|
||||
createOpenTelemetryMetricsContext(
|
||||
'telegram',
|
||||
{},
|
||||
{},
|
||||
|
||||
Reference in New Issue
Block a user