plugins/core/tracer_tools.go (112 lines of code) (raw):

// Licensed to Apache Software Foundation (ASF) under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Apache Software Foundation (ASF) licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package core import ( "os" "reflect" "strconv" "strings" "sync" "unsafe" ) type TracerTools struct { } func NewTracerTools() *TracerTools { return &TracerTools{} } type ReflectFieldFilter struct { name string interfaceType interface{} typeVal reflect.Type } func (r *ReflectFieldFilter) SetName(val string) { r.name = val } func (r *ReflectFieldFilter) SetInterfaceType(val interface{}) { r.interfaceType = val } func (r *ReflectFieldFilter) SetType(val interface{}) { r.typeVal = reflect.TypeOf(val) } type ReflectFieldFilterOpts interface { Apply(interface{}) } func (t *TracerTools) ReflectGetValue(instance interface{}, filterOpts []interface{}) interface{} { instanceVal := reflect.ValueOf(instance) if instanceVal.Kind() == reflect.Ptr && instanceVal.Elem().Kind() == reflect.Struct { instanceVal = instanceVal.Elem() } else { // only support the pointer struct return nil } filter := &ReflectFieldFilter{} for _, opt := range filterOpts { if f, ok := opt.(ReflectFieldFilterOpts); ok { f.Apply(filter) } } for i := 0; i < instanceVal.NumField(); i++ { field := instanceVal.Field(i) fieldType := instanceVal.Type().Field(i) if t.checkFieldSupport(field, &fieldType, filter) { // for getting the export field value // 1. get a pointer to the field, then convert it to a 'generic' pointer // 2. convert the pointer back to an interface{} fieldPtr := unsafe.Pointer(field.UnsafeAddr()) return reflect.NewAt(field.Type(), fieldPtr).Elem().Interface() } } return nil } func (t *TracerTools) GetEnvValue(key string) string { return os.Getenv(key) } func (t *TracerTools) ParseFloat(val string, bitSize int) (float64, error) { return strconv.ParseFloat(val, bitSize) } func (t *TracerTools) ParseBool(val string) bool { return strings.EqualFold(val, "true") } func (t *TracerTools) ParseInt(val string, base, bitSize int) (int64, error) { return strconv.ParseInt(val, base, bitSize) } func (t *TracerTools) ParseStringArray(val string) ([]string, error) { newVal := strings.ReplaceAll(val, " ", "") return strings.Split(newVal, ","), nil } func (t *TracerTools) Atoi(val string) (int, error) { return strconv.Atoi(val) } func (t *TracerTools) NewSyncMap() interface{} { return newSyncMap() } func (t *TracerTools) checkFieldSupport(field reflect.Value, instanceField *reflect.StructField, filter *ReflectFieldFilter) bool { if filter.name != "" { if instanceField.Name != filter.name { return false } } if filter.interfaceType != nil { interfaceType := reflect.TypeOf(filter.interfaceType).Elem() if !field.Type().Implements(interfaceType) { return false } } if filter.typeVal != nil { if field.Type() != filter.typeVal { return false } } return true } type syncMapImpl struct { data *sync.Map } func newSyncMap() *syncMapImpl { return &syncMapImpl{ data: &sync.Map{}, } } func (s *syncMapImpl) Put(key string, value interface{}) { s.data.Store(key, value) } func (s *syncMapImpl) Get(key string) (interface{}, bool) { return s.data.Load(key) } func (s *syncMapImpl) Remove(key string) (interface{}, bool) { return s.data.LoadAndDelete(key) }