Skip to content

Commit

Permalink
feat(infra): add opentelemetry metric instrumentation (#1375)
Browse files Browse the repository at this point in the history
* chore: merge main branch

* feat: add codes for automatic instrumentation in client api

* feat(infra): rebase main branch

* chore(infra): merge tracer into metrics

* Revert "chore(infra): merge tracer into metrics"

This reverts commit 5c9d899.

* chore(infra): merge mian

* Revert "feat(infra): rebase main branch"

This reverts commit a65f505.

* feat(infra): iris memory metrics

* refactor(iris): separate application logic from metric-related code

* feat(iris): add CPU metrics in iris

* chore(iris): add comment of asynchronous metrics

* feat(infra): add backend opentelemtry instrumentation for client and admin api

* feat(infra): install packages for opentelemetry instrumentation

* feat(infra): change iris metric exporter url from env not specifying url

* chore(infra): add env of stage-otel

* fix(infra): delete grafana agent otlp endpoint variable

* feat(infra): install nest package for opentelemetry metric instrumentation

* feat(infra): install nest package for opentelemetry metric instrumentation

* feat(infra): install go package for iris opentelemetry metric instrumentation

* feat(infra): add metric.go functions to main which trace.go functions are already included

* feat(infra): add metric.ts functions to main which trace is included for admin and client api

* chore: resolve otel dependency

* chore: resolve otel dependency for iris

* fix(infra): delete files which not in main branch

---------

Co-authored-by: k1g99 <[email protected]>
Co-authored-by: Goathoon <[email protected]>
  • Loading branch information
3 people authored Mar 14, 2024
1 parent f3d0f3d commit 4a586dd
Show file tree
Hide file tree
Showing 10 changed files with 1,574 additions and 1,238 deletions.
2 changes: 2 additions & 0 deletions apps/backend/apps/admin/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { NestFactory } from '@nestjs/core'
import { graphqlUploadExpress } from 'graphql-upload'
import { Logger, LoggerErrorInterceptor } from 'nestjs-pino'
import { AdminModule } from './admin.module'
import startMetricsExporter from './metric'
import tracer from './tracer'

const bootstrap = async () => {
Expand All @@ -14,6 +15,7 @@ const bootstrap = async () => {
console.log('The exporter url is not defined')
} else {
tracer.init()
startMetricsExporter()
}
}

Expand Down
42 changes: 42 additions & 0 deletions apps/backend/apps/admin/src/metric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'
import { HostMetrics } from '@opentelemetry/host-metrics'
import { Resource } from '@opentelemetry/resources'
import {
MeterProvider,
PeriodicExportingMetricReader
} from '@opentelemetry/sdk-metrics'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'

const startMetricsExporter = () => {
const options = {
url: 'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT + '/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',
environment: 'production' // 사용자 정의 속성
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource: resource

Check warning on line 26 in apps/backend/apps/admin/src/metric.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected property shorthand
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
})
)

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

export default startMetricsExporter
3 changes: 3 additions & 0 deletions apps/backend/apps/client/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'
import * as cookieParser from 'cookie-parser'
import { Logger, LoggerErrorInterceptor } from 'nestjs-pino'
import { AppModule } from './app.module'
import startMetricsExporter from './metric'
import tracer from './tracer'

tracer.init()
const bootstrap = async () => {
// otel instrumentation
if (process.env.NODE_ENV == 'production') {
Expand All @@ -16,6 +18,7 @@ const bootstrap = async () => {
console.log('The exporter url is not defined')
} else {
tracer.init()
startMetricsExporter()
}
}

Expand Down
42 changes: 42 additions & 0 deletions apps/backend/apps/client/src/metric.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-http'
import { HostMetrics } from '@opentelemetry/host-metrics'
import { Resource } from '@opentelemetry/resources'
import {
MeterProvider,
PeriodicExportingMetricReader
} from '@opentelemetry/sdk-metrics'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'

const startMetricsExporter = () => {
const options = {
url: 'http://' + process.env.OTEL_EXPORTER_OTLP_ENDPOINT + '/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',
environment: 'production' // 사용자 정의 속성
})

// Creates MeterProvider and installs the exporter as a MetricReader
const meterProvider = new MeterProvider({
resource: resource

Check warning on line 26 in apps/backend/apps/client/src/metric.ts

View workflow job for this annotation

GitHub Actions / Lint

Expected property shorthand
})
meterProvider.addMetricReader(
new PeriodicExportingMetricReader({
exporter,
exportIntervalMillis: 1000
})
)

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

export default startMetricsExporter
5 changes: 4 additions & 1 deletion apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.3.3",
"@nestjs/swagger": "^7.3.0",
"@opentelemetry/api": "^1.7.0",
"@opentelemetry/api": "~1.7.0",
"@opentelemetry/exporter-metrics-otlp-http": "^0.48.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.48.0",
"@opentelemetry/host-metrics": "^0.35.0",
"@opentelemetry/instrumentation-express": "^0.35.0",
"@opentelemetry/instrumentation-http": "^0.48.0",
"@opentelemetry/resources": "^1.21.0",
"@opentelemetry/sdk-metrics": "^1.21.0",
"@opentelemetry/sdk-node": "^0.48.0",
"@opentelemetry/sdk-trace-node": "^1.21.0",
"@opentelemetry/semantic-conventions": "^1.21.0",
Expand Down
23 changes: 15 additions & 8 deletions apps/iris/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ require (
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.4
github.com/rabbitmq/amqp091-go v1.9.0
github.com/redis/go-redis/v9 v9.5.1
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/skkuding/codedang/iris v0.0.0-20240305172235-94f43878c03d
go.opentelemetry.io/otel v1.23.1
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1
go.opentelemetry.io/otel/sdk v1.23.1
go.opentelemetry.io/otel/trace v1.23.1
go.opentelemetry.io/otel v1.24.0
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0
go.opentelemetry.io/otel/metric v1.24.0
go.opentelemetry.io/otel/sdk v1.24.0
go.opentelemetry.io/otel/sdk/metric v1.24.0
go.opentelemetry.io/otel/trace v1.24.0
go.uber.org/zap v1.27.0
)

Expand All @@ -32,16 +36,19 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
go.opentelemetry.io/otel/metric v1.23.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opentelemetry.io/proto/otlp v1.1.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.16.0 // indirect
golang.org/x/sys v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect
google.golang.org/grpc v1.61.0 // indirect
google.golang.org/grpc v1.61.1 // indirect
google.golang.org/protobuf v1.32.0 // indirect
)
47 changes: 31 additions & 16 deletions apps/iris/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
Expand All @@ -57,6 +59,8 @@ github.com/rabbitmq/amqp091-go v1.9.0 h1:qrQtyzB4H8BQgEuJwhmVQqVHB9O4+MNDJCCAcpc
github.com/rabbitmq/amqp091-go v1.9.0/go.mod h1:+jPrT9iY2eLjRaMSRHUhc3z14E/l85kv/f+6luSD3pc=
github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLBh8=
github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/skkuding/codedang/iris v0.0.0-20240305172235-94f43878c03d h1:SPYErTgsS/APakLVJ/AE7V4idFq43SnFgrZ0xd3B6J0=
github.com/skkuding/codedang/iris v0.0.0-20240305172235-94f43878c03d/go.mod h1:XFphgsq64Qx77cgNVQqpUmc3E760bQtj0ibICZNXhEw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand All @@ -65,18 +69,28 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY=
go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 h1:o8iWeVFa1BcLtVEV0LzrCxV2/55tB3xLxADr6Kyoey4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1/go.mod h1:SEVfdK4IoBnbT2FXNM/k8yC08MrfbhWk3U4ljM8B3HE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 h1:cfuy3bXmLJS7M1RZmAL6SuhGtKUp2KEsrm00OlAXkq4=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1/go.mod h1:22jr92C6KwlwItJmQzfixzQM3oyyuYLCfHiMY+rpsPU=
go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo=
go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI=
go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E=
go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk=
go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8=
go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y=
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM=
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8=
go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
Expand All @@ -88,8 +102,9 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
Expand All @@ -99,8 +114,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU=
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY=
google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
Expand Down
6 changes: 6 additions & 0 deletions apps/iris/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"os"
"time"

"github.com/skkuding/codedang/apps/iris/src/connector"
"github.com/skkuding/codedang/apps/iris/src/connector/rabbitmq"
Expand All @@ -16,6 +17,7 @@ import (
"github.com/skkuding/codedang/apps/iris/src/service/sandbox"
"github.com/skkuding/codedang/apps/iris/src/service/testcase"
"github.com/skkuding/codedang/apps/iris/src/utils"
"go.opentelemetry.io/otel"
)

type Env string
Expand All @@ -36,6 +38,10 @@ func main() {
if utils.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT", "") != "" {
shutdown := observability.InitTracer(ctx)
defer shutdown()
observability.SetGlobalMeterProvider()
// Aynchronous Instruments로써, go routine 불필요
observability.GetMemoryMeter(otel.Meter("memory-metrics"))
observability.GetCPUMeter(otel.Meter("cpu-metrics"), 15*time.Second)
} else {
logProvider.Log(logger.INFO, "Cannot find OTEL_EXPORTER_OTLP_ENDPOINT")
}
Expand Down
107 changes: 107 additions & 0 deletions apps/iris/src/observability/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package observability

import (
"context"
"os"
"runtime"
"time"

"github.com/shirou/gopsutil/cpu"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp"
"go.opentelemetry.io/otel/metric"
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.24.0"
)

const defaultMetricDuration time.Duration = 3 * time.Second

func SetGlobalMeterProvider() {
// Create resource.
res, err := newMetricResource()
if err != nil {
panic(err)
}

// Create a meter provider.
// You can pass this instance directly to your instrumented code if it
// accepts a MeterProvider instance.
meterProvider, err := newMeterProvider(res, defaultMetricDuration)
if err != nil {
panic(err)
}

// Register as global meter provider so that it can be used via otel.Meter
// and accessed using otel.GetMeterProvider.
// Most instrumentation libraries use the global meter provider as default.
// If the global meter provider is not set then a no-op implementation
// is used, which fails to generate data.
otel.SetMeterProvider(meterProvider)
}

func newMetricResource() (*resource.Resource, error) {
return resource.Merge(resource.Default(),
resource.NewWithAttributes(semconv.SchemaURL,
semconv.ServiceName("iris-metric"),
semconv.ServiceVersion("0.1.0"),
))
}

func newMeterProvider(res *resource.Resource, second time.Duration) (*sdkmetric.MeterProvider, error) {
// Use OLTP Exporter for Grafana Agent (Recommended)
entryPoint := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
otlpExporter, err := otlpmetrichttp.New(context.Background(), otlpmetrichttp.WithEndpointURL("http://"+entryPoint+"/v1/metrics"))
if err != nil {
return nil, err
}

meterProvider := sdkmetric.NewMeterProvider(
sdkmetric.WithResource(res),
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(otlpExporter,
// Define duration of Metric
sdkmetric.WithInterval(second))),
)
return meterProvider, nil
}

// TODO - Int64ObservableGauge를 Meter로 추상화할 수 있었으면 합니다.
func GetMemoryMeter(meter metric.Meter) {
if _, err := meter.Int64ObservableGauge(
"memory.heap",
metric.WithDescription(
"Memory usage of the allocated heap objects.",
),
metric.WithUnit("By"), // UCUM 규약의 Byte
metric.WithInt64Callback(func(_ context.Context, o metric.Int64Observer) error {
var m runtime.MemStats
runtime.ReadMemStats(&m)
o.Observe(int64(m.HeapAlloc))
return nil
}),
); err != nil {
panic(err)
}
}

func GetCPUMeter(meter metric.Meter, duration time.Duration) {
// 일단 전체 CPU Usage를 추적합니다.
// 추후에, CPU별로 Usage 추적이 필요할 경우 true로 설정합니다.

//Cpu시간을 cpu.comman함수로 ctx를 중지시키고, Duration 차이에 해당하는 CPU time의 차를 계산합니다.
// busy := t.User + t.System + t.Nice + t.Iowait + t.Irq + t.Softirq + t.Steal 시간의 전체를 CPU usage 계산에 사용합니다.
if _, err := meter.Float64ObservableGauge(
"cpu.usage",
metric.WithDescription(
"All CPU",
),
metric.WithUnit("%"),
metric.WithFloat64Callback(func(_ context.Context, o metric.Float64Observer) error {
cpuPercent, _ := cpu.Percent(duration, false)
o.Observe(float64(cpuPercent[0]))
return nil
}),
); err != nil {
panic(err)
}
}
Loading

0 comments on commit 4a586dd

Please sign in to comment.