Merge branch 'martabal:main' into main
This commit is contained in:
commit
9ea3bac4af
13 changed files with 173 additions and 109 deletions
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -12,6 +12,6 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: Build
|
- name: Build
|
||||||
run: go build -o ./immich.out ./src
|
run: go build -o ./immich.out ./src
|
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repo
|
- name: Checkout repo
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v2
|
||||||
|
|
38
.github/workflows/docker.yml
vendored
38
.github/workflows/docker.yml
vendored
|
@ -3,7 +3,7 @@ on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
tags:
|
tags:
|
||||||
description: 'version'
|
description: "version"
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
|
@ -12,39 +12,47 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: 'main'
|
ref: "main"
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}
|
||||||
|
tags: |
|
||||||
|
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
|
||||||
|
type=sha
|
||||||
|
type=raw,value=${{ inputs.tags }}
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v2
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
id: buildx
|
id: buildx
|
||||||
uses: docker/setup-buildx-action@v2
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
username: martabal
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GH_TOKEN }}
|
password: ${{ secrets.GH_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v4
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: ./
|
context: ./
|
||||||
platforms: linux/arm/v7,linux/amd64,linux/arm64
|
platforms: linux/arm/v7,linux/amd64,linux/arm64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: |
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
martabal/immich-exporter:${{ inputs.tags }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
martabal/immich-exporter:latest
|
|
||||||
ghcr.io/${{ github.repository_owner }}/immich-exporter:${{ inputs.tags }}
|
|
||||||
ghcr.io/${{ github.repository_owner }}/immich-exporter:latest
|
|
||||||
|
|
10
.github/workflows/test.yml
vendored
10
.github/workflows/test.yml
vendored
|
@ -2,16 +2,18 @@ name: Test
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches: [ "main" ]
|
branches: ["main"]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ "main" ]
|
branches: ["main"]
|
||||||
jobs:
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
test:
|
test:
|
||||||
name: Run tests
|
name: Run tests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
- name: Run unit tests
|
||||||
|
run: go test -v ./src/tests
|
||||||
- name: Run formatter
|
- name: Run formatter
|
||||||
run: test -z $(gofmt -l ./src)
|
run: test -z $(gofmt -l ./src)
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.20-alpine3.18 AS builder
|
FROM golang:1.21-alpine3.18 AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
15
go.mod
15
go.mod
|
@ -1,21 +1,20 @@
|
||||||
module immich-exp
|
module immich-exp
|
||||||
|
|
||||||
go 1.20
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/prometheus/client_golang v1.16.0
|
github.com/prometheus/client_golang v1.17.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
github.com/prometheus/client_model v0.5.0 // indirect
|
||||||
github.com/prometheus/client_model v0.4.0 // indirect
|
github.com/prometheus/common v0.45.0 // indirect
|
||||||
github.com/prometheus/common v0.44.0 // indirect
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
github.com/prometheus/procfs v0.11.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
|
||||||
google.golang.org/protobuf v1.31.0 // indirect
|
google.golang.org/protobuf v1.31.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
31
go.sum
31
go.sum
|
@ -5,40 +5,35 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
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/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
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=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||||
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/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
|
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||||
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
|
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||||
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
|
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||||
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
|
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||||
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
|
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||||
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
|
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||||
github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk=
|
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||||
github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
|
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "immich-exporter",
|
"name": "immich-exporter",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "exporter for immich",
|
"description": "exporter for immich",
|
||||||
"main": "src/main.go",
|
"main": "src/main.go",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"build" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out -e",
|
||||||
|
"build:env" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out -e",
|
||||||
"dev" : "go run ./src",
|
"dev" : "go run ./src",
|
||||||
"dev:env" : "go run ./src -e",
|
"dev:env" : "go run ./src -e",
|
||||||
"build" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out -e",
|
"test": "go test -v ./src/tests",
|
||||||
"build:env" : "go build -o ./immich-exporter.out ./src && ./immich-exporter.out -e"
|
"update": "go get -u ./src && go mod tidy"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"exporter",
|
"exporter",
|
||||||
|
|
|
@ -5,15 +5,21 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"immich-exp/src/models"
|
"immich-exp/src/models"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
prom "immich-exp/src/prometheus"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
|
var unmarshalError = "Can not unmarshal JSON"
|
||||||
|
|
||||||
func Allrequests(r *prometheus.Registry) {
|
func Allrequests(r *prometheus.Registry) {
|
||||||
|
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
@ -39,7 +45,7 @@ func Analyze(r *prometheus.Registry) {
|
||||||
|
|
||||||
if err != nil && err2 != nil {
|
if err != nil && err2 != nil {
|
||||||
} else {
|
} else {
|
||||||
SendBackMessagePreference(res2, res1, r)
|
prom.SendBackMessagePreference(res2, res1, r)
|
||||||
}
|
}
|
||||||
close(serverinfo)
|
close(serverinfo)
|
||||||
close(allusers)
|
close(allusers)
|
||||||
|
@ -59,7 +65,7 @@ func GetAllUsers(c chan func() (*models.StructAllUsers, error)) {
|
||||||
|
|
||||||
result := new(models.StructAllUsers)
|
result := new(models.StructAllUsers)
|
||||||
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
||||||
log.Println("Can not unmarshal JSON")
|
log.Error(unmarshalError)
|
||||||
}
|
}
|
||||||
|
|
||||||
c <- (func() (*models.StructAllUsers, error) { return result, nil })
|
c <- (func() (*models.StructAllUsers, error) { return result, nil })
|
||||||
|
@ -81,27 +87,19 @@ func ServerVersion(r *prometheus.Registry) {
|
||||||
|
|
||||||
var result models.StructServerVersion
|
var result models.StructServerVersion
|
||||||
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
||||||
log.Println("Can not unmarshal JSON for version")
|
log.Error(unmarshalError)
|
||||||
}
|
}
|
||||||
|
|
||||||
SendBackMessageserverVersion(&result, r)
|
prom.SendBackMessageserverVersion(&result, r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
resp, err := Apirequest("/api/server-info/stats", "GET")
|
resp, err := Apirequest("/api/server-info/statistics", "GET")
|
||||||
if err != nil {
|
if err == nil {
|
||||||
if err.Error() == "403" {
|
|
||||||
log.Println("Cookie changed, try to reconnect ...")
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == false {
|
|
||||||
log.Println("Error : ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if models.GetPromptError() == true {
|
if models.GetPromptError() == true {
|
||||||
models.SetPromptError(false)
|
models.SetPromptError(false)
|
||||||
}
|
}
|
||||||
|
@ -112,7 +110,7 @@ func ServerInfo(c chan func() (*models.StructServerInfo, error)) {
|
||||||
|
|
||||||
result := new(models.StructServerInfo)
|
result := new(models.StructServerInfo)
|
||||||
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
if err := json.Unmarshal(body, &result); err != nil { // Parse []byte to go struct pointer
|
||||||
log.Println("Can not unmarshal JSON for server infos")
|
log.Println(unmarshalError)
|
||||||
}
|
}
|
||||||
c <- (func() (*models.StructServerInfo, error) { return result, nil })
|
c <- (func() (*models.StructServerInfo, error) { return result, nil })
|
||||||
|
|
||||||
|
@ -124,33 +122,47 @@ func Apirequest(uri string, method string) (*http.Response, error) {
|
||||||
|
|
||||||
req, err := http.NewRequest(method, models.Getbaseurl()+uri, nil)
|
req, err := http.NewRequest(method, models.Getbaseurl()+uri, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Error with url")
|
log.Fatal("Error with url")
|
||||||
}
|
}
|
||||||
req.Header.Add("Accept", "application/json")
|
req.Header.Add("Accept", "application/json")
|
||||||
req.Header.Add("x-api-key", models.GetApiKey())
|
req.Header.Add("x-api-key", models.GetApiKey())
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
err := fmt.Errorf("Can't connect to server")
|
err := fmt.Errorf("Can't connect to server")
|
||||||
if models.GetPromptError() == false {
|
if models.GetPromptError() == false {
|
||||||
log.Println(err.Error())
|
log.Error(err.Error())
|
||||||
models.SetPromptError(true)
|
models.SetPromptError(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, err
|
return resp, err
|
||||||
|
|
||||||
} else {
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
models.SetPromptError(false)
|
|
||||||
return resp, nil
|
|
||||||
} else {
|
|
||||||
err := fmt.Errorf("%d", resp.StatusCode)
|
|
||||||
if models.GetPromptError() == false {
|
|
||||||
models.SetPromptError(true)
|
|
||||||
log.Println("Error code", err.Error(), " for ", models.Getbaseurl()+uri)
|
|
||||||
}
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
switch resp.StatusCode {
|
||||||
|
case http.StatusOK:
|
||||||
|
if models.GetPromptError() {
|
||||||
|
models.SetPromptError(false)
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
case http.StatusNotFound:
|
||||||
|
err := fmt.Errorf("%d", resp.StatusCode)
|
||||||
|
|
||||||
|
log.Fatal("Error code ", resp.StatusCode, " for ", models.Getbaseurl()+uri)
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
case http.StatusUnauthorized, http.StatusForbidden:
|
||||||
|
err := fmt.Errorf("%d", resp.StatusCode)
|
||||||
|
|
||||||
|
log.Fatal("Api key unauthorized")
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
default:
|
||||||
|
err := fmt.Errorf("%d", resp.StatusCode)
|
||||||
|
if !models.GetPromptError() {
|
||||||
|
models.SetPromptError(true)
|
||||||
|
log.Debug("Error code ", resp.StatusCode)
|
||||||
|
}
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"immich-exp/src/immich"
|
immich "immich-exp/src/immich"
|
||||||
"immich-exp/src/models"
|
"immich-exp/src/models"
|
||||||
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
package immich
|
package prom
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"immich-exp/src/models"
|
"immich-exp/src/models"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Gauge []struct {
|
||||||
|
name string
|
||||||
|
help string
|
||||||
|
value float64
|
||||||
|
}
|
||||||
|
|
||||||
func SendBackMessagePreference(result *models.StructServerInfo, result2 *models.StructAllUsers, r *prometheus.Registry) {
|
func SendBackMessagePreference(result *models.StructServerInfo, result2 *models.StructAllUsers, r *prometheus.Registry) {
|
||||||
total_photos := prometheus.NewGauge(prometheus.GaugeOpts{
|
|
||||||
Name: "immich_app_total_photos",
|
gauges := Gauge{
|
||||||
Help: "The total number of photos",
|
{"total photos", "The total number of photos", float64((*result).Photos)},
|
||||||
})
|
{"total videos", "The total number of videos", float64((*result).Videos)},
|
||||||
total_videos := prometheus.NewGauge(prometheus.GaugeOpts{
|
{"total usage", "The max number of active torrents allowed", float64((*result).Usage)},
|
||||||
Name: "immich_app_total_videos",
|
{"number users", "The total number of users", float64(len((*result).UsageByUser))},
|
||||||
Help: "The total number of videos",
|
}
|
||||||
})
|
|
||||||
total_usage := prometheus.NewGauge(prometheus.GaugeOpts{
|
register(gauges, r)
|
||||||
Name: "immich_app_total_usage",
|
|
||||||
Help: "The total usage of disk",
|
|
||||||
})
|
|
||||||
total_users := prometheus.NewGauge(prometheus.GaugeOpts{
|
|
||||||
Name: "immich_app_number_users",
|
|
||||||
Help: "The total number of users",
|
|
||||||
})
|
|
||||||
user_info := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
user_info := prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||||
Name: "immich_user_info",
|
Name: "immich_user_info",
|
||||||
Help: "All infos about users",
|
Help: "All infos about users",
|
||||||
|
@ -43,17 +44,9 @@ func SendBackMessagePreference(result *models.StructServerInfo, result2 *models.
|
||||||
}, []string{"uid", "firstname", "lastname"})
|
}, []string{"uid", "firstname", "lastname"})
|
||||||
|
|
||||||
r.MustRegister(user_info)
|
r.MustRegister(user_info)
|
||||||
r.MustRegister(total_usage)
|
|
||||||
r.MustRegister(total_videos)
|
|
||||||
r.MustRegister(total_photos)
|
|
||||||
r.MustRegister(total_users)
|
|
||||||
r.MustRegister(user_usage)
|
r.MustRegister(user_usage)
|
||||||
r.MustRegister(user_videos)
|
r.MustRegister(user_videos)
|
||||||
r.MustRegister(user_photos)
|
r.MustRegister(user_photos)
|
||||||
total_photos.Add(float64((*result).Photos))
|
|
||||||
total_videos.Add(float64((*result).Videos))
|
|
||||||
total_usage.Add(float64((*result).Usage))
|
|
||||||
total_users.Add(float64(len((*result).UsageByUser)))
|
|
||||||
|
|
||||||
for i := 0; i < len((*result).UsageByUser); i++ {
|
for i := 0; i < len((*result).UsageByUser); i++ {
|
||||||
var myuser = GetName((*result).UsageByUser[i].UserID, result2)
|
var myuser = GetName((*result).UsageByUser[i].UserID, result2)
|
||||||
|
@ -94,3 +87,16 @@ func GetName(result string, result2 *models.StructAllUsers) models.StructCustomU
|
||||||
}
|
}
|
||||||
return myuser
|
return myuser
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func register(gauges Gauge, r *prometheus.Registry) {
|
||||||
|
for _, gauge := range gauges {
|
||||||
|
name := "immich_app_" + strings.Replace(gauge.name, " ", "_", -1)
|
||||||
|
help := gauge.help
|
||||||
|
g := prometheus.NewGauge(prometheus.GaugeOpts{
|
||||||
|
Name: name,
|
||||||
|
Help: help,
|
||||||
|
})
|
||||||
|
r.MustRegister(g)
|
||||||
|
g.Set(gauge.value)
|
||||||
|
}
|
||||||
|
}
|
35
src/tests/prometheus_test.go
Normal file
35
src/tests/prometheus_test.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package prom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"immich-exp/src/models"
|
||||||
|
prom "immich-exp/src/prometheus"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetName(t *testing.T) {
|
||||||
|
result2 := &models.StructAllUsers{
|
||||||
|
{ID: "1", FirstName: "John", LastName: "Doe", Email: "john@example.com", IsAdmin: true},
|
||||||
|
{ID: "2", FirstName: "Jane", LastName: "Smith", Email: "jane@example.com", IsAdmin: false},
|
||||||
|
}
|
||||||
|
|
||||||
|
result := "1"
|
||||||
|
expected := models.StructCustomUser{
|
||||||
|
ID: "1",
|
||||||
|
FirstName: "John",
|
||||||
|
LastName: "Doe",
|
||||||
|
Email: "john@example.com",
|
||||||
|
IsAdmin: true,
|
||||||
|
}
|
||||||
|
actual := prom.GetName(result, result2)
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
t.Errorf("Expected: %v, but got: %v", expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = "3"
|
||||||
|
expected = models.StructCustomUser{}
|
||||||
|
actual = prom.GetName(result, result2)
|
||||||
|
if !reflect.DeepEqual(expected, actual) {
|
||||||
|
t.Errorf("Expected: %v, but got: %v", expected, actual)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue