From f0113fc53bf7d2c6465bdb699104851928b28313 Mon Sep 17 00:00:00 2001 From: Sergey Petrov Date: Mon, 31 Mar 2025 11:03:17 +0500 Subject: [PATCH] Added metrics for Prometheus. --- writer/cmd/main.go | 21 ++++ writer/go.mod | 2 +- writer/go.sum | 19 +--- writer/internal/config/cameras.yaml | 70 +++++++------- writer/internal/ingest/rtsp/rtsp.go | 142 ++++++++++++++++++++-------- writer/internal/metrics/metrics.go | 91 +----------------- 6 files changed, 169 insertions(+), 176 deletions(-) diff --git a/writer/cmd/main.go b/writer/cmd/main.go index ecdc2a2..fc35960 100644 --- a/writer/cmd/main.go +++ b/writer/cmd/main.go @@ -2,6 +2,12 @@ package main import ( "fmt" + "git.insit.tech/psa/rtsp_reader-writer/writer/internal/metrics" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/collectors" + "github.com/prometheus/client_golang/prometheus/promhttp" + "log" + "net/http" "time" "git.insit.tech/psa/rtsp_reader-writer/writer/internal/config" @@ -11,10 +17,25 @@ import ( ) func main() { + // Регистрируем стандартные метрики + appRegistry := prometheus.NewRegistry() + appRegistry.MustRegister(collectors.NewGoCollector()) + appRegistry.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) + appRegistry.MustRegister(metrics.ActiveCameras) + + //// Эндпоинт для метрик + http.Handle("/metrics", promhttp.HandlerFor(appRegistry, promhttp.HandlerOpts{})) + config.LogsDirectory = log2.DirCreator(config.Local, "logs") logger.Log = log2.MainLogging( fmt.Sprintf("%s/writer-main_%s.log", config.LogsDirectory, time.Now().Format("15-04-05_02-01-2006"))) rtsp.StartWriter() + + // Запуск сервера на порту 9110 + err := http.ListenAndServe(":9110", nil) + if err != nil { + log.Println(err) + } select {} } diff --git a/writer/go.mod b/writer/go.mod index 359805d..c4df998 100644 --- a/writer/go.mod +++ b/writer/go.mod @@ -3,7 +3,7 @@ module git.insit.tech/psa/rtsp_reader-writer/writer go 1.24.1 require ( - git.insit.tech/sas/rtsp_proxy v0.0.0-20250327104342-ec8a9640a1f9 + git.insit.tech/sas/rtsp_proxy v0.0.0-20250328095933-2642c2a10d0c github.com/Eyevinn/mp4ff v0.47.0 github.com/bluenviron/gortsplib/v4 v4.12.3 github.com/bluenviron/mediacommon v1.14.0 diff --git a/writer/go.sum b/writer/go.sum index 34770e5..8e6642a 100644 --- a/writer/go.sum +++ b/writer/go.sum @@ -1,7 +1,5 @@ -git.insit.tech/sas/rtsp_proxy v0.0.0-20250326040356-446f7f0578d9 h1:8aOLn23rkkXR/mpkOtbaNrCWsiBs0Pl+/ds3CzUuHZo= -git.insit.tech/sas/rtsp_proxy v0.0.0-20250326040356-446f7f0578d9/go.mod h1:/AHWd1Otr+ikOLWzpXtoozzifEx9ZKou+R6DgwaEzr0= -git.insit.tech/sas/rtsp_proxy v0.0.0-20250327104342-ec8a9640a1f9 h1:VX17M9CHqtPbPrvR/24WlyxDyohy/AVsOxzFS6K5B7s= -git.insit.tech/sas/rtsp_proxy v0.0.0-20250327104342-ec8a9640a1f9/go.mod h1:/AHWd1Otr+ikOLWzpXtoozzifEx9ZKou+R6DgwaEzr0= +git.insit.tech/sas/rtsp_proxy v0.0.0-20250328095933-2642c2a10d0c h1:eABK52LAFilOYqVViB7XRA+maacYIGe14NzKdWW+HV0= +git.insit.tech/sas/rtsp_proxy v0.0.0-20250328095933-2642c2a10d0c/go.mod h1:/AHWd1Otr+ikOLWzpXtoozzifEx9ZKou+R6DgwaEzr0= github.com/Eyevinn/mp4ff v0.47.0 h1:XSSHYt5+I0fyOnHWoNwM72DtivlmHFR0V9azgIi+ZVU= github.com/Eyevinn/mp4ff v0.47.0/go.mod h1:hJNUUqOBryLAzUW9wpCJyw2HaI+TCd2rUPhafoS5lgg= github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= @@ -28,13 +26,10 @@ github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= -github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -61,12 +56,8 @@ github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGC github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= -github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k= github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM= github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -87,14 +78,10 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= -golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= -google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/writer/internal/config/cameras.yaml b/writer/internal/config/cameras.yaml index c4f100c..5abe8fd 100644 --- a/writer/internal/config/cameras.yaml +++ b/writer/internal/config/cameras.yaml @@ -1,36 +1,36 @@ -#camera_1: rtsp://intercom-video-1.insit.ru/camera01-centr-pl_slavy -#camera_2: rtsp://intercom-video-1.insit.ru/camera03-centr-administraciya -#camera_3: rtsp://intercom-video-1.insit.ru/camera08-centr-skver_kalinina -#camera_4: rtsp://intercom-video-1.insit.ru/camera04-centr-pobedy -#camera_5: rtsp://intercom-video-1.insit.ru/camera11-centr-dk_kirova -#camera_6: rtsp://intercom-video-1.insit.ru/camera13-centr-pobedy_sutyagina -#camera_7: rtsp://intercom-video-1.insit.ru/camera09-centr-nalogovaya -#camera_8: rtsp://intercom-video-1.insit.ru/camera59-centr-prktslavy -#camera_9: rtsp://intercom-video-1.insit.ru/camera10-centr-kommunisticheskiy_ilycha -#camera_10: rtsp://intercom-video-1.insit.ru/camera16-centr-sportschool2 -#camera_11: rtsp://intercom-video-1.insit.ru/camera40-center-kommunisticheskiy -#camera_12: rtsp://intercom-video-1.insit.ru/camera12-centr-skver_pavshih_geroev -#camera_13: rtsp://intercom-video-1.insit.ru/camera39-center-kommunisticheskiy -#camera_14: rtsp://intercom-video-1.insit.ru/camera14-centr-stadion_himik -#camera_15: rtsp://intercom-video-1.insit.ru/camera41-center-kuznecova_borby -#camera_16: rtsp://intercom-video-1.insit.ru/camera83-gorod-Kommunistichesky +camera_1: rtsp://intercom-video-1.insit.ru/camera01-centr-pl_slavy +camera_2: rtsp://intercom-video-1.insit.ru/camera03-centr-administraciya +camera_3: rtsp://intercom-video-1.insit.ru/camera08-centr-skver_kalinina +camera_4: rtsp://intercom-video-1.insit.ru/camera04-centr-pobedy +camera_5: rtsp://intercom-video-1.insit.ru/camera11-centr-dk_kirova +camera_6: rtsp://intercom-video-1.insit.ru/camera13-centr-pobedy_sutyagina +camera_7: rtsp://intercom-video-1.insit.ru/camera09-centr-nalogovaya +camera_8: rtsp://intercom-video-1.insit.ru/camera59-centr-prktslavy +camera_9: rtsp://intercom-video-1.insit.ru/camera10-centr-kommunisticheskiy_ilycha +camera_10: rtsp://intercom-video-1.insit.ru/camera16-centr-sportschool2 +camera_11: rtsp://intercom-video-1.insit.ru/camera40-center-kommunisticheskiy +camera_12: rtsp://intercom-video-1.insit.ru/camera12-centr-skver_pavshih_geroev +camera_13: rtsp://intercom-video-1.insit.ru/camera39-center-kommunisticheskiy +camera_14: rtsp://intercom-video-1.insit.ru/camera14-centr-stadion_himik +camera_15: rtsp://intercom-video-1.insit.ru/camera41-center-kuznecova_borby +camera_16: rtsp://intercom-video-1.insit.ru/camera83-gorod-Kommunistichesky camera_17: rtsp://intercom-video-1.insit.ru/camera54-centr-kirova-kalinina -#camera_18: rtsp://intercom-video-1.insit.ru/camera53-centr-pobedy_slavy -#camera_19: rtsp://intercom-video-1.insit.ru/camera44-center-skver_temnika -#camera_20: rtsp://intercom-video-1.insit.ru/camera28-oktyabrskiy-severnaya23a -#camera_21: rtsp://intercom-video-1.insit.ru/dp-qamumnrlkizuypnetljzzkjqamdoti -#camera_22: rtsp://intercom-video-1.insit.ru/dp-ohusuxzcvzsnpzzvkpyhddnwxuyeyc -#camera_23: rtsp://intercom-video-1.insit.ru/dp-bflbwjulvgfzurmcpejklrfvqairns -#camera_24: rtsp://intercom-video-1.insit.ru/dp-ajiymmjyytokybrpganfcxlfyjcdbgezphn -#camera_25: rtsp://intercom-video-2.insit.ru/dp-pobedi6a-ii-2125126423 -#camera_26: rtsp://intercom-video-1.insit.ru/dp-pobedi11-ii-2108117729 -#camera_27: rtsp://intercom-video-2.insit.ru/dp-pobedi11-i-2108117197 -#camera_28: rtsp://intercom-video-2.insit.ru/dp-nfhapwbfjpqkmaymfeipraxtzcpedk -#camera_29: rtsp://intercom-video-1.insit.ru/dp-swcixufwlheiwwrcvsrbkmhqzqvbxz -#camera_30: rtsp://intercom-video-1.insit.ru/dp-nerrjszqrbhjvqmfxskunejafdiihj -#camera_31: rtsp://intercom-video-1.insit.ru/dp-aiwukyujwonohpjyzeniispqqullyr -#camera_32: rtsp://intercom-video-1.insit.ru/dp-woxvkbynctgfbuztsalttgburbpvjf -#camera_33: rtsp://intercom-video-1.insit.ru/dp-fdzbasqehtptsuhxnjeqqnlrixfahcgvlcr -#camera_34: rtsp://intercom-video-1.insit.ru/dp-exyeqscyamrbkwkjifagouyprtsdoe -#camera_35: rtsp://intercom-video-2.insit.ru/dp-sutyagina3a-iv-uujtwbsjekv -#camera_36: rtsp://intercom-video-1.insit.ru/dp-wyshispseamhqmnhkqwkbarshnrvni \ No newline at end of file +camera_18: rtsp://intercom-video-1.insit.ru/camera53-centr-pobedy_slavy +camera_19: rtsp://intercom-video-1.insit.ru/camera44-center-skver_temnika +camera_20: rtsp://intercom-video-1.insit.ru/camera28-oktyabrskiy-severnaya23a +camera_21: rtsp://intercom-video-1.insit.ru/dp-qamumnrlkizuypnetljzzkjqamdoti +camera_22: rtsp://intercom-video-1.insit.ru/dp-ohusuxzcvzsnpzzvkpyhddnwxuyeyc +camera_23: rtsp://intercom-video-1.insit.ru/dp-bflbwjulvgfzurmcpejklrfvqairns +camera_24: rtsp://intercom-video-1.insit.ru/dp-ajiymmjyytokybrpganfcxlfyjcdbgezphn +camera_25: rtsp://intercom-video-2.insit.ru/dp-pobedi6a-ii-2125126423 +camera_26: rtsp://intercom-video-1.insit.ru/dp-pobedi11-ii-2108117729 +camera_27: rtsp://intercom-video-2.insit.ru/dp-pobedi11-i-2108117197 +camera_28: rtsp://intercom-video-2.insit.ru/dp-nfhapwbfjpqkmaymfeipraxtzcpedk +camera_29: rtsp://intercom-video-1.insit.ru/dp-swcixufwlheiwwrcvsrbkmhqzqvbxz +camera_30: rtsp://intercom-video-1.insit.ru/dp-nerrjszqrbhjvqmfxskunejafdiihj +camera_31: rtsp://intercom-video-1.insit.ru/dp-aiwukyujwonohpjyzeniispqqullyr +camera_32: rtsp://intercom-video-1.insit.ru/dp-woxvkbynctgfbuztsalttgburbpvjf +camera_33: rtsp://intercom-video-1.insit.ru/dp-fdzbasqehtptsuhxnjeqqnlrixfahcgvlcr +camera_34: rtsp://intercom-video-1.insit.ru/dp-exyeqscyamrbkwkjifagouyprtsdoe +camera_35: rtsp://intercom-video-2.insit.ru/dp-sutyagina3a-iv-uujtwbsjekv +camera_36: rtsp://intercom-video-1.insit.ru/dp-wyshispseamhqmnhkqwkbarshnrvni \ No newline at end of file diff --git a/writer/internal/ingest/rtsp/rtsp.go b/writer/internal/ingest/rtsp/rtsp.go index 6ffb386..d1232f8 100644 --- a/writer/internal/ingest/rtsp/rtsp.go +++ b/writer/internal/ingest/rtsp/rtsp.go @@ -13,6 +13,7 @@ import ( "git.insit.tech/psa/rtsp_reader-writer/writer/internal/config" "git.insit.tech/psa/rtsp_reader-writer/writer/internal/ingest/formats" logger "git.insit.tech/psa/rtsp_reader-writer/writer/internal/log" + "git.insit.tech/psa/rtsp_reader-writer/writer/internal/metrics" "git.insit.tech/psa/rtsp_reader-writer/writer/pkg/storage" log2 "git.insit.tech/sas/rtsp_proxy/core/log" "github.com/bluenviron/gortsplib/v4" @@ -48,6 +49,10 @@ func StartWriter() { // rtsp processes RTSP protocol. func rtsp(dir string, period int, link string, number int) error { + // Увеличиваем счетчик при старте обработки камеры + metrics.ActiveCameras.Inc() + defer metrics.ActiveCameras.Dec() + // Create data folder in the directory. dirData := log2.DirCreator(dir, "data") @@ -278,8 +283,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "" && audioFormat == "G711": @@ -366,9 +376,15 @@ func rtsp(dir string, period int, link string, number int) error { */ } }() + if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "H264" && audioFormat == "AAC": @@ -486,8 +502,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "H264" && audioFormat == "G711" || videoFormat == "H264" && audioFormat == "": @@ -502,11 +523,11 @@ func rtsp(dir string, period int, link string, number int) error { return err } - g711RTPDec, err := g711Format.CreateDecoder() - if err != nil { - cam.Error("create decoder error:", zap.Error(err)) - return err - } + //g711RTPDec, err := g711Format.CreateDecoder() + //if err != nil { + // cam.Error("create decoder error:", zap.Error(err)) + // return err + //} //// Setup MPEG-TS muxer. //var aacFormat *format.MPEG4Audio @@ -561,7 +582,7 @@ func rtsp(dir string, period int, link string, number int) error { // Process input rtp packets. c.OnPacketRTPAny(func(medi *description.Media, forma format.Format, pkt *rtp.Packet) { - switch f := forma.(type) { + switch forma.(type) { case *format.H264: // Process H264 flow and return PTS and AU. pts, au, err := formats.ProcessH264(&c, h264Media, h264RTPDec, pkt) @@ -590,26 +611,26 @@ func rtsp(dir string, period int, link string, number int) error { case *format.G711: // Process G711 flow and returns PTS and AU. - pts, au, err := formats.ProcessG711(&c, g711Media, g711RTPDec, pkt) - if err != nil { - cam.Warn("process packet error:", zap.Error(err)) - } - - if au != nil { - // Convert G711 to LPCM. - lpcmSamples := formats.ConvertG711ToLPCM(au, f.MULaw) - - // Add appropriate lines to the interleaved packet. - seg.Packet.Type = storage.PacketTypeLPCM - seg.Packet.Pts = pts - seg.Packet.LPCMSamples = lpcmSamples - - // Write segment with interleaved packets. - if err := storage.WriteInterleavedPacket(file, seg); err != nil { - cam.Error("write segment error:", zap.Error(err)) - return - } - } + //pts, au, err := formats.ProcessG711(&c, g711Media, g711RTPDec, pkt) + //if err != nil { + // cam.Warn("process packet error:", zap.Error(err)) + //} + // + //if au != nil { + // // Convert G711 to LPCM. + // lpcmSamples := formats.ConvertG711ToLPCM(au, f.MULaw) + // + // // Add appropriate lines to the interleaved packet. + // seg.Packet.Type = storage.PacketTypeLPCM + // seg.Packet.Pts = pts + // seg.Packet.LPCMSamples = lpcmSamples + // + // // Write segment with interleaved packets. + // if err := storage.WriteInterleavedPacket(file, seg); err != nil { + // cam.Error("write segment error:", zap.Error(err)) + // return + // } + //} //// Convert G711 to AAC. //au, err = formats.ConvertLPCMToAAC(lpcmSamples) @@ -710,8 +731,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "H264-" && audioFormat == "": @@ -813,8 +839,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "H265" && audioFormat == "": @@ -918,8 +949,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "" && audioFormat == "LPCM": @@ -1001,8 +1037,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "MJPEG" && audioFormat == "": @@ -1084,8 +1125,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "" && audioFormat == "AAC": @@ -1169,8 +1215,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "" && audioFormat == "OPUS": @@ -1252,8 +1303,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "VP8" && audioFormat == "": @@ -1344,8 +1400,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } case videoFormat == "VP9" && audioFormat == "": @@ -1436,8 +1497,13 @@ func rtsp(dir string, period int, link string, number int) error { }() if err = c.Wait(); err != nil { - rtsp(dir, period, link, fn.Number+1) cam.Error("c.Wait() error:", zap.Error(c.Wait())) + logger.Log.Error("c.Wait() error for camera:", zap.String("camera:", link), zap.Error(c.Wait())) + go func() { + time.Sleep(40 * time.Second) + rtsp(dir, period, link, fn.Number+1) + }() + time.Sleep(1 * time.Second) } } diff --git a/writer/internal/metrics/metrics.go b/writer/internal/metrics/metrics.go index 862a89b..56f9f33 100644 --- a/writer/internal/metrics/metrics.go +++ b/writer/internal/metrics/metrics.go @@ -1,89 +1,8 @@ package metrics -import ( - "net/http" - "runtime" +import "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/collectors" - "github.com/prometheus/client_golang/prometheus/promhttp" -) - -//// Пользовательские метрики -//var ( -// rtspConnectSuccess = prometheus.NewCounter(prometheus.CounterOpts{ -// Name: "rtsp_connect_success_total", -// Help: "Количество успешных подключений к RTSP источнику.", -// }) -// rtspConnectErrors = prometheus.NewCounter(prometheus.CounterOpts{ -// Name: "rtsp_connect_errors_total", -// Help: "Количество ошибок подключения к RTSP источнику.", -// }) -// rtspBytesRead = prometheus.NewCounter(prometheus.CounterOpts{ -// Name: "rtsp_bytes_read_total", -// Help: "Общее количество байт, прочитанных из RTSP-потоков.", -// }) -// funcDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ -// Name: "function_execution_seconds", -// Help: "Время выполнения функций приложения.", -// Buckets: prometheus.DefBuckets, -// }, []string{"function"}) -//) - -func init() { - // Регистрируем стандартные метрики Go - prometheus.MustRegister(collectors.NewGoCollector()) - prometheus.MustRegister(collectors.NewProcessCollector(collectors.ProcessCollectorOpts{})) - - //// Регистрируем пользовательские метрики - //prometheus.MustRegister(rtspConnectSuccess) - //prometheus.MustRegister(rtspConnectErrors) - //prometheus.MustRegister(rtspBytesRead) - //prometheus.MustRegister(funcDuration) -} - -//func processStream() { -// timer := prometheus.NewTimer(funcDuration.WithLabelValues("processStream")) -// defer timer.ObserveDuration() -// -// // Пример: имитация подключения к RTSP -// if err := connectToRTSP(); err != nil { -// rtspConnectErrors.Inc() -// return -// } -// rtspConnectSuccess.Inc() -// -// // Пример: чтение данных -// n := readRTSPData() -// rtspBytesRead.Add(float64(n)) -//} - -//func connectToRTSP() error { -// // Логика подключения (пример) -// return nil // или вернуть ошибку -//} - -//func readRTSPData() int { -// // Логика чтения данных (пример) -// // Для демонстрации можно вернуть случайное значение -// return 1024 -//} - -func metricsHandler(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/plain") - // Дополнительно можно вывести информацию о количестве горутин - w.Write([]byte("Goroutines: ")) - w.Write([]byte(string(runtime.NumGoroutine()))) -} - -func Metrics() { - // Эндпоинт для метрик Prometheus - http.Handle("/metrics", promhttp.Handler()) - // Остальные эндпоинты вашего приложения - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - //processStream() - w.Write([]byte("Processing stream...")) - }) - - http.ListenAndServe(":9100", nil) -} +var ActiveCameras = prometheus.NewGauge(prometheus.GaugeOpts{ + Name: "active_rtsp_cameras_total", + Help: "Количество активных rtsp потоков (работающих горутин) для камер.", +})