func inquireChannelAttributes(objectPatternsList string, infoMap map[string]*ObjInfo) error {
	var err error
	traceEntry("inquireChannelAttributes")
	ci := getConnection(GetConnectionKey())
	statusClearReplyQ()
	if objectPatternsList == "" {
		traceExitErr("inquireChannelAttributes", 1, err)
		return err
	}
	objectPatterns := strings.Split(strings.TrimSpace(objectPatternsList), ",")
	for i := 0; i < len(objectPatterns) && err == nil; i++ {
		var buf []byte
		pattern := strings.TrimSpace(objectPatterns[i])
		if len(pattern) == 0 {
			continue
		}
		putmqmd, pmo, cfh, buf := statusSetCommandHeaders()
		cfh.Command = ibmmq.MQCMD_INQUIRE_CHANNEL
		cfh.ParameterCount = 0
		pcfparm := new(ibmmq.PCFParameter)
		pcfparm.Type = ibmmq.MQCFT_STRING
		pcfparm.Parameter = ibmmq.MQCACH_CHANNEL_NAME
		pcfparm.String = []string{pattern}
		cfh.ParameterCount++
		buf = append(buf, pcfparm.Bytes()...)
		pcfparm = new(ibmmq.PCFParameter)
		pcfparm.Type = ibmmq.MQCFT_INTEGER_LIST
		pcfparm.Parameter = ibmmq.MQIACF_CHANNEL_ATTRS
		pcfparm.Int64Value = []int64{int64(ibmmq.MQIACH_MAX_INSTANCES), int64(ibmmq.MQIACH_MAX_INSTS_PER_CLIENT), int64(ibmmq.MQCACH_DESC), int64(ibmmq.MQIACH_CHANNEL_TYPE)}
		cfh.ParameterCount++
		buf = append(buf, pcfparm.Bytes()...)
		buf = append(cfh.Bytes(), buf...)
		err = ci.si.cmdQObj.Put(putmqmd, pmo, buf)
		if err != nil {
			traceExitErr("inquireChannelAttributes", 2, err)
			return err
		}
		for allReceived := false; !allReceived; {
			cfh, buf, allReceived, err = statusGetReply()
			if buf != nil {
				parseChannelAttrData(cfh, buf, infoMap)
			}
		}
	}
	traceExit("inquireChannelAttributes", 0)
	return nil
}
Issue the INQUIRE_Q call for wildcarded queue names and
extract the required attributes - currently, just the
Maximum Queue Depth
package mqmetric
import (
	_ "fmt"
	"github.com/ibm-messaging/mq-golang/v5/ibmmq"
	"regexp"
	"strings"
	"time"
)
const (
	ATTR_CHL_NAME     = "name"
	ATTR_CHL_CONNNAME = "connname"
	ATTR_CHL_JOBNAME  = "jobname"
	ATTR_CHL_RQMNAME  = "rqmname"
	ATTR_CHL_MESSAGES      = "messages"
	ATTR_CHL_BYTES_SENT    = "bytes_sent"
	ATTR_CHL_BYTES_RCVD    = "bytes_rcvd"
	ATTR_CHL_BUFFERS_SENT  = "buffers_sent"
	ATTR_CHL_BUFFERS_RCVD  = "buffers_rcvd"
	ATTR_CHL_BATCHES       = "batches"
	ATTR_CHL_STATUS        = "status"
	ATTR_CHL_STATUS_SQUASH = ATTR_CHL_STATUS + "_squash"
	ATTR_CHL_SUBSTATE      = "substate"
	ATTR_CHL_TYPE          = "type"
	ATTR_CHL_INSTANCE_TYPE = "instance_type"
	ATTR_CHL_SINCE_MSG     = "time_since_msg"
	ATTR_CHL_NETTIME_SHORT = "nettime_short"
	ATTR_CHL_NETTIME_LONG  = "nettime_long"
	ATTR_CHL_BATCHSZ_SHORT = "batchsz_short"
	ATTR_CHL_BATCHSZ_LONG  = "batchsz_long"
	ATTR_CHL_XQTIME_SHORT  = "xmitq_time_short"
	ATTR_CHL_XQTIME_LONG   = "xmitq_time_long"
	ATTR_CHL_MAX_INSTC = "attribute_max_instc"
	ATTR_CHL_MAX_INST  = "attribute_max_inst"
	SQUASH_CHL_STATUS_STOPPED    = 0
	SQUASH_CHL_STATUS_TRANSITION = 1
	SQUASH_CHL_STATUS_RUNNING    = 2
	DUMMY_STRING = "-"  
)
func ChannelInitAttributes() {
	traceEntry("ChannelInitAttributes")
	ci := getConnection(GetConnectionKey())
	os := &ci.objectStatus[OT_CHANNEL]
	st := GetObjectStatus(GetConnectionKey(), OT_CHANNEL)
	if os.init {
		traceExit("ChannelInitAttributes", 1)
		return
	}
	st.Attributes = make(map[string]*StatusAttribute)
	attr := ATTR_CHL_NAME
	st.Attributes[attr] = newPseudoStatusAttribute(attr, "Channel Name")
	attr = ATTR_CHL_RQMNAME
	st.Attributes[attr] = newPseudoStatusAttribute(attr, "Remote Queue Manager Name")
	attr = ATTR_CHL_JOBNAME
	st.Attributes[attr] = newPseudoStatusAttribute(attr, "MCA Job Name")
	attr = ATTR_CHL_CONNNAME
	st.Attributes[attr] = newPseudoStatusAttribute(attr, "Connection Name")
	attr = ATTR_CHL_MESSAGES
	st.Attributes[attr] = newStatusAttribute(attr, "Messages (API Calls for SVRCONN)", ibmmq.MQIACH_MSGS)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_BYTES_SENT
	st.Attributes[attr] = newStatusAttribute(attr, "Bytes sent", ibmmq.MQIACH_BYTES_SENT)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_BYTES_RCVD
	st.Attributes[attr] = newStatusAttribute(attr, "Bytes rcvd", ibmmq.MQIACH_BYTES_RCVD)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_BUFFERS_SENT
	st.Attributes[attr] = newStatusAttribute(attr, "Buffers sent", ibmmq.MQIACH_BUFFERS_SENT)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_BUFFERS_RCVD
	st.Attributes[attr] = newStatusAttribute(attr, "Buffers rcvd", ibmmq.MQIACH_BUFFERS_RCVD)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_BATCHES
	st.Attributes[attr] = newStatusAttribute(attr, "Completed Batches", ibmmq.MQIACH_BATCHES)
	st.Attributes[attr].delta = true  
	attr = ATTR_CHL_STATUS
	st.Attributes[attr] = newStatusAttribute(attr, "Channel Status", ibmmq.MQIACH_CHANNEL_STATUS)
	attr = ATTR_CHL_SUBSTATE
	st.Attributes[attr] = newStatusAttribute(attr, "Channel Substate", ibmmq.MQIACH_CHANNEL_SUBSTATE)
	attr = ATTR_CHL_TYPE
	st.Attributes[attr] = newStatusAttribute(attr, "Channel Type", ibmmq.MQIACH_CHANNEL_TYPE)
	attr = ATTR_CHL_INSTANCE_TYPE
	st.Attributes[attr] = newStatusAttribute(attr, "Channel Instance Type", ibmmq.MQIACH_CHANNEL_INSTANCE_TYPE)
	attr = ATTR_CHL_STATUS_SQUASH
	st.Attributes[attr] = newStatusAttribute(attr, "Channel Status - Simplified", ibmmq.MQIACH_CHANNEL_STATUS)
	st.Attributes[attr].squash = true
	os.init = true
	attr = ATTR_CHL_NETTIME_SHORT
	st.Attributes[attr] = newStatusAttribute(attr, "Network Time Short", ibmmq.MQIACH_NETWORK_TIME_INDICATOR)
	st.Attributes[attr].index = 0
	attr = ATTR_CHL_NETTIME_LONG
	st.Attributes[attr] = newStatusAttribute(attr, "Network Time Long", ibmmq.MQIACH_NETWORK_TIME_INDICATOR)
	st.Attributes[attr].index = 1
	attr = ATTR_CHL_BATCHSZ_SHORT
	st.Attributes[attr] = newStatusAttribute(attr, "Batch Size Average Short", ibmmq.MQIACH_BATCH_SIZE_INDICATOR)
	st.Attributes[attr].index = 0
	attr = ATTR_CHL_BATCHSZ_LONG
	st.Attributes[attr] = newStatusAttribute(attr, "Batch Size Average Short", ibmmq.MQIACH_BATCH_SIZE_INDICATOR)
	st.Attributes[attr].index = 1
	attr = ATTR_CHL_XQTIME_SHORT
	st.Attributes[attr] = newStatusAttribute(attr, "XmitQ Time Average Short", ibmmq.MQIACH_XMITQ_TIME_INDICATOR)
	st.Attributes[attr].index = 0
	attr = ATTR_CHL_XQTIME_LONG
	st.Attributes[attr] = newStatusAttribute(attr, "XmitQ Time Average Short", ibmmq.MQIACH_XMITQ_TIME_INDICATOR)
	st.Attributes[attr].index = 1
	attr = ATTR_CHL_SINCE_MSG
	st.Attributes[attr] = newStatusAttribute(attr, "Time Since Msg", -1)
	attr = ATTR_CHL_MAX_INST
	st.Attributes[attr] = newStatusAttribute(attr, "MaxInst", -1)
	attr = ATTR_CHL_MAX_INSTC
	st.Attributes[attr] = newStatusAttribute(attr, "MaxInstC", -1)
	traceExit("ChannelInitAttributes", 0)
}
func InquireChannels(patterns string) ([]string, error) {
	traceEntry("InquireChannels")
	ChannelInitAttributes()
	rc, err := inquireObjects(patterns, ibmmq.MQOT_CHANNEL)
	traceExitErr("InquireChannels", 0, err)
	return rc, err
}
func CollectChannelStatus(patterns string) error {
	var err error
	traceEntry("CollectChannelStatus")
	ci := getConnection(GetConnectionKey())
	os := &ci.objectStatus[OT_CHANNEL]
	st := GetObjectStatus(GetConnectionKey(), OT_CHANNEL)
	os.objectSeen = make(map[string]bool)  
	ChannelInitAttributes()
	for k := range st.Attributes {
		st.Attributes[k].Values = make(map[string]*StatusValue)
	}
	channelPatterns := strings.Split(patterns, ",")
	if len(channelPatterns) == 0 {
		traceExit("CollectChannelStatus", 1)
		return nil
	}
	for _, pattern := range channelPatterns {
		pattern = strings.TrimSpace(pattern)
		if len(pattern) == 0 {
			continue
		}
		errCurrent := collectChannelStatus(pattern, ibmmq.MQOT_CURRENT_CHANNEL)
		err = errCurrent
	}
	for a, _ := range st.Attributes {
		if st.Attributes[a].delta {
			m := st.Attributes[a].prevValues
			for key, _ := range m {
				if _, ok := os.objectSeen[key]; ok {
				} else {
					delete(m, key)
				}
			}
		}
	}
	if err == nil && ci.showInactiveChannels {
		for chlName, v := range chlInfoMap {
			found := false
			chlPrefix := chlName + "/"
			for k, _ := range st.Attributes[ATTR_CHL_STATUS].Values {
				if strings.HasPrefix(k, chlPrefix) {
					found = true
					break
				}
			}
			if !found {
				key := chlName + "/" + DUMMY_STRING + "/" + DUMMY_STRING + "/" + DUMMY_STRING
				st.Attributes[ATTR_CHL_NAME].Values[key] = newStatusValueString(chlName)
				st.Attributes[ATTR_CHL_CONNNAME].Values[key] = newStatusValueString(DUMMY_STRING)
				st.Attributes[ATTR_CHL_JOBNAME].Values[key] = newStatusValueString(DUMMY_STRING)
				st.Attributes[ATTR_CHL_RQMNAME].Values[key] = newStatusValueString(DUMMY_STRING)
				st.Attributes[ATTR_CHL_STATUS].Values[key] = newStatusValueInt64(int64(ibmmq.MQCHS_INACTIVE))
				st.Attributes[ATTR_CHL_STATUS_SQUASH].Values[key] = newStatusValueInt64(SQUASH_CHL_STATUS_STOPPED)
				st.Attributes[ATTR_CHL_TYPE].Values[key] = newStatusValueInt64(v.AttrChlType)
			}
		}
	}
	traceExitErr("CollectChannelStatus", 0, err)
	return err
}
func collectChannelStatus(pattern string, instanceType int32) error {
	var err error
	traceEntryF("collectChannelStatus", "Pattern: %s", pattern)
	ci := getConnection(GetConnectionKey())
	os := &ci.objectStatus[OT_CHANNEL]
	statusClearReplyQ()
	putmqmd, pmo, cfh, buf := statusSetCommandHeaders()
	cfh.Command = ibmmq.MQCMD_INQUIRE_CHANNEL_STATUS
	pcfparm := new(ibmmq.PCFParameter)
	pcfparm.Type = ibmmq.MQCFT_STRING
	pcfparm.Parameter = ibmmq.MQCACH_CHANNEL_NAME
	pcfparm.String = []string{pattern}
	cfh.ParameterCount++
	buf = append(buf, pcfparm.Bytes()...)
	pcfparm = new(ibmmq.PCFParameter)
	pcfparm.Type = ibmmq.MQCFT_INTEGER
	pcfparm.Parameter = ibmmq.MQIACH_CHANNEL_INSTANCE_TYPE
	pcfparm.Int64Value = []int64{int64(instanceType)}
	cfh.ParameterCount++
	buf = append(buf, pcfparm.Bytes()...)
	buf = append(cfh.Bytes(), buf...)
	err = ci.si.cmdQObj.Put(putmqmd, pmo, buf)
	if err != nil {
		traceExitErr("collectChannelStatus", 1, err)
		return err
	}
	for allReceived := false; !allReceived; {
		cfh, buf, allReceived, err = statusGetReply()
		if buf != nil {
			key := parseChlData(instanceType, cfh, buf)
			if key != "" {
				os.objectSeen[key] = true
			}
		}
	}
	traceExitErr("collectChannelStatus", 0, err)
	return err
}
func parseChlData(instanceType int32, cfh *ibmmq.MQCFH, buf []byte) string {
	var elem *ibmmq.PCFParameter
	traceEntry("parseChlData")
	ci := getConnection(GetConnectionKey())
	os := &ci.objectStatus[OT_CHANNEL]
	st := GetObjectStatus(GetConnectionKey(), OT_CHANNEL)
	chlName := ""
	connName := ""
	jobName := ""
	rqmName := ""
	startDate := ""
	startTime := ""
	key := ""
	lastMsgDate := ""
	lastMsgTime := ""
	parmAvail := true
	bytesRead := 0
	offset := 0
	datalen := len(buf)
	if cfh == nil || cfh.ParameterCount == 0 {
		traceExit("parseChlData", 1)
		return ""
	}
	for parmAvail && cfh.CompCode != ibmmq.MQCC_FAILED {
		elem, bytesRead = ibmmq.ReadPCFParameter(buf[offset:])
		offset += bytesRead
		if offset >= datalen {
			parmAvail = false
		}
		switch elem.Parameter {
		case ibmmq.MQCACH_CHANNEL_NAME:
			chlName = strings.TrimSpace(elem.String[0])
		case ibmmq.MQCACH_CONNECTION_NAME:
			connName = strings.TrimSpace(elem.String[0])
		case ibmmq.MQCACH_MCA_JOB_NAME:
			jobName = strings.TrimSpace(elem.String[0])
		case ibmmq.MQCA_REMOTE_Q_MGR_NAME:
			rqmName = strings.TrimSpace(elem.String[0])
		case ibmmq.MQCACH_CHANNEL_START_TIME:
			startTime = strings.TrimSpace(elem.String[0])
		case ibmmq.MQCACH_CHANNEL_START_DATE:
			startDate = strings.TrimSpace(elem.String[0])
		}
	}
	if rqmName == "" {
		rqmName = DUMMY_STRING
	}
	if jobName == "" || allZero(jobName) {
		jobName = DUMMY_STRING
	}
	if jobName == DUMMY_STRING && ci.si.platform == ibmmq.MQPL_ZOS {
		jobName = startDate + ":" + startTime
	}
	key = chlName + "/" + connName + "/" + rqmName + "/" + jobName
	if instanceType == ibmmq.MQOT_SAVED_CHANNEL {
		subKey := chlName + "/" + connName + "/" + rqmName + "/.*"
		for k, _ := range os.objectSeen {
			re := regexp.MustCompile(subKey)
			if re.MatchString(k) {
				traceExit("parseChlData", 2)
				return ""
			}
		}
	}
	st.Attributes[ATTR_CHL_NAME].Values[key] = newStatusValueString(chlName)
	st.Attributes[ATTR_CHL_CONNNAME].Values[key] = newStatusValueString(connName)
	st.Attributes[ATTR_CHL_RQMNAME].Values[key] = newStatusValueString(rqmName)
	st.Attributes[ATTR_CHL_JOBNAME].Values[key] = newStatusValueString(jobName)
	parmAvail = true
	offset = 0
	for parmAvail && cfh.CompCode != ibmmq.MQCC_FAILED {
		elem, bytesRead = ibmmq.ReadPCFParameter(buf[offset:])
		offset += bytesRead
		if offset >= datalen {
			parmAvail = false
		}
		if !statusGetIntAttributes(GetObjectStatus(GetConnectionKey(), OT_CHANNEL), elem, key) {
			switch elem.Parameter {
			case ibmmq.MQCACH_LAST_MSG_TIME:
				lastMsgTime = strings.TrimSpace(elem.String[0])
			case ibmmq.MQCACH_LAST_MSG_DATE:
				lastMsgDate = strings.TrimSpace(elem.String[0])
			}
		}
	}
	now := time.Now()
	diff := statusTimeDiff(now, lastMsgDate, lastMsgTime)
	st.Attributes[ATTR_CHL_SINCE_MSG].Values[key] = newStatusValueInt64(diff)
	if s, ok := chlInfoMap[chlName]; ok {
		maxInstC := s.AttrMaxInstC
		st.Attributes[ATTR_CHL_MAX_INSTC].Values[key] = newStatusValueInt64(maxInstC)
		maxInst := s.AttrMaxInst
		st.Attributes[ATTR_CHL_MAX_INST].Values[key] = newStatusValueInt64(maxInst)
	}
	traceExitF("parseChlData", 0, "Key: %s", key)
	return key
}
func ChannelNormalise(attr *StatusAttribute, v int64) float64 {
	var f float64
	traceEntry("ChannelNormalise")
	if attr.squash {
		switch attr.pcfAttr {
		case ibmmq.MQIACH_CHANNEL_STATUS:
			v32 := int32(v)
			switch v32 {
			case ibmmq.MQCHS_INACTIVE,
				ibmmq.MQCHS_DISCONNECTED,
				ibmmq.MQCHS_STOPPED,
				ibmmq.MQCHS_PAUSED:
				f = float64(SQUASH_CHL_STATUS_STOPPED)
			case ibmmq.MQCHS_BINDING,
				ibmmq.MQCHS_STARTING,
				ibmmq.MQCHS_STOPPING,
				ibmmq.MQCHS_RETRYING,
				ibmmq.MQCHS_REQUESTING,
				ibmmq.MQCHS_INITIALIZING,
				ibmmq.MQCHS_SWITCHING:
				f = float64(SQUASH_CHL_STATUS_TRANSITION)
			case ibmmq.MQCHS_RUNNING:
				f = float64(SQUASH_CHL_STATUS_RUNNING)
			default:
				f = float64(SQUASH_CHL_STATUS_STOPPED)
			}
		default:
			f = float64(v)
			if f < 0 {
				f = 0
			}
		}
	} else {
		f = float64(v)
		if f < 0 {
			f = 0
		}
	}
	traceExit("ChannelNormalise", 0)
	return f
}