* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package collector
import (
"encoding/json"
"fmt"
"many-core-orchestrator/internal/collector/collectors"
"many-core-orchestrator/pkg/api/analyzerv1"
)
func snapshotToProto(snapshot Snapshot) *analyzerv1.MetricsSnapshot {
return &analyzerv1.MetricsSnapshot{
Node: snapshot.Node,
Timestamp: snapshot.Timestamp.Format("2006-01-02T15:04:05.999999999Z07:00"),
Metrics: &analyzerv1.NodeMetrics{
LlcMissRate: snapshot.Metrics.LLCMissRate,
LlcOccupancy: snapshot.Metrics.LLCOccupancy,
BioLatencyP95Ms: snapshot.Metrics.BioLatencyP95Ms,
BioLatencyP99Ms: snapshot.Metrics.BioLatencyP99Ms,
PsiAvailable: snapshot.Metrics.PSIAvailable,
PsiIoSome: snapshot.Metrics.PSIIOAvg10,
PsiIoFull: snapshot.Metrics.PSIIOFullAvg10,
PsiMemorySome: snapshot.Metrics.PSIMemAvg10,
PsiMemoryFull: snapshot.Metrics.PSIMemFullAvg10,
MemAvailableRatio: snapshot.Metrics.MemAvailRatio,
PageScanRate: snapshot.Metrics.PageScanRate,
},
Status: snapshot.Status,
Collectors: collectorResultsToProto(snapshot.Collectors),
SamplePeriod: snapshot.SamplePeriod,
Sequence: snapshot.Sequence,
Availability: metricAvailabilityToProto(snapshot.Availability),
}
}
func collectorResultsToProto(results []collectors.MetricResult) []*analyzerv1.CollectorResult {
converted := make([]*analyzerv1.CollectorResult, 0, len(results))
for _, result := range results {
converted = append(converted, &analyzerv1.CollectorResult{
Name: result.Name,
Values: result.Values,
Status: result.Status,
Error: result.Error,
Details: stringifyDetails(result.Details),
})
}
return converted
}
func metricAvailabilityToProto(availability []MetricAvailability) []*analyzerv1.MetricAvailability {
converted := make([]*analyzerv1.MetricAvailability, 0, len(availability))
for _, item := range availability {
converted = append(converted, &analyzerv1.MetricAvailability{
Collector: item.Collector,
Metric: item.Metric,
Available: item.Available,
Status: item.Status,
Reason: item.Reason,
})
}
return converted
}
func stringifyDetails(details map[string]interface{}) map[string]string {
if len(details) == 0 {
return nil
}
converted := make(map[string]string, len(details))
for key, value := range details {
switch typed := value.(type) {
case string:
converted[key] = typed
default:
data, err := json.Marshal(typed)
if err != nil {
converted[key] = fmt.Sprint(typed)
continue
}
converted[key] = string(data)
}
}
return converted
}