// (C) 2022 by Harald Welte // SPDX-License-Identifier: Apache-2.0 package main /* #include */ import "C" import ( "fmt" "flag" "unsafe" "syscall" "acln.ro/ioctl" "net/http" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" ) var ( listen_http = flag.String("http",":2113", "local HTTP listen host:port") dahdi_ctl int spanno = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_span_number", Help: "span number of this span", }, []string{ "span_name", }) txlevel = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_txlevel", Help: "current Tx Level", }, []string{ "span_name", }) rxlevel = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_rxlevel", Help: "current Rx Level", }, []string{ "span_name", }) bpvcount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_bpv_error_total", Help: "current BPV (bi-polar violation) count", }, []string{ "span_name", }) crc4count = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_crc4_error_total", Help: "current CRC4 error count", }, []string{ "span_name", }) ebitcount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_ebit_error_total", Help: "current E-bit error count", }, []string{ "span_name", }) fascount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_fas_error_total", Help: "current FAS error count", }, []string{ "span_name", }) fecount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_framing_error_total", Help: "current framing error count", }, []string{ "span_name", }) cvcount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_coding_violation_total", Help: "current coding violation error count", }, []string{ "span_name", }) becount = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_bit_error_total", Help: "current bit error count", }, []string{ "span_name", }) prbs = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_prbs", Help: "current PRBS detected pattern", }, []string{ "span_name", }) errsec = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_errored_seconds", Help: "errored seconds", }, []string{ "span_name", }) irqmisses = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_irq_misses_total", Help: "current IRQ misses", }, []string{ "span_name", }) syncsrc = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_sync_source_span", Help: "span number of current sync source", }, []string{ "span_name", }) numchans = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_channels_configured_total", Help: "number of configured channels in this span", }, []string{ "span_name", }) totalchans = promauto.NewGaugeVec( prometheus.GaugeOpts { Subsystem: "dahdi", Name: "spaninfo_channels_total", Help: "number of channels in this span", }, []string{ "span_name", }) ) /* report one span to prometheus */ func report_span(spaninfo *C.struct_dahdi_spaninfo) { name := C.GoString(&spaninfo.name[0]) spanno.WithLabelValues(name).Set(float64(spaninfo.spanno)) txlevel.WithLabelValues(name).Set(float64(spaninfo.txlevel)) rxlevel.WithLabelValues(name).Set(float64(spaninfo.rxlevel)) bpvcount.WithLabelValues(name).Set(float64(spaninfo.bpvcount)) crc4count.WithLabelValues(name).Set(float64(spaninfo.crc4count)) ebitcount.WithLabelValues(name).Set(float64(spaninfo.ebitcount)) fascount.WithLabelValues(name).Set(float64(spaninfo.fascount)) fecount.WithLabelValues(name).Set(float64(spaninfo.fecount)) cvcount.WithLabelValues(name).Set(float64(spaninfo.cvcount)) becount.WithLabelValues(name).Set(float64(spaninfo.becount)) prbs.WithLabelValues(name).Set(float64(spaninfo.prbs)) errsec.WithLabelValues(name).Set(float64(spaninfo.errsec)) irqmisses.WithLabelValues(name).Set(float64(spaninfo.irqmisses)) syncsrc.WithLabelValues(name).Set(float64(spaninfo.syncsrc)) numchans.WithLabelValues(name).Set(float64(spaninfo.numchans)) totalchans.WithLabelValues(name).Set(float64(spaninfo.totalchans)) } /* read spanstat of one span */ func read_span(spaninfo *C.struct_dahdi_spaninfo) { var spanstat ioctl.WR //var spaninfo C.struct_dahdi_spaninfo var err error spanstat.Name = "DAHDI Spaninfo" spanstat.Type = 0xDA spanstat.Nr = 10 spanstat.Size = uint16(unsafe.Sizeof(*spaninfo)) fmt.Println("SPANSTAT ioctl on span ", spaninfo) if err = spanstat.Exec(dahdi_ctl, unsafe.Pointer(spaninfo)); err != nil { fmt.Println("spaninfo ", spaninfo) panic(fmt.Sprintf("Failed to execute ioctl: %s", err)) } } /* iterate over all spans, read + report each of them */ func read_spans() { var spaninfo C.struct_dahdi_spaninfo //var err error /* first obtain the total number of spans */ spaninfo.spanno = 1 read_span(&spaninfo) report_span(&spaninfo) total_spans := int(spaninfo.totalspans) /* then iterate over the remainder of them */ for i := 2; i <= total_spans; i++ { spaninfo.spanno = C.int(i) read_span(&spaninfo) report_span(&spaninfo) } } func main() { var err error flag.Parse() if dahdi_ctl, err = syscall.Open("/dev/dahdi/ctl", syscall.O_RDWR, 0775); err != nil { panic(fmt.Sprintf("Failed to open DAHDI ctl: %s", err)) } read_spans() fmt.Println("Listening to HTTP requests at", *listen_http) http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(*listen_http, nil) }