Skip to content

Commit 285253d

Browse files
authored
feat(observability): wire unused MyAudio Prometheus metrics (#2232)
* feat(observability): wire unused MyAudio Prometheus metrics to call sites Connect 4 previously-defined but uncalled metrics to their logical call sites in the audio processing pipeline: - RecordAudioInferenceDuration: records BirdNET inference elapsed time - RecordBirdNETResults: records detection result count per inference - RecordAudioQueueOperation: tracks enqueue success/drop on results queue - RecordAudioDataSize: tracks cumulative bytes written to analysis buffer * fix(observability): measure only Predict() latency for inference duration metric Separate inference timing from end-to-end processing time so RecordAudioInferenceDuration accurately reflects only bn.Predict() latency. Also record inference duration on failed predictions. --------- Co-authored-by: tphakala <tphakala@users.noreply.github.com>
1 parent 61e224b commit 285253d

File tree

2 files changed

+23
-3
lines changed

2 files changed

+23
-3
lines changed

internal/myaudio/analysis_buffer.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ func WriteToAnalysisBuffer(sourceID string, data []byte) error {
387387
m.RecordBufferWrite("analysis", sourceID, "success")
388388
m.RecordBufferWriteDuration("analysis", sourceID, duration)
389389
m.RecordBufferWriteBytes("analysis", sourceID, n)
390+
m.RecordAudioDataSize(sourceID, n)
390391
}
391392

392393
if n < len(data) {

internal/myaudio/process.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,36 @@ func ProcessData(bn *birdnet.BirdNET, data []byte, startTime time.Time, source s
152152
}
153153

154154
// run BirdNET inference
155+
inferenceStart := time.Now()
155156
results, err := bn.Predict(sampleData)
157+
inferenceDuration := time.Since(inferenceStart)
156158

157159
// Return float32 buffer to pool after prediction
158160
// This is safe because Predict copies the data to the input tensor
159161
if conf.BitDepth == 16 && len(sampleData) > 0 && len(sampleData[0]) == Float32BufferSize {
160162
ReturnFloat32Buffer(sampleData[0])
161163
}
162164

165+
// Record inference duration metric (always, even on error)
166+
processMetricsMutex.RLock()
167+
pm := processMetrics
168+
processMetricsMutex.RUnlock()
169+
if pm != nil {
170+
pm.RecordAudioInferenceDuration(source, inferenceDuration.Seconds())
171+
}
172+
163173
if err != nil {
164174
return fmt.Errorf("error predicting species: %w", err)
165175
}
166176

167-
// get elapsed time
177+
// get elapsed time (includes conversion + inference for overrun check)
168178
elapsedTime := time.Since(predictStart)
169179

180+
// Record result count metric
181+
if pm != nil {
182+
pm.RecordBirdNETResults(source, len(results))
183+
}
184+
170185
// DEBUG print all BirdNET results
171186
if conf.Setting().BirdNET.Debug {
172187
debugThreshold := float32(0) // set to 0 for now, maybe add a config option later
@@ -264,11 +279,15 @@ func ProcessData(bn *birdnet.BirdNET, data []byte, startTime time.Time, source s
264279
// Note: No copy needed - ownership transfers to the queue consumer
265280
select {
266281
case birdnet.ResultsQueue <- resultsMessage:
267-
// Results enqueued successfully
282+
if pm != nil {
283+
pm.RecordAudioQueueOperation(source, "enqueue", "success")
284+
}
268285
default:
269286
log.Error("results queue is full",
270287
logger.String("source", source))
271-
// Queue is full
288+
if pm != nil {
289+
pm.RecordAudioQueueOperation(source, "enqueue", "dropped")
290+
}
272291
}
273292
return nil
274293
}

0 commit comments

Comments
 (0)