diff --git a/kubernetes/decoupled/autoscaler-pkg/networkpolicy.yaml b/kubernetes/decoupled/autoscaler-pkg/networkpolicy.yaml index f30d5aac..c308ed06 100644 --- a/kubernetes/decoupled/autoscaler-pkg/networkpolicy.yaml +++ b/kubernetes/decoupled/autoscaler-pkg/networkpolicy.yaml @@ -40,3 +40,23 @@ spec: ports: - protocol: TCP port: 3000 +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-otel-submitter-to-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} +spec: + podSelector: + matchLabels: + app: otel-collector + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + otel-submitter: "true" + ports: + - protocol: TCP + port: 4317 diff --git a/kubernetes/decoupled/autoscaler-pkg/otel-collector/Kptfile b/kubernetes/decoupled/autoscaler-pkg/otel-collector/Kptfile new file mode 100644 index 00000000..f0819ed6 --- /dev/null +++ b/kubernetes/decoupled/autoscaler-pkg/otel-collector/Kptfile @@ -0,0 +1,21 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: otel-collector + annotations: + config.kubernetes.io/local-config: "true" +info: + description: Config for OpenTelemetry Collector component of Spanner autoscaler diff --git a/kubernetes/decoupled/autoscaler-pkg/otel-collector/otel-collector.yaml b/kubernetes/decoupled/autoscaler-pkg/otel-collector/otel-collector.yaml new file mode 100644 index 00000000..ea861f4f --- /dev/null +++ b/kubernetes/decoupled/autoscaler-pkg/otel-collector/otel-collector.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otel-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} + labels: + app: otel-collector +spec: + replicas: 1 + selector: + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + containers: + - name: otel-collector + image: otel/opentelemetry-collector-contrib:0.93.0 + args: + - --config + - /etc/otel/config.yaml + volumeMounts: + - mountPath: /etc/otel/ + name: otel-config + volumes: + - name: otel-config + configMap: + name: otel-config + nodeSelector: + iam.gke.io/gke-metadata-server-enabled: "true" + serviceAccountName: otel-collector-sa + automountServiceAccountToken: true +--- +apiVersion: v1 +kind: Service +metadata: + name: otel-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} +spec: + type: ClusterIP + selector: + app: otel-collector + ports: + - protocol: TCP + port: 4317 + targetPort: 4317 diff --git a/kubernetes/decoupled/autoscaler-pkg/poller/poller-hourly.yaml b/kubernetes/decoupled/autoscaler-pkg/poller/poller-hourly.yaml index 107db992..d446bd3c 100644 --- a/kubernetes/decoupled/autoscaler-pkg/poller/poller-hourly.yaml +++ b/kubernetes/decoupled/autoscaler-pkg/poller/poller-hourly.yaml @@ -25,6 +25,7 @@ spec: metadata: labels: app: poller + otel-submitter: "true" spec: containers: - name: poller @@ -38,6 +39,12 @@ spec: env: - name: AUTOSCALER_CONFIG value: "/etc/autoscaler-config/autoscaler-config-hourly.yaml" + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OLTP_COLLECTOR_URL + value: "http://otel-collector:4713/" volumeMounts: - name: config-volume mountPath: /etc/autoscaler-config diff --git a/kubernetes/decoupled/autoscaler-pkg/poller/poller.yaml b/kubernetes/decoupled/autoscaler-pkg/poller/poller.yaml index 68ce0744..5bd28c97 100644 --- a/kubernetes/decoupled/autoscaler-pkg/poller/poller.yaml +++ b/kubernetes/decoupled/autoscaler-pkg/poller/poller.yaml @@ -25,6 +25,7 @@ spec: metadata: labels: app: poller + otel-submitter: "true" spec: containers: - name: poller @@ -35,6 +36,13 @@ spec: cpu: "250m" limits: memory: "256Mi" + env: + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OLTP_COLLECTOR_URL + value: "http://otel-collector:4713/" volumeMounts: - name: config-volume mountPath: /etc/autoscaler-config diff --git a/kubernetes/decoupled/autoscaler-pkg/scaler/scaler.yaml b/kubernetes/decoupled/autoscaler-pkg/scaler/scaler.yaml index e4dcebf2..2bdb1aab 100644 --- a/kubernetes/decoupled/autoscaler-pkg/scaler/scaler.yaml +++ b/kubernetes/decoupled/autoscaler-pkg/scaler/scaler.yaml @@ -28,6 +28,7 @@ spec: metadata: labels: app: scaler + otel-submitter: "true" spec: containers: - name: scaler @@ -40,6 +41,13 @@ spec: cpu: "100m" limits: memory: "256Mi" + env: + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OLTP_COLLECTOR_URL + value: "http://otel-collector:4713/" nodeSelector: iam.gke.io/gke-metadata-server-enabled: "true" serviceAccountName: scaler-sa diff --git a/kubernetes/unified/autoscaler-pkg/networkpolicy.yaml b/kubernetes/unified/autoscaler-pkg/networkpolicy.yaml index 543e4e05..a7e3dd3c 100644 --- a/kubernetes/unified/autoscaler-pkg/networkpolicy.yaml +++ b/kubernetes/unified/autoscaler-pkg/networkpolicy.yaml @@ -21,3 +21,23 @@ spec: podSelector: {} policyTypes: - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: allow-otel-submitter-to-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} +spec: + podSelector: + matchLabels: + app: otel-collector + policyTypes: + - Ingress + ingress: + - from: + - podSelector: + matchLabels: + otel-submitter: "true" + ports: + - protocol: TCP + port: 4317 diff --git a/kubernetes/unified/autoscaler-pkg/otel-collector/Kptfile b/kubernetes/unified/autoscaler-pkg/otel-collector/Kptfile new file mode 100644 index 00000000..f0819ed6 --- /dev/null +++ b/kubernetes/unified/autoscaler-pkg/otel-collector/Kptfile @@ -0,0 +1,21 @@ +# Copyright 2022 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +apiVersion: kpt.dev/v1 +kind: Kptfile +metadata: + name: otel-collector + annotations: + config.kubernetes.io/local-config: "true" +info: + description: Config for OpenTelemetry Collector component of Spanner autoscaler diff --git a/kubernetes/unified/autoscaler-pkg/otel-collector/otel-collector.yaml b/kubernetes/unified/autoscaler-pkg/otel-collector/otel-collector.yaml new file mode 100644 index 00000000..ea861f4f --- /dev/null +++ b/kubernetes/unified/autoscaler-pkg/otel-collector/otel-collector.yaml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: otel-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} + labels: + app: otel-collector +spec: + replicas: 1 + selector: + matchLabels: + app: otel-collector + template: + metadata: + labels: + app: otel-collector + spec: + containers: + - name: otel-collector + image: otel/opentelemetry-collector-contrib:0.93.0 + args: + - --config + - /etc/otel/config.yaml + volumeMounts: + - mountPath: /etc/otel/ + name: otel-config + volumes: + - name: otel-config + configMap: + name: otel-config + nodeSelector: + iam.gke.io/gke-metadata-server-enabled: "true" + serviceAccountName: otel-collector-sa + automountServiceAccountToken: true +--- +apiVersion: v1 +kind: Service +metadata: + name: otel-collector + namespace: spanner-autoscaler # kpt-set: ${namespace} +spec: + type: ClusterIP + selector: + app: otel-collector + ports: + - protocol: TCP + port: 4317 + targetPort: 4317 diff --git a/kubernetes/unified/autoscaler-pkg/scaler/scaler-hourly.yaml b/kubernetes/unified/autoscaler-pkg/scaler/scaler-hourly.yaml index 9f9c0dc5..24c54a63 100644 --- a/kubernetes/unified/autoscaler-pkg/scaler/scaler-hourly.yaml +++ b/kubernetes/unified/autoscaler-pkg/scaler/scaler-hourly.yaml @@ -25,6 +25,7 @@ spec: metadata: labels: app: scaler + otel-submitter: "true" spec: containers: - name: scaler @@ -38,6 +39,12 @@ spec: env: - name: AUTOSCALER_CONFIG value: "/etc/autoscaler-config/autoscaler-config-hourly.yaml" + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OLTP_COLLECTOR_URL + value: "http://otel-collector:4713/" volumeMounts: - name: config-volume mountPath: /etc/autoscaler-config diff --git a/kubernetes/unified/autoscaler-pkg/scaler/scaler.yaml b/kubernetes/unified/autoscaler-pkg/scaler/scaler.yaml index aea0644a..d5573d4e 100644 --- a/kubernetes/unified/autoscaler-pkg/scaler/scaler.yaml +++ b/kubernetes/unified/autoscaler-pkg/scaler/scaler.yaml @@ -25,6 +25,7 @@ spec: metadata: labels: app: scaler + otel-submitter: "true" spec: containers: - name: scaler @@ -35,6 +36,13 @@ spec: cpu: "250m" limits: memory: "256Mi" + env: + - name: K8S_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OLTP_COLLECTOR_URL + value: "http://otel-collector:4713/" volumeMounts: - name: config-volume mountPath: /etc/autoscaler-config diff --git a/src/autoscaler-common/counters_base.js b/src/autoscaler-common/counters_base.js index 978c380c..bb202fa9 100644 --- a/src/autoscaler-common/counters_base.js +++ b/src/autoscaler-common/counters_base.js @@ -25,7 +25,10 @@ const {MeterProvider, PeriodicExportingMetricReader} = const {Resource} = require('@opentelemetry/resources'); const {MetricExporter: GcpMetricExporter} = require('@google-cloud/opentelemetry-cloud-monitoring-exporter'); -const {GcpDetectorSync} = require('@google-cloud/opentelemetry-resource-util'); +const {OTLPMetricExporter} = + require('@opentelemetry/exporter-metrics-otlp-grpc'); +const {GcpDetectorSync} = + require('@google-cloud/opentelemetry-resource-util'); const {SemanticResourceAttributes} = require('@opentelemetry/semantic-conventions'); const OpenTelemetryApi = require('@opentelemetry/api'); @@ -53,6 +56,11 @@ const AUTOSCALER_RESOURCE_ATTRIBUTES = { [SemanticResourceAttributes.SERVICE_VERSION]: '1.0', }; +const COUNTER_ATTRIBUTE_NAMES = { + SPANNER_PROJECT_ID: 'spanner_project_id', + SPANNER_INSTANCE_ID: 'spanner_project_id', +}; + /** * The prefix to use for any autoscaler counters. */ @@ -179,19 +187,39 @@ async function initMetrics() { await gcpResources.waitForAsyncAttributes(); logger.debug('got GCP resources %o', gcpResources); + + if (process.env.KUBERNETES_SERVICE_HOST) { + if (process.env.K8S_POD_NAME) { + gcpResources[SemanticResourceAttributes.K8S_POD_NAME] = + process.env.K8S_POD_NAME; + } else { + logger.warn('WARNING: running under Kubernetes, but K8S_POD_NAME ' + + 'environment variable is not set. ' + + 'This may lead to duplicate TimeSeries errors'); + } + } + + let exporter; + if (process.env.OLTP_COLLECTOR_URL) { + logger.info(`Counters using OLTP Metrics exporter to ${ + process.env.OLTP_COLLECTOR_URL}`); + exporter = new OTLPMetricExporter({url: process.env.OLTP_COLLECTOR_URL}); + } else { + logger.info('Counters exporting directly to GCP monitoring'); + exporter = new GcpMetricExporter(); + } + meterProvider = new MeterProvider({ resource: new Resource(AUTOSCALER_RESOURCE_ATTRIBUTES) .merge(gcpResources), + readers: [ + new PeriodicExportingMetricReader({ + exportIntervalMillis: PERIODIC_FLUSH_INTERVAL, + exportTimeoutMillis: PERIODIC_FLUSH_INTERVAL, + exporter: exporter, + }), + ], }); - - // Export metrics to GCP. - const gcpMetricExporter = new GcpMetricExporter(); - - meterProvider.addMetricReader(new PeriodicExportingMetricReader({ - exportIntervalMillis: PERIODIC_FLUSH_INTERVAL, - exportTimeoutMillis: PERIODIC_FLUSH_INTERVAL, - exporter: gcpMetricExporter, - })); } catch (e) { // report failures to other waiters. rejectPendingInit(e); @@ -346,6 +374,7 @@ function setTryFlushEnabled(newTryFlushEnabled) { } module.exports = { + COUNTER_ATTRIBUTE_NAMES, createCounters, incCounter, tryFlush, diff --git a/src/autoscaler-common/package-lock.json b/src/autoscaler-common/package-lock.json index 6451ee60..34660f6d 100644 --- a/src/autoscaler-common/package-lock.json +++ b/src/autoscaler-common/package-lock.json @@ -10,6 +10,7 @@ "@google-cloud/logging-bunyan": "^5.0.1", "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.17.0", "@opentelemetry/api": "^1.7.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.48.0", "@opentelemetry/sdk-metrics": "^1.18.0", "@opentelemetry/sdk-node": "^0.45.0", "bunyan": "^1.8.15" @@ -337,11 +338,218 @@ } }, "node_modules/@opentelemetry/core": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.19.0.tgz", - "integrity": "sha512-w42AukJh3TP8R0IZZOVJVM/kMWu8g+lm4LzT70WtuKqhwq7KVhcDzZZuZinWZa6TtQCl7Smt2wolEYzpHabOgw==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.21.0.tgz", + "integrity": "sha512-KP+OIweb3wYoP7qTYL/j5IpOlu52uxBv5M4+QhSmmUfLyTgu1OIS71msK3chFo1D6Y61BIH3wMiMYRCxJCQctA==", "dependencies": { - "@opentelemetry/semantic-conventions": "1.19.0" + "@opentelemetry/semantic-conventions": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.8.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-grpc/-/exporter-metrics-otlp-grpc-0.48.0.tgz", + "integrity": "sha512-DcACDP4keD6hiWI4uMgIo1dFQpxuH9zAwTceB8P8NdZVeOMtP4KyevcwM7FFMZZPd4ha9agsaPFwHk7eCTBcAA==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.21.0", + "@opentelemetry/exporter-metrics-otlp-http": "0.48.0", + "@opentelemetry/otlp-grpc-exporter-base": "0.48.0", + "@opentelemetry/otlp-transformer": "0.48.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/sdk-metrics": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/api-logs": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.48.0.tgz", + "integrity": "sha512-1/aMiU4Eqo3Zzpfwu51uXssp5pzvHFObk8S9pKAiXb1ne8pvg1qxBQitYL1XUiAMEXFzgjaidYG2V6624DRhhw==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.48.0.tgz", + "integrity": "sha512-T4LJND+Ugl87GUONoyoQzuV9qCn4BFIPOnCH1biYqdGhc2JahjuLqVD9aefwLzGBW638iLAo88Lh68h2F1FLiA==", + "dependencies": { + "@opentelemetry/core": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/otlp-grpc-exporter-base": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-grpc-exporter-base/-/otlp-grpc-exporter-base-0.48.0.tgz", + "integrity": "sha512-Vdp56RK9OU+Oeoy3YQC/UMOWglKQ9qvgGr49FgF4r8vk5DlcTUgVS0m3KG8pykmRPA+5ZKaDuqwPw5aTvWmHFw==", + "dependencies": { + "@grpc/grpc-js": "^1.7.1", + "@opentelemetry/core": "1.21.0", + "@opentelemetry/otlp-exporter-base": "0.48.0", + "protobufjs": "^7.2.3" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.48.0.tgz", + "integrity": "sha512-yuoS4cUumaTK/hhxW3JUy3wl2U4keMo01cFDrUOmjloAdSSXvv1zyQ920IIH4lymp5Xd21Dj2/jq2LOro56TJg==", + "dependencies": { + "@opentelemetry/api-logs": "0.48.0", + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/sdk-logs": "0.48.0", + "@opentelemetry/sdk-metrics": "1.21.0", + "@opentelemetry/sdk-trace-base": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.8.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-logs": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.48.0.tgz", + "integrity": "sha512-lRcA5/qkSJuSh4ItWCddhdn/nNbVvnzM+cm9Fg1xpZUeTeozjJDBcHnmeKoOaWRnrGYBdz6UTY6bynZR9aBeAA==", + "dependencies": { + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.8.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-grpc/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.21.0.tgz", + "integrity": "sha512-yrElGX5Fv0umzp8Nxpta/XqU71+jCAyaLk34GmBzNcrW43nqbrqvdPs4gj4MVy/HcTjr6hifCDCYA3rMkajxxA==", + "dependencies": { + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/semantic-conventions": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.8.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.48.0.tgz", + "integrity": "sha512-lZ0gah/WjPpUBVR2Qml8GHraLznsXEpmIS897vdL2IXCxJzGev7sCb9IwAiq89+MgHkuGUWhTWFB2frKrqX1sA==", + "dependencies": { + "@opentelemetry/core": "1.21.0", + "@opentelemetry/otlp-exporter-base": "0.48.0", + "@opentelemetry/otlp-transformer": "0.48.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/sdk-metrics": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/api-logs": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.48.0.tgz", + "integrity": "sha512-1/aMiU4Eqo3Zzpfwu51uXssp5pzvHFObk8S9pKAiXb1ne8pvg1qxBQitYL1XUiAMEXFzgjaidYG2V6624DRhhw==", + "dependencies": { + "@opentelemetry/api": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.48.0.tgz", + "integrity": "sha512-T4LJND+Ugl87GUONoyoQzuV9qCn4BFIPOnCH1biYqdGhc2JahjuLqVD9aefwLzGBW638iLAo88Lh68h2F1FLiA==", + "dependencies": { + "@opentelemetry/core": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.0.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/otlp-transformer": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.48.0.tgz", + "integrity": "sha512-yuoS4cUumaTK/hhxW3JUy3wl2U4keMo01cFDrUOmjloAdSSXvv1zyQ920IIH4lymp5Xd21Dj2/jq2LOro56TJg==", + "dependencies": { + "@opentelemetry/api-logs": "0.48.0", + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/sdk-logs": "0.48.0", + "@opentelemetry/sdk-metrics": "1.21.0", + "@opentelemetry/sdk-trace-base": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.8.0" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-logs": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.48.0.tgz", + "integrity": "sha512-lRcA5/qkSJuSh4ItWCddhdn/nNbVvnzM+cm9Fg1xpZUeTeozjJDBcHnmeKoOaWRnrGYBdz6UTY6bynZR9aBeAA==", + "dependencies": { + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.8.0", + "@opentelemetry/api-logs": ">=0.39.1" + } + }, + "node_modules/@opentelemetry/exporter-metrics-otlp-http/node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.21.0.tgz", + "integrity": "sha512-yrElGX5Fv0umzp8Nxpta/XqU71+jCAyaLk34GmBzNcrW43nqbrqvdPs4gj4MVy/HcTjr6hifCDCYA3rMkajxxA==", + "dependencies": { + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0", + "@opentelemetry/semantic-conventions": "1.21.0" }, "engines": { "node": ">=14" @@ -847,12 +1055,12 @@ } }, "node_modules/@opentelemetry/resources": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.19.0.tgz", - "integrity": "sha512-RgxvKuuMOf7nctOeOvpDjt2BpZvZGr9Y0vf7eGtY5XYZPkh2p7e2qub1S2IArdBMf9kEbz0SfycqCviOu9isqg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.21.0.tgz", + "integrity": "sha512-1Z86FUxPKL6zWVy2LdhueEGl9AHDJcx+bvHStxomruz6Whd02mE3lNUMjVJ+FGRoktx/xYQcxccYb03DiUP6Yw==", "dependencies": { - "@opentelemetry/core": "1.19.0", - "@opentelemetry/semantic-conventions": "1.19.0" + "@opentelemetry/core": "1.21.0", + "@opentelemetry/semantic-conventions": "1.21.0" }, "engines": { "node": ">=14" @@ -915,12 +1123,12 @@ } }, "node_modules/@opentelemetry/sdk-metrics": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.19.0.tgz", - "integrity": "sha512-FiMii40zr0Fmys4F1i8gmuCvbinBnBsDeGBr4FQemOf0iPCLytYQm5AZJ/nn4xSc71IgKBQwTFQRAGJI7JvZ4Q==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.21.0.tgz", + "integrity": "sha512-on1jTzIHc5DyWhRP+xpf+zrgrREXcHBH4EDAfaB5mIG7TWpKxNXooQ1JCylaPsswZUv4wGnVTinr4HrBdGARAQ==", "dependencies": { - "@opentelemetry/core": "1.19.0", - "@opentelemetry/resources": "1.19.0", + "@opentelemetry/core": "1.21.0", + "@opentelemetry/resources": "1.21.0", "lodash.merge": "^4.6.2" }, "engines": { @@ -1104,9 +1312,9 @@ } }, "node_modules/@opentelemetry/semantic-conventions": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.19.0.tgz", - "integrity": "sha512-14jRpC8f5c0gPSwoZ7SbEJni1PqI+AhAE8m1bMz6v+RPM4OlP1PT2UHBJj5Qh/ALLPjhVU/aZUK3YyjTUqqQVg==", + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.21.0.tgz", + "integrity": "sha512-lkC8kZYntxVKr7b8xmjCVUgE0a8xgDakPyDo9uSWavXPyYqLgYYGdEd2j8NxihRyb6UwpX3G/hFUF4/9q2V+/g==", "engines": { "node": ">=14" } diff --git a/src/autoscaler-common/package.json b/src/autoscaler-common/package.json index 6e195e7c..2a96b91d 100644 --- a/src/autoscaler-common/package.json +++ b/src/autoscaler-common/package.json @@ -4,11 +4,12 @@ "license": "Apache-2.0", "author": "Google Inc.", "dependencies": { - "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.17.0", - "@opentelemetry/api": "^1.7.0", - "@opentelemetry/sdk-metrics": "^1.18.0", - "@opentelemetry/sdk-node": "^0.45.0", - "@google-cloud/logging-bunyan": "^5.0.1", - "bunyan": "^1.8.15" + "@google-cloud/logging-bunyan": "^5.0.1", + "@google-cloud/opentelemetry-cloud-monitoring-exporter": "^0.17.0", + "@opentelemetry/api": "^1.7.0", + "@opentelemetry/exporter-metrics-otlp-grpc": "^0.48.0", + "@opentelemetry/sdk-metrics": "^1.18.0", + "@opentelemetry/sdk-node": "^0.45.0", + "bunyan": "^1.8.15" } - } +} diff --git a/src/poller/poller-core/counters.js b/src/poller/poller-core/counters.js index ee44835f..68ce5805 100644 --- a/src/poller/poller-core/counters.js +++ b/src/poller/poller-core/counters.js @@ -72,8 +72,10 @@ const pendingInit = CountersBase.createCounters(COUNTERS); */ function _getCounterAttributes(spanner) { return { - 'projectId': spanner.projectId, - 'instanceId': spanner.instanceId, + [CountersBase.COUNTER_ATTRIBUTE_NAMES.SPANNER_PROJECT_ID]: + spanner.projectId, + [CountersBase.COUNTER_ATTRIBUTE_NAMES.SPANNER_INSTANCE_ID]: + spanner.instanceId, }; } diff --git a/src/scaler/scaler-core/counters.js b/src/scaler/scaler-core/counters.js index a2309638..955edb71 100644 --- a/src/scaler/scaler-core/counters.js +++ b/src/scaler/scaler-core/counters.js @@ -31,6 +31,12 @@ const COUNTER_NAMES = { REQUESTS_FAILED: COUNTERS_PREFIX + 'requests-failed', }; +const ATTRIBUTE_NAMES = { + ...CountersBase.COUNTER_ATTRIBUTE_NAMES, + SCALING_DENIED_REASON: 'scaling_denied_reason', + SCALING_METHOD: 'scaling_method', + SCALING_DIRECTION: 'scaling_direction', +}; /** * @typedef {import('../../autoscaler-common/types.js') @@ -79,10 +85,10 @@ const pendingInit = CountersBase.createCounters(COUNTERS); */ function _getCounterAttributes(spanner, requestedSize) { return { - 'projectId': spanner.projectId, - 'instanceId': spanner.instanceId, - 'method': spanner.scalingMethod, - 'direction': + [ATTRIBUTE_NAMES.SPANNER_PROJECT_ID]: spanner.projectId, + [ATTRIBUTE_NAMES.SPANNER_INSTANCE_ID]: spanner.instanceId, + [ATTRIBUTE_NAMES.SCALING_METHOD]: spanner.scalingMethod, + [ATTRIBUTE_NAMES.SCALING_DIRECTION]: requestedSize > spanner.currentSize ? 'SCALE_UP' : requestedSize < spanner.currentSize ? 'SCALE_DOWN' : 'SCALE_SAME', }; @@ -124,7 +130,7 @@ async function incScalingDeniedCounter(spanner, requestedSize, reason) { await pendingInit; CountersBase.incCounter(COUNTER_NAMES.SCALING_DENIED, { ..._getCounterAttributes(spanner, requestedSize), - 'reason': reason, + [ATTRIBUTE_NAMES.SCALING_DENIED_REASON]: reason, }); }