私はGoを使用してさまざまなperfmon統計を収集し、それらをEAVモデルのようなものに正規化したいと思っていますが、これを達成する方法に頭を悩ませています。
これらの構造体の例を考えると:
type Win32_PerfFormattedData_Counters_ProcessorInformation struct {
Name string
C1TransitionsPersec uint64
C2TransitionsPersec uint64
C3TransitionsPersec uint64
PercentUserTime uint64
PercentInterruptTime uint64
PercentPrivilegedTime uint64
PercentC1Time uint64
PercentC2Time uint64
PercentC3Time uint64
}
type Win32_PerfFormattedData_Tcpip_NetworkAdapter struct {
Name string
BytesSentPersec uint64
BytesReceivedPersec uint64
OffloadedConnections uint64
PacketsOutboundDiscarded uint64
PacketsOutboundErrors uint64
PacketsReceivedDiscarded uint64
PacketsReceivedErrors uint64
}
それらを次のように正規化したいと思います。
type Counter struct {
counter_category string
counter_name string
counter_instance string
counter_value uint64
}
使用reflect
してこれを思いつくことができました:
func pivot(cpu_info *[]Counter, cpu Win32_PerfFormattedData_Counters_ProcessorInformation, category string) {
e := reflect.ValueOf(&cpu).Ellem()
for i := 0; i < e.NumField(); i++ {
f_name := e.Type().Field(i).Name
f_value := e.Field(i).Interface()
if f_name != "Name" {
c := Counter {
counter_category: category,
counter_name: f_name,
counter_instance: cpu.Name,
counter_value: f_value.(uint64),
}
*cpu_info = append(*cpu_info,c)
}
}
}
ただし、私が収集しているカウンターカテゴリは17あり、これらの関数を17個記述するのが最善の方法であるとは思いません(ただし、それが正しく、修正できる場合を除きます)。
これまでにインターフェースを使用する関数を使用してきましたが、私が正しい道にいるかどうかはわかりません:
func pivot_counter(counter interface{}, counter_info *[]Counter) {
var counter_category string
switch t := counter.(type) {
case []Win32_PerfFormattedData_Counters_ProcessorInformation:
counter_category = "Processor"
fmt.Printf("%T\r\n",t)
case []Win32_PerfRawData_Tcpip_NetworkAdapter:
counter_category = "Network Adapter"
fmt.Printf("%T\r\n",t)
default:
counter_category = "Unknown"
fmt.Printf("%T\r\n", t)
}
}
しかし、ここで私が行き詰まっているのは、それらのケース内に「ピボット」ロジックの17の異なるブロックを持つ17の異なるケースステートメントを作成する必要がある場所にいるためです。私は何か間違ったことをしていることを知っています。私は基本的に、構造体/インターフェイスを受け入れ、型アサーションを介して型を決定し、そのオブジェクトを使用して構造体フィールドを反復して均一な形式にピボットアウトする関数を記述しようとしています。現在自分がいる場所からどこへ行くのですか?
インターフェイスを定義します。
type CounterMaker interface {
MakeCounter() Counter
}
今、あなたが持っているタイプごとに、それがCounterMakerをサポートするようにしてください:
type Win32_PerfFormattedData_Counters_ProcessorInformation struct {
...
}
func (value Win32_PerfFormattedData_Counters_ProcessorInformation) MakeCounter() Counter {
... code to turn "value" into a counter ...
return result
}
他のタイプについても繰り返します。
(上記のインターフェースは必ずしも正しいものではありません。状況に合ったものを選択してください。)
ここで、Counterインスタンスを必要とする関数がある場合は、それを呼び出す前に、またはその内部で作成できます。例えば:
func Increment(running *Counter, newstuff CounterMaker) {
inc := CounterMaker.MakeCounter()
// maybe double check that the running counter matches w/ "inc"
running.counter_value += inc.counter_value
}
この例を使用して実行した場合(これも正しい方法ではない可能性がありWin32_PerfFormattedData_Counters_ProcessorInformation
ます)、2番目の引数として値を渡すことができます。これIncrement
は、それがを実装するMakeCounter
ため、として修飾されるためCounterMaker
です。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加