Skip to content

Commit

Permalink
feat(infra): get ec2 instance id and send to monitoring system by usi…
Browse files Browse the repository at this point in the history
…ng label (#1631)

* feat(infra): get ec2 instance id and send to grafana agent by using resource label

* feat(infra): get ec2 instance id and send to grafana agent by using resource label for admin api

* feat(infra): get ec2 instance id of Iris Server

* fix(infra): delete specifying data type

---------

Co-authored-by: Goathoon <[email protected]>
  • Loading branch information
ssupecial and goathoon authored Apr 4, 2024
1 parent ea3bdda commit fbd90b6
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 59 deletions.
87 changes: 61 additions & 26 deletions apps/backend/apps/admin/src/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,73 @@ import {
PeriodicExportingMetricReader
} from '@opentelemetry/sdk-metrics'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import * as http from 'http'

const startMetricsExporter = () => {
const options = {
url:
'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT_URL + '/v1/metrics', // Grafana Agent Metric을 받는 url
headers: {},
concurrencyLimit: 5
}
const exporter = new OTLPMetricExporter(options)
const getInstanceId = (): Promise<string> => {
return new Promise((resolve, reject) => {
const options = {
hostname: '169.254.169.254',
path: '/latest/meta-data/instance-id',
method: 'GET',
timeout: 1000
}

const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'backend-admin-metric',
[SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
environment: 'production' // 사용자 정의 속성
})
const req = http.request(options, (res) => {
let data = ''
res.on('data', (chunk: Buffer) => {
data += chunk.toString()
})
res.on('end', () => {
resolve(data)
})
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource: resource
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
req.on('error', (error: Error) => {
console.error(error)
reject(error)
})
)

const hostMetrics = new HostMetrics({
meterProvider,
name: 'backend-admin-host-metric'
req.end()
})
hostMetrics.start()
}

const startMetricsExporter = async () => {
try {
const instanceId = await getInstanceId()
const options = {
url:
'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT_URL + '/v1/metrics', // Grafana Agent Metric을 받는 url
headers: {},
concurrencyLimit: 5
}
const exporter = new OTLPMetricExporter(options)

const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'backend-admin-metric',
[SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: instanceId,
environment: 'production' // 사용자 정의 속성
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
})
)

const hostMetrics = new HostMetrics({
meterProvider,
name: 'backend-admin-host-metric'
})
hostMetrics.start()
} catch (e) {
console.error('Failed to initialize the metric', e)
}
}

export default startMetricsExporter
87 changes: 61 additions & 26 deletions apps/backend/apps/client/src/metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,73 @@ import {
PeriodicExportingMetricReader
} from '@opentelemetry/sdk-metrics'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import * as http from 'http'

const startMetricsExporter = () => {
const options = {
url:
'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT_URL + '/v1/metrics', // Grafana Agent Metric을 받는 url
headers: {},
concurrencyLimit: 5
}
const exporter = new OTLPMetricExporter(options)
const getInstanceId = (): Promise<string> => {
return new Promise((resolve, reject) => {
const options = {
hostname: '169.254.169.254',
path: '/latest/meta-data/instance-id',
method: 'GET',
timeout: 1000
}

const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'backend-client-metric',
[SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
environment: 'production' // 사용자 정의 속성
})
const req = http.request(options, (res) => {
let data = ''
res.on('data', (chunk: Buffer) => {
data += chunk.toString()
})
res.on('end', () => {
resolve(data)
})
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource: resource
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
req.on('error', (error: Error) => {
console.error(error)
reject(error)
})
)

const hostMetrics = new HostMetrics({
meterProvider,
name: 'backend-client-host-metric'
req.end()
})
hostMetrics.start()
}

const startMetricsExporter = async () => {
try {
const instanceId = await getInstanceId()
const options = {
url:
'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT_URL + '/v1/metrics', // Grafana Agent Metric을 받는 url
headers: {},
concurrencyLimit: 5
}
const exporter = new OTLPMetricExporter(options)

const resource = new Resource({
[SemanticResourceAttributes.SERVICE_NAME]: 'backend-client-metric',
[SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0',
[SemanticResourceAttributes.SERVICE_INSTANCE_ID]: instanceId,
environment: 'production' // 사용자 정의 속성
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
})
)

const hostMetrics = new HostMetrics({
meterProvider,
name: 'backend-client-host-metric'
})
hostMetrics.start()
} catch (e) {
console.error('Failed to initialize the metric', e)
}
}

export default startMetricsExporter
20 changes: 13 additions & 7 deletions apps/iris/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ module github.com/skkuding/codedang/apps/iris
go 1.21

require (
github.com/aws/aws-sdk-go-v2 v1.26.0
github.com/aws/aws-sdk-go-v2/credentials v1.17.9
github.com/aws/aws-sdk-go-v2 v1.26.1
github.com/aws/aws-sdk-go-v2/credentials v1.17.10
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0
github.com/rabbitmq/amqp091-go v1.9.0
github.com/redis/go-redis/v9 v9.5.1
Expand All @@ -23,14 +23,20 @@ require (

require (
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.10 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.4 // indirect
github.com/aws/smithy-go v1.20.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 // indirect
github.com/aws/smithy-go v1.20.2 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
Expand Down
26 changes: 26 additions & 0 deletions apps/iris/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,42 @@ github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v
github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA=
github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo=
github.com/aws/aws-sdk-go-v2/config v1.27.10 h1:PS+65jThT0T/snC5WjyfHHyUgG+eBoupSDV+f838cro=
github.com/aws/aws-sdk-go-v2/config v1.27.10/go.mod h1:BePM7Vo4OBpHreKRUMuDXX+/+JWP38FLkzl5m27/Jjs=
github.com/aws/aws-sdk-go-v2/credentials v1.17.7 h1:WJd+ubWKoBeRh7A5iNMnxEOs982SyVKOJD+K8HIezu4=
github.com/aws/aws-sdk-go-v2/credentials v1.17.7/go.mod h1:UQi7LMR0Vhvs+44w5ec8Q+VS+cd10cjwgHwiVkE0YGU=
github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao=
github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ=
github.com/aws/aws-sdk-go-v2/credentials v1.17.10 h1:qDZ3EA2lv1KangvQB6y258OssCHD0xvaGiEDkG4X/10=
github.com/aws/aws-sdk-go-v2/credentials v1.17.10/go.mod h1:6t3sucOaYDwDssHQa0ojH1RpmVmF5/jArkye1b2FKMI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3 h1:ifbIbHZyGl1alsAhPIYsHOg5MuApgqOvVeI8wIugXfs=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.3/go.mod h1:oQZXg3c6SNeY6OZrDY+xHcF4VGIEoNotX2B4PrDeoJI=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4/go.mod h1:84KyjNZdHC6QZW08nfHI6yZgPd+qRgaWcYsyLUo3QY8=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3 h1:Qvodo9gHG9F3E8SfYOspPeBt0bjSbsevK8WhRAUHcoY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.3/go.mod h1:vCKrdLXtybdf/uQd/YfVR2r5pcbNuEYKzMQpcxmeSJw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4 h1:sHmMWWX5E7guWEFQ9SVo6A3S4xpPrWnd77a6y4WM6PU=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.4/go.mod h1:WjpDrhWisWOIoS9n3nk67A3Ll1vfULJ9Kq6h29HTD48=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3 h1:mDnFOE2sVkyphMWtTH+stv0eW3k0OTx94K63xpxHty4=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.3/go.mod h1:V8MuRVcCRt5h1S+Fwu8KbC7l/gBGo3yBAyUbJM2IJOk=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4 h1:SIkD6T4zGQ+1YIit22wi37CGNkrE7mXV1vNA5VpI3TI=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.4/go.mod h1:XfeqbsG0HNedNs0GT+ju4Bs+pFAwsrlzcRdMvdNVf5s=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5 h1:mbWNpfRUTT6bnacmvOTKXZjR/HycibdWzNpfbrbLDIs=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.5/go.mod h1:FCOPWGjsshkkICJIn9hq9xr6dLKtyaWpuUojiN3W1/8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.6 h1:NkHCgg0Ck86c5PTOzBZ0JRccI51suJDg5lgFtxBu1ek=
Expand All @@ -30,6 +46,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5 h1:K/NXvIftO
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.5/go.mod h1:cl9HGLV66EnCmMNzq4sYOti+/xo8w34CsgzVtm2GgsY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3 h1:4t+QEX7BsXz98W8W1lNvMAG+NX8qHz2CjLBxQKku40g=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.3/go.mod h1:oFcjjUq5Hm09N9rpxTdeMeLeQcxS7mIkBkL8qUKng+A=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.4 h1:uDj2K47EM1reAYU9jVlQ1M5YENI1u6a/TxJpf6AeOLA=
Expand All @@ -40,8 +58,16 @@ github.com/aws/aws-sdk-go-v2/service/s3 v1.52.1 h1:Y/TTvxMdYwNvhzolvneV1wEEN/ncQ
github.com/aws/aws-sdk-go-v2/service/s3 v1.52.1/go.mod h1:MGTaf3x/+z7ZGugCGvepnx2DS6+caCYYqKhzVoLNYPk=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0 h1:r3o2YsgW9zRcIP3Q0WCmttFVhTuugeKIvT5z9xDspc0=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.0/go.mod h1:w2E4f8PUfNtyjfL6Iu+mWI96FGttE03z3UdNcUEC4tA=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 h1:WzFol5Cd+yDxPAdnzTA5LmpHYSWinhmSj4rQChV0ee8=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw=
github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
Expand Down
32 changes: 32 additions & 0 deletions apps/iris/src/observability/metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package observability

import (
"context"
"io"
"os"
"runtime"
"time"
Expand All @@ -13,6 +14,9 @@ import (
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"

"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
)

const defaultMetricDuration time.Duration = 3 * time.Second
Expand Down Expand Up @@ -45,6 +49,7 @@ func newMetricResource() (*resource.Resource, error) {
resource.NewWithAttributes(semconv.SchemaURL,
semconv.ServiceName("iris-metric"),
semconv.ServiceVersion("0.1.0"),
semconv.ServiceInstanceID(getInstanceId()),
))
}

Expand Down Expand Up @@ -105,3 +110,30 @@ func GetCPUMeter(meter metric.Meter, duration time.Duration) {
reportErr(err, "failed to create CPU meter")
}
}

func getInstanceId() string {
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
reportErr(err, "failed to get Config Of AWS")
return "Instance-Id-Not-Found"
}

client := imds.NewFromConfig(cfg)
output, err := client.GetMetadata(context.TODO(), &imds.GetMetadataInput{
Path: "instance-id",
})

if err != nil {
reportErr(err, "failed to get Instance Id")
return "Instance-Id-Not-Found"
}

defer output.Content.Close()

bytes, err := io.ReadAll(output.Content)
if err != nil {
reportErr(err, "failed to Type Cast from Metadata Output to String")
return "Instance-Id-Not-Found"
}
return string(bytes)
}

0 comments on commit fbd90b6

Please sign in to comment.