Skip to content

Commit

Permalink
Instrument databases (Postgres, Redis, Mongo) and send metrics to Coroot
Browse files Browse the repository at this point in the history
  • Loading branch information
apetruhin committed Jun 26, 2024
1 parent 52a7e7d commit 88adf15
Show file tree
Hide file tree
Showing 26 changed files with 2,983 additions and 315 deletions.
55 changes: 0 additions & 55 deletions .github/workflows/build.yml

This file was deleted.

25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Continuous Integration

on:
pull_request:
push:
branches:
- main

jobs:
GO:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: gofmt -l .
run: files=$(gofmt -l .); if [[ -n "$files" ]]; then echo "$files"; exit 1; fi
- name: goimports -l .
run: |
go install golang.org/x/tools/cmd/goimports@latest
files=$(goimports -l .); if [[ -n "$files" ]]; then echo "$files"; exit 1; fi
- run: go vet ./...
- run: go test ./...
- run: go build -mod=readonly .
93 changes: 93 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Release

on:
release:
types: [created]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
packages: write

steps:
- uses: actions/checkout@v4

- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3

- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
- uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
build-args: |
VERSION=${{ steps.meta.outputs.version }}
- name: extract amd64 binary from the image
run: |
docker create --platform linux/amd64 --name amd64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} &&
docker cp amd64:/usr/bin/coroot-cluster-agent /tmp/coroot-cluster-agent-amd64
- name: extract arm64 binary from the image
run: |
docker create --platform linux/arm64 --name arm64 ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} &&
docker cp arm64:/usr/bin/coroot-cluster-agent /tmp/coroot-cluster-agent-arm64
- name: upload amd64 binary
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: /tmp/coroot-cluster-agent-amd64
asset_name: coroot-cluster-agent-amd64
asset_content_type: application/octet-stream

- name: upload arm64 binary
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: /tmp/coroot-cluster-agent-arm64
asset_name: coroot-cluster-agent-arm64
asset_content_type: application/octet-stream

- uses: actions/github-script@v7
env:
RELEASE_ID: ${{ github.event.release.id }}
with:
script: |
const { RELEASE_ID } = process.env
github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: `${RELEASE_ID}`,
prerelease: false,
make_latest: true
})
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
/.idea/
/config.yaml
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ COPY go.sum .
RUN go mod download
COPY . .
ARG VERSION=unknown
RUN go build -mod=readonly -ldflags "-X main.version=$VERSION" -o /tmp/coroot-cluster-agent .
RUN go build -mod=readonly -ldflags "-X main.version=$VERSION" -o coroot-cluster-agent .


FROM debian:bullseye
RUN apt update && apt install -y ca-certificates && apt clean

COPY --from=builder /tmp/coroot-cluster-agent /coroot-cluster-agent
COPY --from=builder /tmp/src/coroot-cluster-agent /usr/bin/coroot-cluster-agent

ENTRYPOINT ["/coroot-cluster-agent", "config.yaml"]
ENTRYPOINT ["coroot-cluster-agent"]
31 changes: 31 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package common

import (
"net/http"

"github.com/prometheus/client_golang/prometheus"
)

func AuthHeaders(apiKey string) map[string]string {
return map[string]string{
"X-Api-Key": apiKey,
}
}

func SetAuthHeaders(r *http.Request, apiKey string) {
for k, v := range AuthHeaders(apiKey) {
r.Header.Set(k, v)
}
}

func Desc(name, help string, labels ...string) *prometheus.Desc {
return prometheus.NewDesc(name, help, labels, nil)
}

func Gauge(desc *prometheus.Desc, value float64, labels ...string) prometheus.Metric {
return prometheus.MustNewConstMetric(desc, prometheus.GaugeValue, value, labels...)
}

func Counter(desc *prometheus.Desc, value float64, labels ...string) prometheus.Metric {
return prometheus.MustNewConstMetric(desc, prometheus.CounterValue, value, labels...)
}
55 changes: 0 additions & 55 deletions config.go

This file was deleted.

89 changes: 89 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package config

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"

"github.com/coroot/coroot-cluster-agent/common"
"github.com/coroot/coroot-cluster-agent/flags"
"github.com/coroot/coroot/model"
"k8s.io/klog"
)

type Listener interface {
ListenConfigUpdates(updates <-chan model.Config)
}

type Updater struct {
endpoint *url.URL
apiKey string
updateInterval time.Duration
httpClient *http.Client
subscribers []chan<- model.Config
}

func NewUpdater() (*Updater, error) {
c := &Updater{
endpoint: (*flags.CorootURL).JoinPath("/v1/config"),
apiKey: *flags.APIKey,
updateInterval: *flags.ConfigUpdateInterval,
httpClient: &http.Client{Timeout: *flags.ConfigUpdateTimeout},
}
klog.Infof("endpoint: %s, update interval: %s", c.endpoint, c.updateInterval)

return c, nil
}

func (u *Updater) Subscribe(l Listener) {
ch := make(chan model.Config)
l.ListenConfigUpdates(ch)
u.subscribers = append(u.subscribers, ch)
}

func (u *Updater) Start() {
go func() {
ticker := time.NewTicker(u.updateInterval)
defer ticker.Stop()
for {
cfg, err := u.fetchConfig()
if err != nil {
klog.Error(err)
} else {
for _, s := range u.subscribers {
s <- *cfg
}
}
<-ticker.C
}
}()
}

func (u *Updater) Stop() {
for _, s := range u.subscribers {
close(s)
}
}

func (u *Updater) fetchConfig() (*model.Config, error) {
req, err := http.NewRequest(http.MethodGet, u.endpoint.String(), nil)
if err != nil {
return nil, err
}
common.SetAuthHeaders(req, u.apiKey)
resp, err := u.httpClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("%d: %s", resp.StatusCode, string(body))
}
var cfg model.Config
err = json.NewDecoder(resp.Body).Decode(&cfg)
return &cfg, err
}
Loading

0 comments on commit 88adf15

Please sign in to comment.