Compare commits
156 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4732aa5ab2 | |||
| c00564cdcb | |||
| 2836af0242 | |||
| 212369811f | |||
| afac050279 | |||
| afa847c76c | |||
| fff76c4acc | |||
| 7bc3101cee | |||
| a8a8d53cd1 | |||
| 485b8434d8 | |||
| 9dce38187c | |||
| 33f22237dc | |||
| 4bbd8b3e63 | |||
| ec0ea2a287 | |||
| dc4bc4a98c | |||
| e92f853311 | |||
| a6660fd70d | |||
| cbf01d4546 | |||
| cfab683ab8 | |||
| 4a6c014206 | |||
| 88ae10c9d7 | |||
| f1cfd58922 | |||
| d5528d3635 | |||
| 15cff2329e | |||
| 4e2f496f5d | |||
| 2d55da0fb9 | |||
| af15b97d05 | |||
| 0bc2b48f20 | |||
| 65a41418c6 | |||
| 235083bb95 | |||
| 4ce727b275 | |||
|
54e7739ea5
|
|||
| 8a0fd9c60d | |||
| 94fb394035 | |||
| c95ba47672 | |||
| f96bd92aa7 | |||
| d7261826b4 | |||
| f7defd4f23 | |||
| 32933694ed | |||
| 7c44181434 | |||
| 1572b26c7a | |||
| b6045ca52b | |||
| 094003d561 | |||
| 9491c7db2a | |||
| 0d38fbd8bf | |||
| f2ed1a375b | |||
| db3eac9a0f | |||
| e6a193f514 | |||
| 4270e528b6 | |||
| c2f7b9e8d5 | |||
| fb62d12e35 | |||
| 4aa3e361b5 | |||
| 639148e40a | |||
| ca8c3a9e1b | |||
|
8540caba8c
|
|||
| a66446b1df | |||
|
06aaa0c202
|
|||
| bfbe6a09e5 | |||
| 026a08d54e | |||
| 10282596e2 | |||
| 8271687580 | |||
| ae2ca7265b | |||
| 608ad2b582 | |||
| 7c1b3bf801 | |||
| 95d1a52df6 | |||
| 23c3deb623 | |||
|
450cc99f41
|
|||
| 2b5127d91a | |||
| 8b71dd6f20 | |||
| 467bdd7b69 | |||
| 689df41ded | |||
| 4e4cc1c29d | |||
| e440a290da | |||
| 8a2c1d071c | |||
| 98cba7621d | |||
|
8c4db543ad
|
|||
| 70554e246e | |||
|
da69271e82
|
|||
| 3926b6133e | |||
| aa582b6706 | |||
| a48d4242b3 | |||
| 0a91d34815 | |||
| 68b2008b64 | |||
| 0711246d48 | |||
| 94bbb2c47e | |||
|
e05d98d150
|
|||
| c52dc55424 | |||
| 19501ac53c | |||
| cd7f54fdc0 | |||
| 9afaed7327 | |||
| 6625f62f31 | |||
| 6223e21298 | |||
| dc7aa8167f | |||
| 6e08b444a4 | |||
| 690c82e1e0 | |||
| bec0687fcc | |||
| 44069beeca | |||
| 514ae1068c | |||
| 6f52e9679f | |||
| 8f640c4064 | |||
| 6389fcf8ec | |||
| d3efe93ba7 | |||
| aa0648930e | |||
| b09779cff9 | |||
| f64928d986 | |||
| d6f270a604 | |||
| a0cc0518be | |||
|
a0e1ad35b3
|
|||
| 0009c127aa | |||
| ba19e0f7af | |||
| 64f85981a6 | |||
| e7f1a833d2 | |||
| 2d8cdeea67 | |||
| e294e8b19d | |||
| 035158446f | |||
| e3cae200f4 | |||
| 76eb95d80c | |||
| 22050d0ddd | |||
| 71ce43937e | |||
| 7437674e4b | |||
| 7327aa4bf1 | |||
| 73cd72775a | |||
| 56b9f16391 | |||
| 119f382de2 | |||
| 703a34baa9 | |||
| f0425653cf | |||
| ed51ca54b5 | |||
| 10ab7bf109 | |||
| a7a03d33ae | |||
| 8c40221d60 | |||
| be2ebb1dad | |||
| d9de35bf31 | |||
| c338c54ad0 | |||
| 0bfb84db45 | |||
| cfe5dc727d | |||
| abe839c325 | |||
| 12afc55b6c | |||
| ef740ec281 | |||
| 5234120fa9 | |||
| a7c50ed3c1 | |||
| af3a313ed4 | |||
| 1e6f84a61c | |||
| 61cebcb83a | |||
| a39cebbc5a | |||
| fe51eae18f | |||
| dd0868749f | |||
| e1fbf1461c | |||
| c7ccab5e27 | |||
| 216627d83b | |||
| eaeae4bd09 | |||
|
ddadf63cab
|
|||
| 52ba3460dc | |||
| 2c3cdc34af | |||
| 0707a6aab7 | |||
| 0c495ce1d5 | |||
| 4ecc1bf12b |
@@ -0,0 +1,81 @@
|
|||||||
|
name: otelsetup
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: 'stable'
|
||||||
|
- name: Run tests
|
||||||
|
run: go test -race -coverprofile=coverage.txt ./...
|
||||||
|
|
||||||
|
- name: Check coverage
|
||||||
|
id: coverage
|
||||||
|
run: |
|
||||||
|
go install github.com/vladopajic/go-test-coverage/v2@latest
|
||||||
|
go-test-coverage --config ./.testcoverage.yml --github-action-output
|
||||||
|
- name: Download baseline coverage
|
||||||
|
if: gitea.event_name == 'pull_request'
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
name: coverage-baseline
|
||||||
|
path: ./baseline
|
||||||
|
continue-on-error: true
|
||||||
|
- name: Compare coverage
|
||||||
|
if: gitea.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
CURRENT="${{ steps.coverage.outputs.total-coverage }}"
|
||||||
|
if [ -f ./baseline/coverage.txt ]; then
|
||||||
|
BASE=$(cat ./baseline/coverage.txt)
|
||||||
|
echo "Base coverage: ${BASE}%"
|
||||||
|
echo "Current coverage: ${CURRENT}%"
|
||||||
|
if [ "$(echo "$CURRENT < $BASE" | bc -l)" -eq 1 ]; then
|
||||||
|
echo "::error::Coverage decreased from ${BASE}% to ${CURRENT}%"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Coverage maintained or improved: ${BASE}% -> ${CURRENT}%"
|
||||||
|
else
|
||||||
|
echo "No baseline coverage found, skipping comparison"
|
||||||
|
echo "Current coverage: ${CURRENT}%"
|
||||||
|
fi
|
||||||
|
- name: Save coverage baseline
|
||||||
|
if: gitea.ref == 'refs/heads/main'
|
||||||
|
run: echo "${{ steps.coverage.outputs.total-coverage }}" > coverage.txt
|
||||||
|
- name: Upload coverage baseline
|
||||||
|
if: gitea.ref == 'refs/heads/main'
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: coverage-baseline
|
||||||
|
path: coverage.txt
|
||||||
|
retention-days: 90
|
||||||
|
- name: Post coverage comment
|
||||||
|
if: gitea.event_name == 'pull_request'
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
GITEA_URL: ${{ gitea.server_url }}
|
||||||
|
run: |
|
||||||
|
COVERAGE="${{ steps.coverage.outputs.total-coverage }}"
|
||||||
|
curl -X POST "${GITEA_URL}/api/v1/repos/${{ gitea.repository }}/issues/${{ gitea.event.pull_request.number }}/comments" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"body\": \"## Coverage Report\n\nTotal coverage: **${COVERAGE}%**\"}"
|
||||||
|
|
||||||
|
vulnerabilities:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: 'stable'
|
||||||
|
- name: Check vulnerabilities
|
||||||
|
run: |
|
||||||
|
go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
govulncheck ./...
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
name: pre-commit
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
SKIP: no-commit-to-branch
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: stable
|
||||||
|
- uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: '3.14'
|
||||||
|
- name: Install goimports
|
||||||
|
run: go install golang.org/x/tools/cmd/goimports@latest
|
||||||
|
- uses: pre-commit/action@v3.0.1
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
uses: unboundsoftware/shared-workflows/.gitea/workflows/Release.yml@main
|
||||||
@@ -1,2 +1,3 @@
|
|||||||
.idea
|
.idea
|
||||||
|
.claude
|
||||||
/release
|
/release
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
include:
|
|
||||||
- template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
|
|
||||||
- project: unboundsoftware/ci-templates
|
|
||||||
file: Defaults.gitlab-ci.yml
|
|
||||||
- project: unboundsoftware/ci-templates
|
|
||||||
file: Release.gitlab-ci.yml
|
|
||||||
- project: unboundsoftware/ci-templates
|
|
||||||
file: Pre-Commit-Go.gitlab-ci.yml
|
|
||||||
|
|
||||||
image: amd64/golang:1.25.1@sha256:53f7808857782118f3a062261f721507dfa36e5c545e5d39c2dcf9916e3f0b1b
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- deps
|
|
||||||
- test
|
|
||||||
|
|
||||||
deps:
|
|
||||||
stage: deps
|
|
||||||
script:
|
|
||||||
- go mod download
|
|
||||||
|
|
||||||
test:
|
|
||||||
stage: test
|
|
||||||
dependencies:
|
|
||||||
- deps
|
|
||||||
script:
|
|
||||||
- CGO_ENABLED=1 go test -mod=readonly -race -coverprofile=coverage.txt -covermode=atomic -coverpkg=$(go list ./... | tr '\n' , | sed 's/,$//') ./...
|
|
||||||
- go tool cover -html=coverage.txt -o coverage.html
|
|
||||||
- go tool cover -func=coverage.txt
|
|
||||||
- curl -Os https://uploader.codecov.io/latest/linux/codecov
|
|
||||||
- chmod +x codecov
|
|
||||||
- ./codecov -t ${CODECOV_TOKEN} -R $CI_PROJECT_DIR -C $CI_COMMIT_SHA -r $CI_PROJECT_PATH
|
|
||||||
|
|
||||||
vulnerabilities:
|
|
||||||
stage: test
|
|
||||||
image: amd64/golang:1.25.1@sha256:53f7808857782118f3a062261f721507dfa36e5c545e5d39c2dcf9916e3f0b1b
|
|
||||||
script:
|
|
||||||
- go install golang.org/x/vuln/cmd/govulncheck@latest
|
|
||||||
- govulncheck ./...
|
|
||||||
+4
-11
@@ -10,15 +10,8 @@ repos:
|
|||||||
args:
|
args:
|
||||||
- --allow-multiple-documents
|
- --allow-multiple-documents
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- repo: https://gitlab.com/devopshq/gitlab-ci-linter
|
|
||||||
rev: v1.0.6
|
|
||||||
hooks:
|
|
||||||
- id: gitlab-ci-linter
|
|
||||||
args:
|
|
||||||
- --project
|
|
||||||
- unboundsoftware/shiny/otelsetup
|
|
||||||
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
||||||
rev: v9.22.0
|
rev: v9.25.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: commitlint
|
- id: commitlint
|
||||||
stages: [ commit-msg ]
|
stages: [ commit-msg ]
|
||||||
@@ -30,17 +23,17 @@ repos:
|
|||||||
- id: go-imports
|
- id: go-imports
|
||||||
args:
|
args:
|
||||||
- -local
|
- -local
|
||||||
- gitlab.com/unboundsoftware/shiny/sentrysetup
|
- gitea.unbound.se/shiny/otelsetup
|
||||||
- repo: https://github.com/lietu/go-pre-commit
|
- repo: https://github.com/lietu/go-pre-commit
|
||||||
rev: v1.0.0
|
rev: v1.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: go-test
|
- id: go-test
|
||||||
- id: gofumpt
|
- id: gofumpt
|
||||||
- repo: https://github.com/golangci/golangci-lint
|
- repo: https://github.com/golangci/golangci-lint
|
||||||
rev: v2.5.0
|
rev: v2.12.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: golangci-lint-full
|
- id: golangci-lint-full
|
||||||
- repo: https://github.com/gitleaks/gitleaks
|
- repo: https://github.com/gitleaks/gitleaks
|
||||||
rev: v8.28.0
|
rev: v8.30.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: gitleaks
|
- id: gitleaks
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# Coverage configuration for go-test-coverage
|
||||||
|
# https://github.com/vladopajic/go-test-coverage
|
||||||
|
|
||||||
|
profile: coverage.txt
|
||||||
|
|
||||||
|
threshold:
|
||||||
|
file: 0
|
||||||
|
package: 0
|
||||||
|
total: 0
|
||||||
|
|
||||||
|
exclude:
|
||||||
|
paths:
|
||||||
|
- _test\.go$
|
||||||
+215
@@ -2,12 +2,189 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
## [0.4.0] - 2026-06-16
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- *(metrics)* Add SubscriptionMetrics OTel observer for subscriptions (#150)
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo (#146)
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.91 (#148)
|
||||||
|
|
||||||
|
## [0.3.1] - 2026-05-29
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- Set service.instance.id for unique instance label (#144)
|
||||||
|
|
||||||
|
## [0.3.0] - 2026-05-26
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- Add eventsourced MetricsRecorder adapter for OpenTelemetry (#142)
|
||||||
|
|
||||||
|
## [0.2.7] - 2026-05-09
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo (#131)
|
||||||
|
- *(ci)* Use go-test-coverage binary directly to fix Gitea Actions (#134)
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.90 (#133)
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook alessandrojcm/commitlint-pre-commit-hook to v9.25.0 (#136)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.12.0 (#137)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.12.1 (#138)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.12.2 (#140)
|
||||||
|
|
||||||
|
## [0.2.6] - 2026-04-02
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.88 (#121)
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.89 (#129)
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.11.2 (#119)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.11.3 (#123)
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.30.1 (#125)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.11.4 (#127)
|
||||||
|
|
||||||
|
## [0.2.5] - 2026-03-06
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo to v1.42.0 (#117)
|
||||||
|
|
||||||
|
## [0.2.4] - 2026-03-06
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update golang.org/x/net to v0.51.0
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo (#110)
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo (#115)
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.11.0 (#111)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.11.1 (#113)
|
||||||
|
|
||||||
|
## [0.2.3] - 2026-02-19
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.87
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.9.0 (#100)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.10.0 (#102)
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.10.1 (#103)
|
||||||
|
|
||||||
|
## [0.2.2] - 2026-02-03
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.86 (#90)
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.86 (#90)
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo to v1.40.0 (#98)
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo (#99)
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update golang:1.25.5 docker digest to 3a01526 (#91)
|
||||||
|
- *(deps)* Update pre-commit hook alessandrojcm/commitlint-pre-commit-hook to v9.24.0 (#92)
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.6 (#93)
|
||||||
|
- Remove GitLab CI configuration
|
||||||
|
- Add code coverage integration
|
||||||
|
|
||||||
|
## [0.2.1] - 2026-01-09
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update actions/setup-python action to v6
|
||||||
|
- Migrate module path to gitea.unbound.se
|
||||||
|
|
||||||
|
## [0.2.0] - 2026-01-09
|
||||||
|
|
||||||
|
### 🚀 Features
|
||||||
|
|
||||||
|
- Migrate from GitLab CI to Gitea Actions
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update opentelemetry-go monorepo
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.85
|
||||||
|
|
||||||
|
### 🚜 Refactor
|
||||||
|
|
||||||
|
- Update import paths to the new repository location
|
||||||
|
|
||||||
|
### 📚 Documentation
|
||||||
|
|
||||||
|
- Add CLAUDE.md for Claude Code integration
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.30.0
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.5
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.7.0
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.7.1
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.7.2
|
||||||
|
- *(deps)* Update golang:1.25.5 docker digest to 0c27bcf
|
||||||
|
- *(deps)* Update golang:1.25.5 docker digest to ad03ba9
|
||||||
|
- *(deps)* Update actions/checkout action to v6
|
||||||
|
- *(deps)* Update actions/setup-go action to v6
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.8.0
|
||||||
|
- Add pre-commit and release workflows
|
||||||
|
|
||||||
|
## [0.1.11] - 2025-11-24
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.84
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.6.2
|
||||||
|
- *(deps)* Update golang:1.25.4 docker digest to efe81fa
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.29.1
|
||||||
|
|
||||||
|
## [0.1.10] - 2025-11-13
|
||||||
|
|
||||||
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.82
|
||||||
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.83
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update golang:1.25.1 docker digest to 12640a4
|
||||||
|
- *(deps)* Update pre-commit hook alessandrojcm/commitlint-pre-commit-hook to v9.23.0
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.2
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.3
|
||||||
|
- *(deps)* Update golang:1.25.3 docker digest to 69d1009
|
||||||
|
- Remove initial tag from configuration
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.6.0
|
||||||
|
- *(deps)* Update golang:1.25.3 docker digest to 9ac0edc
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.6.1
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.29.0
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.4
|
||||||
|
|
||||||
## [0.1.9] - 2025-09-26
|
## [0.1.9] - 2025-09-26
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.81
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.81
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.5.0
|
||||||
|
|
||||||
## [0.1.8] - 2025-09-17
|
## [0.1.8] - 2025-09-17
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
@@ -20,24 +197,54 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.79
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.79
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.1
|
||||||
|
- *(deps)* Update golang:1.25.1 docker digest to 53f7808
|
||||||
|
- *(deps)* Update pre-commit hook lietu/go-pre-commit to v1
|
||||||
|
|
||||||
## [0.1.6] - 2025-09-01
|
## [0.1.6] - 2025-09-01
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- *(deps)* Update opentelemetry-go monorepo
|
- *(deps)* Update opentelemetry-go monorepo
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.3.1
|
||||||
|
- *(deps)* Update golang docker tag to v1.24.6
|
||||||
|
- *(deps)* Update pre-commit hook pre-commit/pre-commit-hooks to v6
|
||||||
|
- *(deps)* Update golang:1.24.6 docker digest to 958bfd1
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.4.0
|
||||||
|
- *(deps)* Update golang docker tag to v1.25.0
|
||||||
|
- *(deps)* Update golang:1.25.0 docker digest to f6b9e1a
|
||||||
|
|
||||||
## [0.1.5] - 2025-07-28
|
## [0.1.5] - 2025-07-28
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.78
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.78
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.2.1
|
||||||
|
- *(deps)* Update golang:1.24.4 docker digest to 9f820b6
|
||||||
|
- *(deps)* Update golang docker tag to v1.24.5
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.2.2
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.28.0
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.3.0
|
||||||
|
- *(deps)* Update golang:1.24.5 docker digest to 0a156a4
|
||||||
|
|
||||||
## [0.1.4] - 2025-06-29
|
## [0.1.4] - 2025-06-29
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
|
|
||||||
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.76
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.76
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook golangci/golangci-lint to v2.2.0
|
||||||
|
|
||||||
## [0.1.3] - 2025-06-25
|
## [0.1.3] - 2025-06-25
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
@@ -50,6 +257,13 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.75
|
- *(deps)* Update module github.com/99designs/gqlgen to v0.17.75
|
||||||
|
|
||||||
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update golang docker tag to v1.24.4
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.27.1
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.27.2
|
||||||
|
- *(deps)* Update golang:1.24.4 docker digest to 3494bbe
|
||||||
|
|
||||||
## [0.1.1] - 2025-06-02
|
## [0.1.1] - 2025-06-02
|
||||||
|
|
||||||
### 🐛 Bug Fixes
|
### 🐛 Bug Fixes
|
||||||
@@ -58,6 +272,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
### ⚙️ Miscellaneous Tasks
|
### ⚙️ Miscellaneous Tasks
|
||||||
|
|
||||||
|
- *(deps)* Update pre-commit hook gitleaks/gitleaks to v8.27.0
|
||||||
- *(pre-commit)* Update project reference for linter setup
|
- *(pre-commit)* Update project reference for linter setup
|
||||||
|
|
||||||
## [0.1.0] - 2025-05-30
|
## [0.1.0] - 2025-05-30
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# otelsetup
|
||||||
|
|
||||||
|
Shared Go library for OpenTelemetry setup across all microservices.
|
||||||
|
|
||||||
|
## Shared Documentation
|
||||||
|
|
||||||
|
@../docs/claude/architecture.md
|
||||||
|
@../docs/claude/go-services.md
|
||||||
|
@../docs/claude/conventions.md
|
||||||
|
|
||||||
|
## Library Information
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
|
||||||
|
Provides standardized OpenTelemetry configuration for tracing, metrics, and logging. Used by all Go microservices to enable observability.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
import "gitea.unbound.se/shiny/otelsetup"
|
||||||
|
|
||||||
|
// Bootstrap OpenTelemetry SDK
|
||||||
|
shutdown, err := otelsetup.SetupOTelSDK(ctx, enabled, serviceName, buildVersion, environment)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer shutdown(ctx)
|
||||||
|
|
||||||
|
// Wrap HTTP handlers with tracing
|
||||||
|
http.Handle("/", otelsetup.Handler(myHandler))
|
||||||
|
```
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **Tracing** - OTLP HTTP exporter with batch processing
|
||||||
|
- **Metrics** - OTLP HTTP exporter with periodic reader
|
||||||
|
- **Logging** - Stdout log exporter
|
||||||
|
- **Propagation** - TraceContext and Baggage propagation
|
||||||
|
- **HTTP Handler** - Middleware for automatic span creation
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
- `OTEL_RESOURCE_ATTRIBUTES` - Auto-set if not provided (service.name, service.version, service.environment)
|
||||||
|
- Standard OTLP environment variables for endpoint configuration
|
||||||
@@ -1,4 +1 @@
|
|||||||
# Shiny otelsetup
|
# Shiny otelsetup
|
||||||
|
|
||||||
[](https://gitlab.com/unboundsoftware/shiny/otelsetup/commits/main)
|
|
||||||
[](https://codecov.io/gl/unboundsoftware:shiny/otelsetup)
|
|
||||||
|
|||||||
+17
-24
@@ -5,9 +5,6 @@
|
|||||||
# Configuration options are organized into tables and keys.
|
# Configuration options are organized into tables and keys.
|
||||||
# See documentation for more information on available options.
|
# See documentation for more information on available options.
|
||||||
|
|
||||||
[bump]
|
|
||||||
initial_tag = "v0.0.1"
|
|
||||||
|
|
||||||
[changelog]
|
[changelog]
|
||||||
# template for the changelog header
|
# template for the changelog header
|
||||||
header = """
|
header = """
|
||||||
@@ -39,7 +36,7 @@ footer = """
|
|||||||
trim = true
|
trim = true
|
||||||
# postprocessors
|
# postprocessors
|
||||||
postprocessors = [
|
postprocessors = [
|
||||||
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
|
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
|
||||||
]
|
]
|
||||||
# render body even when there are no releases to process
|
# render body even when there are no releases to process
|
||||||
# render_always = true
|
# render_always = true
|
||||||
@@ -55,28 +52,25 @@ filter_unconventional = true
|
|||||||
split_commits = false
|
split_commits = false
|
||||||
# regex for preprocessing the commit messages
|
# regex for preprocessing the commit messages
|
||||||
commit_preprocessors = [
|
commit_preprocessors = [
|
||||||
# Replace issue numbers
|
# Replace issue numbers
|
||||||
#{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
|
#{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
|
||||||
# Check spelling of the commit with https://github.com/crate-ci/typos
|
# Check spelling of the commit with https://github.com/crate-ci/typos
|
||||||
# If the spelling is incorrect, it will be automatically fixed.
|
# If the spelling is incorrect, it will be automatically fixed.
|
||||||
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
|
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
|
||||||
]
|
]
|
||||||
# regex for parsing and grouping commits
|
# regex for parsing and grouping commits
|
||||||
commit_parsers = [
|
commit_parsers = [
|
||||||
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
|
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
|
||||||
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
|
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
|
||||||
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
|
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
|
||||||
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
|
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
|
||||||
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
|
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
|
||||||
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
|
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
|
||||||
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
|
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
|
||||||
{ message = "^chore\\(release\\): prepare for", skip = true },
|
{ message = "^chore\\(release\\): prepare for", skip = true },
|
||||||
{ message = "^chore\\(deps.*\\)", skip = true },
|
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
|
||||||
{ message = "^chore\\(pr\\)", skip = true },
|
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
||||||
{ message = "^chore\\(pull\\)", skip = true },
|
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
|
||||||
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
|
|
||||||
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
|
|
||||||
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
|
|
||||||
]
|
]
|
||||||
# filter out the commits that are not matched by commit parsers
|
# filter out the commits that are not matched by commit parsers
|
||||||
filter_commits = false
|
filter_commits = false
|
||||||
@@ -84,4 +78,3 @@ filter_commits = false
|
|||||||
topo_order = false
|
topo_order = false
|
||||||
# sort the commits inside sections by oldest/newest order
|
# sort the commits inside sections by oldest/newest order
|
||||||
sort_commits = "oldest"
|
sort_commits = "oldest"
|
||||||
tag_pattern = "v[0-9]+\\.[0-9]+\\.[0-9]+"
|
|
||||||
|
|||||||
@@ -1,37 +1,40 @@
|
|||||||
module gitlab.com/unboundsoftware/shiny/otelsetup
|
module gitea.unbound.se/shiny/otelsetup
|
||||||
|
|
||||||
go 1.24.3
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/99designs/gqlgen v0.17.81
|
github.com/99designs/gqlgen v0.17.91
|
||||||
go.opentelemetry.io/otel v1.38.0
|
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.23.0
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0
|
go.opentelemetry.io/otel v1.44.0
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0
|
||||||
go.opentelemetry.io/otel/log v0.14.0
|
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.20.0
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0
|
go.opentelemetry.io/otel/log v0.20.0
|
||||||
go.opentelemetry.io/otel/sdk/log v0.14.0
|
go.opentelemetry.io/otel/metric v1.44.0
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0
|
go.opentelemetry.io/otel/sdk v1.44.0
|
||||||
go.opentelemetry.io/otel/trace v1.38.0
|
go.opentelemetry.io/otel/sdk/log v0.20.0
|
||||||
|
go.opentelemetry.io/otel/sdk/metric v1.44.0
|
||||||
|
go.opentelemetry.io/otel/trace v1.44.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||||
github.com/sosodev/duration v1.3.1 // indirect
|
github.com/sosodev/duration v1.4.0 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.5.30 // indirect
|
github.com/vektah/gqlparser/v2 v2.5.34 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
golang.org/x/net v0.55.0 // indirect
|
||||||
golang.org/x/net v0.44.0 // indirect
|
golang.org/x/sync v0.20.0 // indirect
|
||||||
golang.org/x/sys v0.36.0 // indirect
|
golang.org/x/sys v0.45.0 // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
golang.org/x/text v0.37.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||||
google.golang.org/grpc v1.75.0 // indirect
|
google.golang.org/grpc v1.81.1 // indirect
|
||||||
google.golang.org/protobuf v1.36.9 // indirect
|
google.golang.org/protobuf v1.36.11 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
github.com/99designs/gqlgen v0.17.81 h1:kCkN/xVyRb5rEQpuwOHRTYq83i0IuTQg9vdIiwEerTs=
|
github.com/99designs/gqlgen v0.17.91 h1:/mIvXnN0lAorqszP3Vukw10SVRfLVUYtBTQFwmYRMmI=
|
||||||
github.com/99designs/gqlgen v0.17.81/go.mod h1:vgNcZlLwemsUhYim4dC1pvFP5FX0pr2Y+uYUoHFb1ig=
|
github.com/99designs/gqlgen v0.17.91/go.mod h1:N7+yJF6zbGIEqohF+ZtEUp/eq2dTnn0bDizLUIYPUCU=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
github.com/agnivade/levenshtein v1.2.1 h1:EHBY3UOn1gwdy/VbFwgo4cxecRznFk7fKWN1KOX7eoM=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/agnivade/levenshtein v1.2.1/go.mod h1:QVVI16kDrtSuwcpd0p1+xMC6Z/VfhtCyDIjcwga4/DU=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
@@ -17,63 +19,67 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
github.com/sosodev/duration v1.4.0 h1:35ed0KiVFriGHHzZZJaZLgmTEEICIyt8Sx0RQfj9IjE=
|
||||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
github.com/sosodev/duration v1.4.0/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
||||||
github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
|
|
||||||
github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/vektah/gqlparser/v2 v2.5.30 h1:EqLwGAFLIzt1wpx1IPpY67DwUujF1OfzgEyDsLrN6kE=
|
github.com/vektah/gqlparser/v2 v2.5.34 h1:MEea5P0qhdcqfBL45ghKE+qr9laidVHTMHjav5h7ckk=
|
||||||
github.com/vektah/gqlparser/v2 v2.5.30/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
|
github.com/vektah/gqlparser/v2 v2.5.34/go.mod h1:mFdHLGCio7OGX1fby9ZjTW6FN+qxgmbnBcRIeeScE5s=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.23.0 h1:qcteJH9D7kHaOgLQ0fzlW9dv42hSa0Vluqt7p4kooWA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.23.0/go.mod h1:LrA7I7etRmhIC1PjO8c26BHm+gWsy2rC3eSMe5+XUWE=
|
||||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0 h1:Oe2z/BCg5q7k4iXC3cqJxKYg0ieRiOqF0cecFYdPTwk=
|
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.38.0/go.mod h1:ZQM5lAJpOsKnYagGg/zV2krVqTtaVdYdDkhMoX6Oalg=
|
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 h1:RuynHbfU8JUEw7DyONgkVYg2SVtsoF28y0LGIr69jgA=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
|
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0/go.mod h1:qZF+/lBs71APw8mlnEZcqZHMzqrYrsFiJOv83lX1OGo=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0 h1:aTL7F04bJHUlztTsNGJ2l+6he8c+y/b//eR0jjjemT4=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 h1:4YsVu3B8+3qtWYYrsUYgn0OG78pN0rnNPRGX4SbokQI=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.38.0/go.mod h1:kldtb7jDTeol0l3ewcmd8SDvx3EmIE7lyvqbasU3QC4=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0/go.mod h1:+wnlSn0mD1ADVMe3v9Z/WIaiz6q6gL2J/ejaAmdmv80=
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0 h1:B/g+qde6Mkzxbry5ZZag0l7QrQBCtVm7lVjaLgmpje8=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 h1:lgh3PiVrRUWMLOVSkQicxzZll5NjF1r+AtsX1XRIHw0=
|
||||||
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.14.0/go.mod h1:mOJK8eMmgW6ocDJn6Bn11CcZ05gi3P8GylBXEkZtbgA=
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0/go.mod h1:5Cnhth3m/AgOeTgE3ex12pPmiu/gGtZit03kSzx9X7s=
|
||||||
go.opentelemetry.io/otel/log v0.14.0 h1:2rzJ+pOAZ8qmZ3DDHg73NEKzSZkhkGIua9gXtxNGgrM=
|
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.20.0 h1:aZfdmtI6QU/DAPD4b7YZ5zuJgewxO1EW9miOZklqleU=
|
||||||
go.opentelemetry.io/otel/log v0.14.0/go.mod h1:5jRG92fEAgx0SU/vFPxmJvhIuDU9E1SUnEQrMlJpOno=
|
go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.20.0/go.mod h1:isNl10/Om5CBWu9jj8WOb2+tJLbCVXDgqwzCaJMnJ6w=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
go.opentelemetry.io/otel/log v0.20.0 h1:/5i0vuHxCLWUfChWG41K9wkM0jafruPw9NU1/RCJirs=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
go.opentelemetry.io/otel/log v0.20.0/go.mod h1:wOcMcjsZpG8x7Bak7IhSi/lg8wscV2C1VdrKCLPlt0E=
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo=
|
||||||
go.opentelemetry.io/otel/sdk/log v0.14.0 h1:JU/U3O7N6fsAXj0+CXz21Czg532dW2V4gG1HE/e8Zrg=
|
go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA=
|
||||||
go.opentelemetry.io/otel/sdk/log v0.14.0/go.mod h1:imQvII+0ZylXfKU7/wtOND8Hn4OpT3YUoIgqJVksUkM=
|
go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk=
|
||||||
go.opentelemetry.io/otel/sdk/log/logtest v0.14.0 h1:Ijbtz+JKXl8T2MngiwqBlPaHqc4YCaP/i13Qrow6gAM=
|
go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58=
|
||||||
go.opentelemetry.io/otel/sdk/log/logtest v0.14.0/go.mod h1:dCU8aEL6q+L9cYTqcVOk8rM9Tp8WdnHOPLiBgp0SGOA=
|
go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
go.opentelemetry.io/otel/sdk/log v0.20.0 h1:vM3xI7TQgKPiSghe6urZtAkyFY7SodrSpC83CffDFuY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
go.opentelemetry.io/otel/sdk/log v0.20.0/go.mod h1:Knej2nmsTUzN79T2eeXdRsjjPcoxoq2pUyUHz9TFyyU=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
go.opentelemetry.io/otel/sdk/log/logtest v0.20.0 h1:OqdRZ1guyzamK3M6LlRsmGqRrjkHWw6WZOKKli5ELpg=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/sdk/log/logtest v0.20.0/go.mod h1:PuMIlm7zAt7c3z8zfOI5ox4iT1Z87We+PF6YoINux/M=
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
|
go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI=
|
||||||
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
|
go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA=
|
||||||
|
go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk=
|
||||||
|
go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8=
|
||||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww=
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY=
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
|
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
|
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||||
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
package otelsetup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gitlab.com/unboundsoftware/eventsourced/eventsourced"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
// eventsourcedMeterName is the instrumentation scope for the event-sourcing
|
||||||
|
// metrics emitted by the adapter returned from NewEventsourcedMetrics.
|
||||||
|
const eventsourcedMeterName = "gitea.unbound.se/shiny/otelsetup/eventsourced"
|
||||||
|
|
||||||
|
// durationBucketsSeconds are explicit histogram boundaries tuned for
|
||||||
|
// sub-second event-store and command latencies. The SDK default boundaries are
|
||||||
|
// scaled for milliseconds, which would bucket nearly every second-valued
|
||||||
|
// observation into the first bucket and make percentiles useless.
|
||||||
|
var durationBucketsSeconds = []float64{0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10}
|
||||||
|
|
||||||
|
// eventsourcedMetrics implements eventsourced.MetricsRecorder by translating
|
||||||
|
// the framework's Metric values into OpenTelemetry instruments registered on
|
||||||
|
// the global MeterProvider configured by SetupOTelSDK.
|
||||||
|
//
|
||||||
|
// The OTel metric instruments are safe for concurrent use, and the struct is
|
||||||
|
// immutable after construction, so Record may be called from multiple
|
||||||
|
// goroutines as the framework requires.
|
||||||
|
//
|
||||||
|
// Operation counts are read off each duration histogram's generated _count
|
||||||
|
// series rather than separate counters; the only standalone counters carry
|
||||||
|
// information a histogram count cannot (events.loaded sums the number of events
|
||||||
|
// per load, idempotency.checks counts lookups that have no duration).
|
||||||
|
type eventsourcedMetrics struct {
|
||||||
|
commandDuration metric.Float64Histogram
|
||||||
|
eventStoreDur metric.Float64Histogram
|
||||||
|
eventsLoaded metric.Int64Counter
|
||||||
|
eventLoadDur metric.Float64Histogram
|
||||||
|
snapshotStoreDur metric.Float64Histogram
|
||||||
|
snapshotLoadDur metric.Float64Histogram
|
||||||
|
idempotencyCheck metric.Int64Counter
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEventsourcedMetrics builds an eventsourced.MetricsRecorder that records to
|
||||||
|
// the global OpenTelemetry MeterProvider. Pass the result to both
|
||||||
|
// pg.WithMetrics (for event-store operations) and eventsourced.WithMetrics
|
||||||
|
// (for command handling) so a single recorder covers store and handler
|
||||||
|
// metrics.
|
||||||
|
//
|
||||||
|
// SetupOTelSDK must have run first so the global MeterProvider is configured;
|
||||||
|
// when metrics are disabled the global provider is a no-op and recording is
|
||||||
|
// effectively free.
|
||||||
|
func NewEventsourcedMetrics() (eventsourced.MetricsRecorder, error) {
|
||||||
|
m := otel.Meter(eventsourcedMeterName)
|
||||||
|
var errs []error
|
||||||
|
hist := func(name, desc string) metric.Float64Histogram {
|
||||||
|
h, err := m.Float64Histogram(
|
||||||
|
name,
|
||||||
|
metric.WithDescription(desc),
|
||||||
|
metric.WithUnit("s"),
|
||||||
|
metric.WithExplicitBucketBoundaries(durationBucketsSeconds...),
|
||||||
|
)
|
||||||
|
errs = append(errs, err)
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
counter := func(name, desc string) metric.Int64Counter {
|
||||||
|
c, err := m.Int64Counter(name, metric.WithDescription(desc))
|
||||||
|
errs = append(errs, err)
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
r := &eventsourcedMetrics{
|
||||||
|
commandDuration: hist("eventsourced.command.duration", "Wall-clock time to process a command in Handle."),
|
||||||
|
eventStoreDur: hist("eventsourced.event.store.duration", "Time taken to persist a single event."),
|
||||||
|
eventsLoaded: counter("eventsourced.events.loaded", "Number of events loaded when rehydrating aggregates."),
|
||||||
|
eventLoadDur: hist("eventsourced.event.load.duration", "Time taken to load events for an aggregate."),
|
||||||
|
snapshotStoreDur: hist("eventsourced.snapshot.store.duration", "Time taken to persist a snapshot."),
|
||||||
|
snapshotLoadDur: hist("eventsourced.snapshot.load.duration", "Time taken to load a snapshot."),
|
||||||
|
idempotencyCheck: counter("eventsourced.idempotency.checks", "Number of command idempotency lookups."),
|
||||||
|
}
|
||||||
|
if err := errors.Join(errs...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Record implements eventsourced.MetricsRecorder. Metric types the adapter does
|
||||||
|
// not recognise (for example pg outbox metrics when the outbox is not enabled)
|
||||||
|
// are ignored.
|
||||||
|
func (e *eventsourcedMetrics) Record(ctx context.Context, raw eventsourced.Metric) {
|
||||||
|
switch m := raw.(type) {
|
||||||
|
case eventsourced.CommandDuration:
|
||||||
|
e.commandDuration.Record(ctx, m.Duration.Seconds(), metric.WithAttributes(
|
||||||
|
attribute.String("command.type", m.CommandType),
|
||||||
|
attribute.Bool("success", m.Success),
|
||||||
|
))
|
||||||
|
case eventsourced.EventStored:
|
||||||
|
e.eventStoreDur.Record(ctx, m.Duration.Seconds(), metric.WithAttributes(
|
||||||
|
attribute.String("aggregate.type", m.AggregateType),
|
||||||
|
attribute.String("event.type", m.EventType),
|
||||||
|
))
|
||||||
|
case eventsourced.EventsLoaded:
|
||||||
|
attrs := metric.WithAttributes(attribute.String("aggregate.type", m.AggregateType))
|
||||||
|
e.eventsLoaded.Add(ctx, int64(m.EventCount), attrs)
|
||||||
|
e.eventLoadDur.Record(ctx, m.Duration.Seconds(), attrs)
|
||||||
|
case eventsourced.SnapshotStored:
|
||||||
|
e.snapshotStoreDur.Record(ctx, m.Duration.Seconds(), metric.WithAttributes(
|
||||||
|
attribute.String("aggregate.type", m.AggregateType),
|
||||||
|
attribute.Bool("success", m.Success),
|
||||||
|
))
|
||||||
|
case eventsourced.SnapshotLoaded:
|
||||||
|
e.snapshotLoadDur.Record(ctx, m.Duration.Seconds(), metric.WithAttributes(
|
||||||
|
attribute.String("aggregate.type", m.AggregateType),
|
||||||
|
attribute.Bool("found", m.Found),
|
||||||
|
))
|
||||||
|
case eventsourced.IdempotencyCheck:
|
||||||
|
e.idempotencyCheck.Add(ctx, 1, metric.WithAttributes(
|
||||||
|
attribute.String("aggregate.type", m.AggregateType),
|
||||||
|
attribute.Bool("hit", m.Hit),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package otelsetup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gitlab.com/unboundsoftware/eventsourced/eventsourced"
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewEventsourcedMetrics_RecordsContract(t *testing.T) {
|
||||||
|
reader := sdkmetric.NewManualReader()
|
||||||
|
otel.SetMeterProvider(sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)))
|
||||||
|
|
||||||
|
r, err := NewEventsourcedMetrics()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewEventsourcedMetrics returned error: %v", err)
|
||||||
|
}
|
||||||
|
if r == nil {
|
||||||
|
t.Fatal("NewEventsourcedMetrics returned nil recorder")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recording every known metric type (and an unknown one) must not panic
|
||||||
|
// and must emit the expected instruments.
|
||||||
|
for _, m := range []eventsourced.Metric{
|
||||||
|
eventsourced.CommandDuration{CommandType: "AddEntry", Duration: time.Millisecond, Success: true},
|
||||||
|
eventsourced.EventStored{AggregateType: "Entry", EventType: "EntryAdded", Duration: time.Millisecond},
|
||||||
|
eventsourced.EventsLoaded{AggregateType: "Entry", EventCount: 3, Duration: time.Millisecond},
|
||||||
|
eventsourced.SnapshotStored{AggregateType: "Entry", Duration: time.Millisecond, Success: true},
|
||||||
|
eventsourced.SnapshotLoaded{AggregateType: "Entry", Found: false, Duration: time.Millisecond},
|
||||||
|
eventsourced.IdempotencyCheck{AggregateType: "Entry", Hit: true},
|
||||||
|
unknownMetric{},
|
||||||
|
} {
|
||||||
|
r.Record(context.Background(), m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var rm metricdata.ResourceMetrics
|
||||||
|
if err := reader.Collect(context.Background(), &rm); err != nil {
|
||||||
|
t.Fatalf("collect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := map[string]bool{}
|
||||||
|
for _, sm := range rm.ScopeMetrics {
|
||||||
|
for _, md := range sm.Metrics {
|
||||||
|
got[md.Name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
want := []string{
|
||||||
|
"eventsourced.command.duration",
|
||||||
|
"eventsourced.event.store.duration",
|
||||||
|
"eventsourced.events.loaded",
|
||||||
|
"eventsourced.event.load.duration",
|
||||||
|
"eventsourced.snapshot.store.duration",
|
||||||
|
"eventsourced.snapshot.load.duration",
|
||||||
|
"eventsourced.idempotency.checks",
|
||||||
|
}
|
||||||
|
var missing []string
|
||||||
|
for _, w := range want {
|
||||||
|
if !got[w] {
|
||||||
|
missing = append(missing, w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(missing) > 0 {
|
||||||
|
sort.Strings(missing)
|
||||||
|
t.Errorf("missing expected metrics: %v", missing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type unknownMetric struct{}
|
||||||
|
|
||||||
|
func (unknownMetric) IsMetric() {}
|
||||||
@@ -22,7 +22,17 @@ import (
|
|||||||
// SetupOTelSDK bootstraps the OpenTelemetry pipeline.
|
// SetupOTelSDK bootstraps the OpenTelemetry pipeline.
|
||||||
func SetupOTelSDK(ctx context.Context, enabled bool, serviceName, buildVersion, environment string) (func(context.Context) error, error) {
|
func SetupOTelSDK(ctx context.Context, enabled bool, serviceName, buildVersion, environment string) (func(context.Context) error, error) {
|
||||||
if os.Getenv("OTEL_RESOURCE_ATTRIBUTES") == "" {
|
if os.Getenv("OTEL_RESOURCE_ATTRIBUTES") == "" {
|
||||||
if err := os.Setenv("OTEL_RESOURCE_ATTRIBUTES", fmt.Sprintf("service.name=%s,service.version=%s,service.environment=%s", serviceName, buildVersion, environment)); err != nil {
|
// service.instance.id makes every pod a distinct telemetry resource. The
|
||||||
|
// OTLP→Prometheus exporter maps it to the `instance` label on metrics and
|
||||||
|
// target_info, which keeps multi-replica services from colliding on a
|
||||||
|
// single series and gives joins a unique (job, instance) key. Hostname is
|
||||||
|
// the pod name under Kubernetes; fall back to the service name if it is
|
||||||
|
// unavailable so the attribute is always present.
|
||||||
|
instanceID, err := os.Hostname()
|
||||||
|
if err != nil || instanceID == "" {
|
||||||
|
instanceID = serviceName
|
||||||
|
}
|
||||||
|
if err := os.Setenv("OTEL_RESOURCE_ATTRIBUTES", fmt.Sprintf("service.name=%s,service.version=%s,service.environment=%s,service.instance.id=%s", serviceName, buildVersion, environment, instanceID)); err != nil {
|
||||||
return func(context.Context) error {
|
return func(context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}, err
|
}, err
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
package otelsetup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric"
|
||||||
|
)
|
||||||
|
|
||||||
|
// subscriptionMeterName is the instrumentation scope for the cross-service
|
||||||
|
// subscription push metrics emitted by SubscriptionMetrics.
|
||||||
|
const subscriptionMeterName = "gitea.unbound.se/shiny/otelsetup/subscriptions"
|
||||||
|
|
||||||
|
// SubscriptionMetrics records cross-service subscription push outcomes (the
|
||||||
|
// read-your-writes subscriptions described in ADR-0012) as OpenTelemetry
|
||||||
|
// counters.
|
||||||
|
//
|
||||||
|
// Its method set (Pushed/PushSkipped/Dropped/ChannelFull) satisfies the
|
||||||
|
// Observer interface of gitea.unbound.se/shiny/subscriptions *structurally* —
|
||||||
|
// otelsetup does not import that library. A service constructs it and passes it
|
||||||
|
// to the registry:
|
||||||
|
//
|
||||||
|
// metrics, err := otelsetup.NewSubscriptionMetrics("availableCompanies")
|
||||||
|
// if err != nil { return err }
|
||||||
|
// reg := subscriptions.New[T](subscriptions.WithObserver(metrics))
|
||||||
|
//
|
||||||
|
// The WithObserver call type-checks the structural match, so a drift in the
|
||||||
|
// Observer interface fails the service build. Add a
|
||||||
|
// `var _ subscriptions.Observer = (*otelsetup.SubscriptionMetrics)(nil)` next to
|
||||||
|
// it for an explicit guard.
|
||||||
|
//
|
||||||
|
// Outcomes are recorded against a low-cardinality (subscription, outcome) pair.
|
||||||
|
// The subscriber key (company id / user email) the Observer methods receive is
|
||||||
|
// deliberately NOT used as a metric attribute — that would be unbounded
|
||||||
|
// cardinality; the key stays in the subscriptions library's logs for
|
||||||
|
// correlation.
|
||||||
|
type SubscriptionMetrics struct {
|
||||||
|
notifications metric.Int64Counter
|
||||||
|
subscription attribute.KeyValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSubscriptionMetrics builds a SubscriptionMetrics that records to the global
|
||||||
|
// OpenTelemetry MeterProvider. subscription is the low-cardinality name of the
|
||||||
|
// subscription field (e.g. "availableCompanies", "entryBasesChanged"), recorded
|
||||||
|
// as an attribute so one counter covers every subscription.
|
||||||
|
//
|
||||||
|
// SetupOTelSDK must have run first so the global MeterProvider is configured;
|
||||||
|
// when metrics are disabled the global provider is a no-op and recording is
|
||||||
|
// effectively free.
|
||||||
|
func NewSubscriptionMetrics(subscription string) (*SubscriptionMetrics, error) {
|
||||||
|
c, err := otel.Meter(subscriptionMeterName).Int64Counter(
|
||||||
|
"subscription.notifications",
|
||||||
|
metric.WithDescription("Cross-service subscription push outcomes, by outcome (pushed/skipped/dropped/channel_full)."),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SubscriptionMetrics{
|
||||||
|
notifications: c,
|
||||||
|
subscription: attribute.String("subscription", subscription),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SubscriptionMetrics) record(outcome string) {
|
||||||
|
s.notifications.Add(context.Background(), 1, metric.WithAttributes(
|
||||||
|
s.subscription,
|
||||||
|
attribute.String("outcome", outcome),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pushed records a change that was gated and delivered to the key's subscribers
|
||||||
|
// — the denominator for a skip/drop rate.
|
||||||
|
func (s *SubscriptionMetrics) Pushed(string) { s.record("pushed") }
|
||||||
|
|
||||||
|
// PushSkipped records a push skipped because the read view never reflected the
|
||||||
|
// change within the retry budget.
|
||||||
|
func (s *SubscriptionMetrics) PushSkipped(string) { s.record("skipped") }
|
||||||
|
|
||||||
|
// Dropped records a notification dropped because the worker queue was full.
|
||||||
|
func (s *SubscriptionMetrics) Dropped(string) { s.record("dropped") }
|
||||||
|
|
||||||
|
// ChannelFull records a notification dropped because a subscriber's buffer was
|
||||||
|
// full.
|
||||||
|
func (s *SubscriptionMetrics) ChannelFull(string) { s.record("channel_full") }
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package otelsetup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"go.opentelemetry.io/otel"
|
||||||
|
"go.opentelemetry.io/otel/attribute"
|
||||||
|
"go.opentelemetry.io/otel/metric/noop"
|
||||||
|
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||||
|
"go.opentelemetry.io/otel/sdk/metric/metricdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
// observerShape mirrors gitea.unbound.se/shiny/subscriptions.Observer. This
|
||||||
|
// compile-time assertion guards that SubscriptionMetrics still satisfies that
|
||||||
|
// interface structurally, without otelsetup importing the library.
|
||||||
|
//
|
||||||
|
// KEEP IN SYNC with subscriptions.Observer: this only proves SubscriptionMetrics
|
||||||
|
// matches this local copy. The authoritative check that the local copy still
|
||||||
|
// matches the real interface is the `subscriptions.WithObserver(...)` call site
|
||||||
|
// in each consuming service — keep a `var _ subscriptions.Observer` guard there.
|
||||||
|
type observerShape interface {
|
||||||
|
Pushed(string)
|
||||||
|
PushSkipped(string)
|
||||||
|
Dropped(string)
|
||||||
|
ChannelFull(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ observerShape = (*SubscriptionMetrics)(nil)
|
||||||
|
|
||||||
|
// TestSubscriptionMetrics_DisabledProviderIsSafe proves the "recording is free
|
||||||
|
// when metrics are disabled" claim: with the default global no-op provider, the
|
||||||
|
// methods neither panic nor emit instruments.
|
||||||
|
func TestSubscriptionMetrics_DisabledProviderIsSafe(t *testing.T) {
|
||||||
|
otel.SetMeterProvider(noop.NewMeterProvider())
|
||||||
|
|
||||||
|
m, err := NewSubscriptionMetrics("entryBasesChanged")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewSubscriptionMetrics returned error: %v", err)
|
||||||
|
}
|
||||||
|
// Must not panic on the no-op provider.
|
||||||
|
m.Pushed("c1")
|
||||||
|
m.PushSkipped("c1")
|
||||||
|
m.Dropped("c1")
|
||||||
|
m.ChannelFull("c1")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewSubscriptionMetrics_RecordsOutcomes(t *testing.T) {
|
||||||
|
reader := sdkmetric.NewManualReader()
|
||||||
|
otel.SetMeterProvider(sdkmetric.NewMeterProvider(sdkmetric.WithReader(reader)))
|
||||||
|
|
||||||
|
m, err := NewSubscriptionMetrics("availableCompanies")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewSubscriptionMetrics returned error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The subscriber key is ignored for metrics; different keys must not create
|
||||||
|
// new series (cardinality guard is implicit — we only label by outcome).
|
||||||
|
m.Pushed("c1")
|
||||||
|
m.Pushed("c2")
|
||||||
|
m.PushSkipped("c1")
|
||||||
|
m.Dropped("c1")
|
||||||
|
m.ChannelFull("c1")
|
||||||
|
|
||||||
|
var rm metricdata.ResourceMetrics
|
||||||
|
if err := reader.Collect(context.Background(), &rm); err != nil {
|
||||||
|
t.Fatalf("collect: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
counts := map[string]int64{}
|
||||||
|
dataPoints := 0
|
||||||
|
found := false
|
||||||
|
for _, sm := range rm.ScopeMetrics {
|
||||||
|
for _, md := range sm.Metrics {
|
||||||
|
if md.Name != "subscription.notifications" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found = true
|
||||||
|
sum, ok := md.Data.(metricdata.Sum[int64])
|
||||||
|
if !ok {
|
||||||
|
t.Fatalf("expected Sum[int64], got %T", md.Data)
|
||||||
|
}
|
||||||
|
for _, dp := range sum.DataPoints {
|
||||||
|
dataPoints++
|
||||||
|
sub, _ := dp.Attributes.Value(attribute.Key("subscription"))
|
||||||
|
if sub.AsString() != "availableCompanies" {
|
||||||
|
t.Errorf("unexpected subscription attribute: %q", sub.AsString())
|
||||||
|
}
|
||||||
|
outcome, _ := dp.Attributes.Value(attribute.Key("outcome"))
|
||||||
|
counts[outcome.AsString()] += dp.Value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
t.Fatal("subscription.notifications counter not emitted")
|
||||||
|
}
|
||||||
|
// One series per outcome, keyed by outcome only (not by subscriber key).
|
||||||
|
if dataPoints != 4 {
|
||||||
|
t.Errorf("expected 4 data points (one per outcome), got %d", dataPoints)
|
||||||
|
}
|
||||||
|
want := map[string]int64{"pushed": 2, "skipped": 1, "dropped": 1, "channel_full": 1}
|
||||||
|
for k, v := range want {
|
||||||
|
if counts[k] != v {
|
||||||
|
t.Errorf("outcome %q: got %d, want %d", k, counts[k], v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user