diff --git a/README.md b/README.md index e08d66c..9e3e6b2 100644 --- a/README.md +++ b/README.md @@ -136,6 +136,20 @@ pnpm env:development build --filter=chain pnpm env:development sequencer:start --filter=chain ``` +### Observability + +Protokit has the ability to report metrics, logs and traces to a Grafana instance for visualisation. +These can be configured by the following environment variables +```zsh +OPEN_TELEMETRY_TRACING_URL= +OPEN_TELEMETRY_TRACING_ENABLED= + +OPEN_TELEMETRY_METRICS_URL= +OPEN_TELEMETRY_METRICS_ENABLED= +OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY= +```` +Note that the functionality is not configured for the `in-memory` mode. + ### Running the UI ```zsh @@ -230,11 +244,43 @@ The caddy reverse-proxy automatically uses https for all connections, use this g +### Monitoring + +Protokit offers monitoring via three different kinds of data and a collection of preconfigured services: +- Logs via Promtail and Loki +- Metrics via OpenTelemetry and Prometheus +- Traces via OpenTelemetry, OTel Collector and Tempo +- Dashboard via Grafana + +#### Development + +In Development mode, monitoring is disabled by default. + +To enabled, edit the `development/.env` file in the following way: +1. Add the monitoring profile to `COMPOSE_PROFILES` +2. Uncomment `...metricsSequencerModules` in the sequencer's module definition. +Important: This has to be in front of all other modules (i.e. has to be first in the modules record) +3. Uncomment `...metricsSequencerModulesConfig` in the configuration call. + +Then, run `pnpm env:development docker:up` like usual. This should start all the services needed for monitoring. +Grafana is available at `localhost:3000`. + +Note: Logs are currently not available without docker, since promtail is only configured to pick up container logs + +#### Sovereign + +In Sovereign mode, monitoring is configured by default. + +Grafana is reachable under `localhost/grafana`. + +If you want to remove the monitoring services, remove the docker profile `monitoring` from the `.env` file and remove the `OpenTelemetryServer` configuration + +More information about monitoring can be found [here](https://github.com/proto-kit/framework/pull/272). ## Building the framework from source 1. Make sure the framework is located under ../framework from the starter-kit's location -2. Adapt your starter-kit's package.json to use the file:// references to framework +2. Adapt your starter-kit's `packages/chain` and `apps/web` package.json to use the file:// references to framework, including +references to `o1js` and `tsyringe`. Important: Make sure to update references in both chain and web, otherwise the location of the node_modules will be different and lead to errors 3. Go into the framework folder, and build a docker image containing the sources with `docker build -f ./packages/deployment/docker/development-base/Dockerfile -t protokit-base .` - -4. Comment out the first line of docker/base/Dockerfile to use protokit-base +4. Replace the first line of `docker/base/Dockerfile` and `docker/web/Dockerfile` to use `FROM protokit-base:latest` diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index 92dc447..d2954d0 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -1,5 +1,5 @@ # For regular deployment -FROM node:18 +FROM protokit-base # For locally built and imported framework references # Make sure you build the base-image first @@ -17,7 +17,7 @@ COPY ./packages/chain/package.json ./packages/chain/package.json COPY ./packages/eslint-config-custom/package.json ./packages/eslint-config-custom/package.json COPY ./apps/web/package.json ./apps/web/package.json -RUN corepack enable +RUN npm i -g pnpm@9.8.0 COPY ./tsconfig.json . COPY ./packages/chain/tsconfig.json ./packages/chain/tsconfig.json diff --git a/docker/base/entry.sh b/docker/base/entry.sh index aeef42a..9134078 100644 --- a/docker/base/entry.sh +++ b/docker/base/entry.sh @@ -25,4 +25,4 @@ cd /app echo $@ # We can't use start:headless here bcs that task hardcodes the .js file, we want it to be extensible -node --experimental-vm-modules --experimental-wasm-modules --experimental-wasm-threads --es-module-specifier-resolution=node $@ \ No newline at end of file +node --experimental-vm-modules --experimental-wasm-modules --es-module-specifier-resolution=node $@ \ No newline at end of file diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index c93e660..8fb16fc 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -7,3 +7,4 @@ include: - ./indexer/docker-compose.yml - ./processor-persistence/docker-compose.yml - ./processor/docker-compose.yml + - ./monitoring/docker-compose.yml diff --git a/docker/indexer/docker-compose.yml b/docker/indexer/docker-compose.yml index 44d12ec..c8dacf1 100644 --- a/docker/indexer/docker-compose.yml +++ b/docker/indexer/docker-compose.yml @@ -43,6 +43,9 @@ services: [ "./packages/chain/dist/start.js start ./environments/${PROTOKIT_ENV_FOLDER}/indexer.config.js", ] + labels: + logging: "promtail" + logging_jobname: "indexer" networks: indexer-net: diff --git a/docker/monitoring/docker-compose.yml b/docker/monitoring/docker-compose.yml new file mode 100644 index 0000000..5ee80b7 --- /dev/null +++ b/docker/monitoring/docker-compose.yml @@ -0,0 +1,102 @@ +services: + prometheus: + image: prom/prometheus + container_name: prometheus + profiles: + - monitoring + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--web.enable-remote-write-receiver' + - '--enable-feature=native-histograms' + networks: + - monitoring + - chain-net + ports: + - "9090:9090" + restart: unless-stopped + volumes: + - ./prometheus/${PROTOKIT_ENV_FOLDER}:/etc/prometheus + - ../data/prometheus:/prometheus + + loki: + image: grafana/loki:latest + container_name: loki + profiles: + - monitoring + networks: + - monitoring + ports: + - "3100:3100" + command: -config.file=/etc/loki/local-config.yaml + + promtail: + image: grafana/promtail:latest + container_name: promtail + profiles: + - monitoring + networks: + - monitoring + volumes: + - ./promtail/promtail.yaml:/etc/promtail/docker-config.yaml + - /var/lib/docker/containers:/var/lib/docker/containers:ro + - /var/run/docker.sock:/var/run/docker.sock + command: -config.file=/etc/promtail/docker-config.yaml + depends_on: + - loki + + otel-collector: + image: otel/opentelemetry-collector:0.86.0 + container_name: otel-collector + profiles: + - monitoring + networks: + - monitoring + - chain-net + command: [ "--config=/etc/otel-collector.yaml" ] + volumes: + - ./otel-collector/otel-collector.yaml:/etc/otel-collector.yaml + ports: + - "4318:4317" + + tempo: + image: grafana/tempo:latest + container_name: tempo + networks: + - monitoring + profiles: + - monitoring + command: [ "-config.file=/etc/tempo.yaml" ] + volumes: + - ./tempo/tempo.yaml:/etc/tempo.yaml + - ../data/tempo:/var/tempo + ports: + - "3200:3200" # tempo + - "4317:4317" # otlp grpc + + grafana: + image: grafana/grafana:11.0.1 + container_name: grafana + profiles: + - monitoring + restart: unless-stopped + networks: + - monitoring + ports: + - "3001:3000" + environment: + - GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER} + - GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD} + - GF_SECURITY_ALLOW_EMBEDDING=true + volumes: + - ./grafana:/etc/grafana/provisioning/datasources + - ../data/grafana:/var/lib/grafana + depends_on: + - loki + - tempo + - prometheus + labels: + logging: "promtail" + logging_jobname: "grafana" + +networks: + monitoring: \ No newline at end of file diff --git a/docker/monitoring/grafana/grafana-datasources.yaml b/docker/monitoring/grafana/grafana-datasources.yaml new file mode 100644 index 0000000..cc275cb --- /dev/null +++ b/docker/monitoring/grafana/grafana-datasources.yaml @@ -0,0 +1,33 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + type: prometheus + url: http://prometheus:9090 + isDefault: true + access: proxy + editable: true + - name: Loki + type: loki + access: proxy + orgId: 1 + url: http://loki:3100 + basicAuth: false + version: 1 + editable: false + - name: Tempo + type: tempo + access: proxy + orgId: 1 + url: http://tempo:3200 + basicAuth: false + version: 1 + editable: false + apiVersion: 1 + uid: tempo + jsonData: + httpMethod: GET + serviceMap: + datasourceUid: prometheus + streamingEnabled: + search: true \ No newline at end of file diff --git a/docker/monitoring/otel-collector/otel-collector.yaml b/docker/monitoring/otel-collector/otel-collector.yaml new file mode 100644 index 0000000..e11401e --- /dev/null +++ b/docker/monitoring/otel-collector/otel-collector.yaml @@ -0,0 +1,16 @@ +receivers: + otlp: + protocols: + grpc: +exporters: + otlp: + endpoint: tempo:4317 + tls: + insecure: true + debug: + verbosity: detailed +service: + pipelines: + traces: + receivers: [otlp] + exporters: [otlp] \ No newline at end of file diff --git a/docker/monitoring/prometheus/development/prometheus.yml b/docker/monitoring/prometheus/development/prometheus.yml new file mode 100644 index 0000000..0bc98da --- /dev/null +++ b/docker/monitoring/prometheus/development/prometheus.yml @@ -0,0 +1,30 @@ +global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 10s + api_version: v2 +scrape_configs: + - job_name: prometheus + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - localhost:9090 + - job_name: sequencer + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - host.docker.internal:4320 diff --git a/docker/monitoring/prometheus/sovereign/prometheus.yml b/docker/monitoring/prometheus/sovereign/prometheus.yml new file mode 100644 index 0000000..f810d17 --- /dev/null +++ b/docker/monitoring/prometheus/sovereign/prometheus.yml @@ -0,0 +1,30 @@ +global: + scrape_interval: 15s + scrape_timeout: 10s + evaluation_interval: 15s +alerting: + alertmanagers: + - static_configs: + - targets: [] + scheme: http + timeout: 10s + api_version: v2 +scrape_configs: + - job_name: prometheus + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - localhost:9090 + - job_name: sequencer + honor_timestamps: true + scrape_interval: 15s + scrape_timeout: 10s + metrics_path: /metrics + scheme: http + static_configs: + - targets: + - starterkit-sequencer:4320 diff --git a/docker/monitoring/promtail/promtail.yaml b/docker/monitoring/promtail/promtail.yaml new file mode 100644 index 0000000..dbc28d7 --- /dev/null +++ b/docker/monitoring/promtail/promtail.yaml @@ -0,0 +1,26 @@ +server: + http_listen_port: 9080 + grpc_listen_port: 0 + +positions: + filename: /tmp/positions.yaml + +clients: + - url: http://loki:3100/loki/api/v1/push + +scrape_configs: + - job_name: flog_scrape + docker_sd_configs: + - host: unix:///var/run/docker.sock + refresh_interval: 5s + filters: + - name: label + values: ["logging=promtail"] + relabel_configs: + - source_labels: ['__meta_docker_container_name'] + regex: '/(.*)' + target_label: 'container' + - source_labels: ['__meta_docker_container_log_stream'] + target_label: 'logstream' + - source_labels: ['__meta_docker_container_label_logging_jobname'] + target_label: 'job' \ No newline at end of file diff --git a/docker/monitoring/tempo/tempo.yaml b/docker/monitoring/tempo/tempo.yaml new file mode 100644 index 0000000..828f1ca --- /dev/null +++ b/docker/monitoring/tempo/tempo.yaml @@ -0,0 +1,56 @@ + +stream_over_http_enabled: true +server: + http_listen_port: 3200 + log_level: info + +query_frontend: + search: + duration_slo: 5s + throughput_bytes_slo: 1.073741824e+09 + metadata_slo: + duration_slo: 5s + throughput_bytes_slo: 1.073741824e+09 + trace_by_id: + duration_slo: 5s + +distributor: + receivers: + otlp: + protocols: + grpc: + endpoint: "tempo:4317" + +ingester: + max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally + +compactor: + compaction: + block_retention: 1h # overall Tempo trace retention. set for demo purposes + +metrics_generator: + registry: + external_labels: + source: tempo + cluster: docker-compose + storage: + path: /var/tempo/generator/wal + remote_write: + - url: http://prometheus:9090/api/v1/write + send_exemplars: true + traces_storage: + path: /var/tempo/generator/traces + +storage: + trace: + backend: local # backend configuration to use + wal: + path: /var/tempo/wal # where to store the wal locally + local: + path: /var/tempo/blocks + +overrides: + defaults: + metrics_generator: + processors: [service-graphs, span-metrics, local-blocks] # enables metrics generator + generate_native_histograms: both diff --git a/docker/processor/docker-compose.yml b/docker/processor/docker-compose.yml index 632d0f4..820205a 100644 --- a/docker/processor/docker-compose.yml +++ b/docker/processor/docker-compose.yml @@ -30,6 +30,9 @@ services: - 8082:8080 working_dir: /app command: ["./packages/chain/dist/start.js start ./environments/${PROTOKIT_ENV_FOLDER}/processor.config.js",] + labels: + logging: "promtail" + logging_jobname: "processor" networks: processor-net: \ No newline at end of file diff --git a/docker/proxy/Caddyfile b/docker/proxy/Caddyfile index 3e4ebda..a5bcdec 100644 --- a/docker/proxy/Caddyfile +++ b/docker/proxy/Caddyfile @@ -2,6 +2,7 @@ reverse_proxy /graphql sequencer:8080 reverse_proxy /indexer/graphql indexer:8081 reverse_proxy /processor/graphql processor:8082 + reverse_proxy /grafana grafana:3000 reverse_proxy web:3000 encode gzip -} +} \ No newline at end of file diff --git a/docker/sequencer/docker-compose.yml b/docker/sequencer/docker-compose.yml index 0bf00ea..7c37f61 100644 --- a/docker/sequencer/docker-compose.yml +++ b/docker/sequencer/docker-compose.yml @@ -23,6 +23,14 @@ services: - PROTOKIT_GRAPHQL_HOST=${PROTOKIT_GRAPHQL_HOST} - PROTOKIT_GRAPHQL_PORT=${PROTOKIT_GRAPHQL_PORT} - PROTOKIT_GRAPHIQL_ENABLED=${PROTOKIT_GRAPHIQL_ENABLED} + + - OPEN_TELEMETRY_TRACING_ENABLED=${OPEN_TELEMETRY_TRACING_ENABLED} + - OPEN_TELEMETRY_TRACING_URL=${OPEN_TELEMETRY_TRACING_URL} + + - OPEN_TELEMETRY_METRICS_ENABLED=${OPEN_TELEMETRY_METRICS_ENABLED} + - OPEN_TELEMETRY_METRICS_PORT=${OPEN_TELEMETRY_METRICS_PORT} + - OPEN_TELEMETRY_METRICS_HOST=${OPEN_TELEMETRY_METRICS_HOST} + - OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY=${OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY} profiles: - monolithic-sequencer depends_on: @@ -37,6 +45,9 @@ services: ports: - 8080:8080 command: ["./packages/chain/dist/start.js start ./environments/${PROTOKIT_ENV_FOLDER}/chain.config.js"] + labels: + logging: "promtail" + logging_jobname: "sequencer" networks: chain-net: \ No newline at end of file diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 4e5d483..99f6227 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -21,7 +21,7 @@ COPY package.json pnpm-workspace.yaml pnpm-lock.yaml turbo.json ./ COPY ./packages/chain/package.json ./packages/chain/package.json COPY ./apps/web/package.json ./apps/web/package.json -RUN corepack enable pnpm +RUN npm i -g pnpm@9.8.0 COPY ./tsconfig.json . COPY ./packages/chain/tsconfig.json ./packages/chain/tsconfig.json diff --git a/docker/web/docker-compose.yml b/docker/web/docker-compose.yml index 6de1029..01c18ea 100644 --- a/docker/web/docker-compose.yml +++ b/docker/web/docker-compose.yml @@ -22,3 +22,6 @@ services: - chain-net ports: - 3000:3000 + labels: + logging: "promtail" + logging_jobname: "grafana" \ No newline at end of file diff --git a/packages/chain/src/environments/development/.env b/packages/chain/src/environments/development/.env index 5977346..0ade698 100644 --- a/packages/chain/src/environments/development/.env +++ b/packages/chain/src/environments/development/.env @@ -1,4 +1,5 @@ COMPOSE_PROFILES=db, indexer-db, processor-db +; monitoring COMPOSE_PROJECT_NAME=starter-kit POSTGRES_PASSWORD=password @@ -55,4 +56,15 @@ PROTOKIT_PROCESSOR_INDEXER_GRAPHQL_HOST=0.0.0.0 # expose graphql configuration to the client app-chain NEXT_PUBLIC_PROTOKIT_GRAPHQL_URL=http://localhost:8080/graphql NEXT_PUBLIC_PROTOKIT_INDEXER_GRAPHQL_URL=http://localhost:8081/graphql -NEXT_PUBLIC_PROTOKIT_PROCESSOR_GRAPHQL_URL=http://localhost:8082/graphql \ No newline at end of file +NEXT_PUBLIC_PROTOKIT_PROCESSOR_GRAPHQL_URL=http://localhost:8082/graphql + +OPEN_TELEMETRY_TRACING_ENABLED=true +OPEN_TELEMETRY_TRACING_URL=http://localhost:4318 + +OPEN_TELEMETRY_METRICS_ENABLED=true +OPEN_TELEMETRY_METRICS_PORT=4320 +OPEN_TELEMETRY_METRICS_HOST=0.0.0.0 +OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY=10 + +GF_SECURITY_ADMIN_USER=admin +GF_SECURITY_ADMIN_PASSWORD=grafana \ No newline at end of file diff --git a/packages/chain/src/environments/development/chain.config.ts b/packages/chain/src/environments/development/chain.config.ts index 614f699..e08e4dc 100644 --- a/packages/chain/src/environments/development/chain.config.ts +++ b/packages/chain/src/environments/development/chain.config.ts @@ -1,7 +1,7 @@ import { AppChain } from "@proto-kit/sdk"; import { Runtime } from "@proto-kit/module"; import { Protocol } from "@proto-kit/protocol"; -import { DatabasePruneModule, Sequencer } from "@proto-kit/sequencer"; +import { DatabasePruneModule, LocalTaskWorkerModule, Sequencer, VanillaTaskWorkerModules } from "@proto-kit/sequencer"; import { PrismaRedisDatabase } from "@proto-kit/persistance"; import runtime from "../../runtime"; import protocol from "../../protocol"; @@ -9,7 +9,7 @@ import { baseSequencerModules, baseSequencerModulesConfig, indexerSequencerModules, - indexerSequencerModulesConfig, + indexerSequencerModulesConfig, metricsSequencerModules, metricsSequencerModulesConfig, } from "../../sequencer"; import { BullQueue, Startable } from "@proto-kit/deployment"; import { Arguments } from "../../start"; @@ -29,9 +29,11 @@ export const appChain = AppChain.from({ modules: { // ordering of the modules matters due to dependency resolution Database: PrismaRedisDatabase, + ...metricsSequencerModules, + TaskQueue: BullQueue, + LocalTaskWorkerModule: LocalTaskWorkerModule.from(VanillaTaskWorkerModules.withoutSettlement()), ...baseSequencerModules, ...indexerSequencerModules, - TaskQueue: BullQueue, DatabasePruneModule, }, }), @@ -45,6 +47,7 @@ export default async (args: Arguments): Promise => { Sequencer: { ...baseSequencerModulesConfig, ...indexerSequencerModulesConfig, + ...metricsSequencerModulesConfig, DatabasePruneModule: { pruneOnStartup: args.pruneOnStartup, }, @@ -65,6 +68,8 @@ export default async (args: Arguments): Promise => { connection: process.env.DATABASE_URL!, }, }, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig() + }, ...baseAppChainModulesConfig, }); diff --git a/packages/chain/src/environments/sovereign/.env b/packages/chain/src/environments/sovereign/.env index 8be21e6..6c298a8 100644 --- a/packages/chain/src/environments/sovereign/.env +++ b/packages/chain/src/environments/sovereign/.env @@ -1,4 +1,4 @@ -COMPOSE_PROFILES=db,indexer-db,monolithic-sequencer,monolithic-indexer,proxy,web,processor-db,monolithic-processor +COMPOSE_PROFILES=db,indexer-db,monolithic-sequencer,monolithic-indexer,proxy,web,processor-db,monolithic-processor, monitoring COMPOSE_PROJECT_NAME=starter-kit @@ -58,3 +58,14 @@ NEXT_PUBLIC_PROTOKIT_GRAPHQL_URL=https://localhost/graphql # NEXT_PUBLIC_PROTOKIT_GRAPHQL_URL=http://yourdomain.com/graphql NEXT_PUBLIC_PROTOKIT_INDEXER_GRAPHQL_URL=https://localhost/indexer/graphql NEXT_PUBLIC_PROTOKIT_PROCESSOR_GRAPHQL_URL=https://localhost/processor/graphql + +OPEN_TELEMETRY_TRACING_ENABLED=true +OPEN_TELEMETRY_TRACING_URL=http://otel-collector:4317 + +OPEN_TELEMETRY_METRICS_ENABLED=true +OPEN_TELEMETRY_METRICS_PORT=4320 +OPEN_TELEMETRY_METRICS_HOST=0.0.0.0 +OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY=10 + +GF_SECURITY_ADMIN_USER=admin +GF_SECURITY_ADMIN_PASSWORD=grafana \ No newline at end of file diff --git a/packages/chain/src/environments/sovereign/chain.config.ts b/packages/chain/src/environments/sovereign/chain.config.ts index 614f699..441fc8b 100644 --- a/packages/chain/src/environments/sovereign/chain.config.ts +++ b/packages/chain/src/environments/sovereign/chain.config.ts @@ -1,7 +1,12 @@ import { AppChain } from "@proto-kit/sdk"; import { Runtime } from "@proto-kit/module"; import { Protocol } from "@proto-kit/protocol"; -import { DatabasePruneModule, Sequencer } from "@proto-kit/sequencer"; +import { + DatabasePruneModule, + LocalTaskWorkerModule, + Sequencer, + VanillaTaskWorkerModules +} from "@proto-kit/sequencer"; import { PrismaRedisDatabase } from "@proto-kit/persistance"; import runtime from "../../runtime"; import protocol from "../../protocol"; @@ -10,6 +15,8 @@ import { baseSequencerModulesConfig, indexerSequencerModules, indexerSequencerModulesConfig, + metricsSequencerModules, + metricsSequencerModulesConfig, } from "../../sequencer"; import { BullQueue, Startable } from "@proto-kit/deployment"; import { Arguments } from "../../start"; @@ -29,9 +36,11 @@ export const appChain = AppChain.from({ modules: { // ordering of the modules matters due to dependency resolution Database: PrismaRedisDatabase, + LocalTaskWorkerModule: LocalTaskWorkerModule.from(VanillaTaskWorkerModules.withoutSettlement()), + TaskQueue: BullQueue, ...baseSequencerModules, ...indexerSequencerModules, - TaskQueue: BullQueue, + ...metricsSequencerModules, DatabasePruneModule, }, }), @@ -45,6 +54,7 @@ export default async (args: Arguments): Promise => { Sequencer: { ...baseSequencerModulesConfig, ...indexerSequencerModulesConfig, + ...metricsSequencerModulesConfig, DatabasePruneModule: { pruneOnStartup: args.pruneOnStartup, }, @@ -65,6 +75,7 @@ export default async (args: Arguments): Promise => { connection: process.env.DATABASE_URL!, }, }, + LocalTaskWorkerModule: VanillaTaskWorkerModules.defaultConfig() }, ...baseAppChainModulesConfig, }); diff --git a/packages/chain/src/processor/api/resolvers.ts b/packages/chain/src/processor/api/resolvers.ts index 37b281f..a2c2565 100644 --- a/packages/chain/src/processor/api/resolvers.ts +++ b/packages/chain/src/processor/api/resolvers.ts @@ -4,6 +4,7 @@ import { resolvers as generatedResolvers, ResolversEnhanceMap, } from "./generated/type-graphql"; +import {NonEmptyArray} from "type-graphql"; // enhance the generated resolvers with custom middlewares/validations const resolversEnchanceMap: ResolversEnhanceMap = { @@ -22,4 +23,4 @@ const resolversEnchanceMap: ResolversEnhanceMap = { applyResolversEnhanceMap(resolversEnchanceMap); // remove non read only generated resolvers and their methods -export const resolvers = cleanResolvers(generatedResolvers); +export const resolvers: NonEmptyArray = cleanResolvers(generatedResolvers); diff --git a/packages/chain/src/runtime/modules/balances.ts b/packages/chain/src/runtime/modules/balances.ts index ca4ec5a..98a2621 100644 --- a/packages/chain/src/runtime/modules/balances.ts +++ b/packages/chain/src/runtime/modules/balances.ts @@ -1,5 +1,5 @@ -import { runtimeModule, state, runtimeMethod } from "@proto-kit/module"; -import { State, assert } from "@proto-kit/protocol"; +import { runtimeModule, runtimeMethod } from "@proto-kit/module"; +import { State, assert, state } from "@proto-kit/protocol"; import { Balance, Balances as BaseBalances, TokenId } from "@proto-kit/library"; import { PublicKey } from "o1js"; diff --git a/packages/chain/src/sequencer/index.ts b/packages/chain/src/sequencer/index.ts index 900b228..f065b89 100644 --- a/packages/chain/src/sequencer/index.ts +++ b/packages/chain/src/sequencer/index.ts @@ -2,12 +2,14 @@ import { VanillaGraphqlModules, GraphqlSequencerModule, GraphqlServer, + OpenTelemetryServer, } from "@proto-kit/api"; import { PrivateMempool, SequencerModulesRecord, TimedBlockTrigger, BlockProducerModule, + SequencerStartupModule, } from "@proto-kit/sequencer"; import { ModulesConfig } from "@proto-kit/common"; import { IndexerNotifier } from "@proto-kit/indexer"; @@ -28,11 +30,36 @@ export const apiSequencerModulesConfig = { }, } satisfies ModulesConfig; +export const metricsSequencerModules = { + OpenTelemetryServer +} satisfies SequencerModulesRecord; + +export const metricsSequencerModulesConfig = { + OpenTelemetryServer: { + metrics: { + enabled: Boolean(process.env.OPEN_TELEMETRY_METRICS_ENABLED ?? false), + prometheus: { + host: process.env.OPEN_TELEMETRY_METRICS_HOST ?? "localhost", + port: Number(process.env.OPEN_TELEMETRY_METRICS_PORT), + appendTimestamp: true + }, + nodeScrapeInterval: Number(process.env.OPEN_TELEMETRY_METRICS_SCRAPING_FREQUENCY ?? 10), + }, + tracing: { + enabled: Boolean(process.env.OPEN_TELEMETRY_TRACING_ENABLED ?? false), + otlp: { + url: process.env.OPEN_TELEMETRY_TRACING_URL, + }, + }, + }, +} satisfies ModulesConfig; + export const baseSequencerModules = { ...apiSequencerModules, Mempool: PrivateMempool, BlockProducerModule: BlockProducerModule, BlockTrigger: TimedBlockTrigger, + SequencerStartupModule } satisfies SequencerModulesRecord; export const baseSequencerModulesConfig = { @@ -43,6 +70,7 @@ export const baseSequencerModulesConfig = { blockInterval: Number(process.env.PROTOKIT_BLOCK_INTERVAL!), produceEmptyBlocks: true, }, + SequencerStartupModule: {} } satisfies ModulesConfig; export const indexerSequencerModules = {