diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 000000000..892d32c70 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,65 @@ +name: Run End to End tests for IBM MQ Metrics + +on: + push: + branches: [ main ] + paths: + - ibm-mq-metrics/** + pull_request: + paths: + - ibm-mq-metrics/** + + +permissions: + contents: read + +jobs: + e2e: + runs-on: ubuntu-latest + steps: + - name: Cache Docker images. + uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7 # 0.6.0 + with: + key: docker-mq-e2e + - name: Checkout code + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Set up JDK for running Gradle + uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + distribution: temurin + java-version: 17 + + - name: Set up gradle + uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4.4.2 + with: + cache-read-only: ${{ github.event_name == 'pull_request' }} + + - name: Build the jar + run: | + ./gradlew ibm-mq-metrics:clean ibm-mq-metrics:shadowJar + + - name: Make a local copy of the ibm client jar + run: | + ./gradlew ibm-mq-metrics:copyIbmClientJar + + - name: Start MQ and the test services + run: | + cd ibm-mq-metrics/golden + docker compose up -d --wait + + - name: Run the integration + run: | + cd ibm-mq-metrics/golden + ./run.sh & + exit_code=$(docker wait golden) + docker logs golden + if [ "$exit_code" -ne 0 ]; then + exit 1 + fi + + - name: Notify failed build + uses: jayqi/failed-build-issue-action@1a893bbf43ef1c2a8705e2b115cd4f0fe3c5649b # v1.2.0 + if: failure() && github.event.pull_request == null + with: + github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/ibm-mq-metrics/build.gradle.kts b/ibm-mq-metrics/build.gradle.kts index 3eeb876c5..e193b54cf 100644 --- a/ibm-mq-metrics/build.gradle.kts +++ b/ibm-mq-metrics/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.provideDelegate + plugins { application id("com.gradleup.shadow") @@ -63,6 +65,16 @@ tasks.shadowJar { } } +tasks { + // This exists purely to get the IBM jar into our build dir + val copyIbmClientJar by registering(Jar::class) { + archiveFileName.set("com.ibm.mq.allclient.jar") + doFirst { + from(zipTree(ibmClientJar.singleFile)) + } + } +} + val integrationTest = tasks.register("integrationTest") { description = "Runs integration tests." group = "verification" diff --git a/ibm-mq-metrics/golden/config.yml b/ibm-mq-metrics/golden/config.yml new file mode 100644 index 000000000..7eae76f96 --- /dev/null +++ b/ibm-mq-metrics/golden/config.yml @@ -0,0 +1,216 @@ +#Run it as a scheduled task instead of running every minute. +#If you want to run this every minute, comment this out +#taskSchedule: +# numberOfThreads: 20 +# taskDelaySeconds: 300 + +#This is the timeout on queue metrics and channel metrics threads.Default value is 20 seconds. +#No need to change the default unless you know what you are doing. +#queueMetricsCollectionTimeoutInSeconds: 40 +#channelMetricsCollectionTimeoutInSeconds: 40 +#topicMetricsCollectionTimeoutInSeconds: 40 + +queueManagers: + - name: "QM1" + host: "0.0.0.0" + port: 1414 + + # Indicate the MaxActiveChannels as set in qm.ini, see https://www.ibm.com/docs/en/ibm-mq/9.3.x?topic=qmini-channels-stanza-file + maxActiveChannels: 4200 + + #The transport type for the queue manager connection, the default is "Bindings" for a binding type connection + #For bindings type, connection WMQ extension (i.e machine agent) need to be on the same machine on which WebbsphereMQ server is running + #For client type, connection change it to "Client". + transportType: "Client" + + #Channel name of the queue manager, channel should be server-conn type. + #This field is not required in case of transportType: Bindings + channelName: DEV.ADMIN.SVRCONN + + #for user access level, please check "Access Permissions" section on the extensions page + #comment out the username and password in case of transportType: Bindings. + username: "admin" + password: "passw0rd" + + #PCF requests are always sent to SYSTEM.ADMIN.COMMAND.QUEUE. The PCF responses to these requests are sent to the default reply-to queue called + #SYSTEM.DEFAULT.MODEL.QUEUE. However, you can override this behavior and send it to a temporary dynamic queue by changing the modelQueueName and replyQueuePrefix fields. + #For more details around this https://www.ibm.com/support/knowledgecenter/SSFKSJ_7.5.0/com.ibm.mq.ref.adm.doc/q083240_.htm & https://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.adm.doc/q020010_.htm + #modelQueueName: "" + #replyQueuePrefix: "" + + # Name of the temporary dynamic queue holding the configuration events. This queue contains information regarding the configuration of the queue manager, notable MaxChannels and MaxActiveChannels. + # If unset, the default queue name `SYSTEM.ADMIN.CONFIG.EVENT` is applied. + # Configuration events need to be enabled explicitly in the queue manager configuration. See https://www.ibm.com/docs/en/ibm-mq/9.4.x?topic=monitoring-configuration-events for reference. + #configurationQueueName: "SYSTEM.ADMIN.CONFIG.EVENT" + + # Interval in milliseconds at which the configuration events in the configuration queue can be consumed. + # By default, no events are consumed. + #consumeConfigurationEventInterval: 600000 # 10 minutes + + # Enable running a queue manager refresh request to reload its configuration and create a configuration event. + # This action is only executed if no configuration events are found when reading the configuration queue.name: + # By default, this action is disabled. + #refreshQueueManagerConfigurationEnabled: false + + #Sets the CCSID used in the message descriptor of request and response messages. The default value is MQC.MQCCSI_Q_MGR. + #To set this, please use the integer value. + #ccsid: + + #Sets the encoding used in the message descriptor of request and response messages. The default value is MQC.MQENC_NATIVE. + #To set this, please use the integer value. + #encoding: + + # IBM Cipher Suite e.g. "SSL_RSA_WITH_AES_128_CBC_SHA256".. + # For translation to IBM Cipher http://www.ibm.com/support/knowledgecenter/SSFKSJ_8.0.0/com.ibm.mq.dev.doc/q113210_.htm + # A cipher working for IBM Cloud MQ and Temurin JDK 8 is TLS_AES_128_GCM_SHA256 + #cipherSuite: "TLS_AES_128_GCM_SHA256" + + + queueFilters: + #Can provide complete queue name or generic names. A generic name is a character string followed by an asterisk (*), + #for example ABC*, and it selects all objects having names that start with the selected character string. + #An asterisk on its own matches all possible names. + include: ["*"] + exclude: + #type value: STARTSWITH, EQUALS, ENDSWITH, CONTAINS + - type: "STARTSWITH" + #The name of the queue or queue name pattern as per queue filter, comma separated values + values: ["SYSTEM","AMQ"] + + + channelFilters: + #Can provide complete channel name or generic names. A generic name is a character string followed by an asterisk (*), + #for example ABC*, and it selects all objects having names that start with the selected character string. + #An asterisk on its own matches all possible names. + include: ["*"] + exclude: + #type value: STARTSWITH, EQUALS, ENDSWITH, CONTAINS + - type: "STARTSWITH" + #The name of the queue or queue name pattern as per queue filter, comma separated values + values: ["SYSTEM"] + + listenerFilters: + #Can provide complete channel name or generic names. A generic name is a character string followed by an asterisk (*), + #for example ABC*, and it selects all objects having names that start with the selected character string. + #An asterisk on its own matches all possible names. + include: ["*"] + exclude: + #type value: STARTSWITH, EQUALS, ENDSWITH, CONTAINS + - type: "STARTSWITH" + #The name of the queue or queue name pattern as per queue filter, comma separated values + values: ["SYSTEM"] + + topicFilters: + # For topics, IBM MQ uses the topic wildcard characters ('#' and '+') and does not treat a trailing asterisk as a wildcard + # https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.5.0/com.ibm.mq.pla.doc/q005020_.htm + include: ["#"] + exclude: + #type value: STARTSWITH, EQUALS, ENDSWITH, CONTAINS + - type: "STARTSWITH" + #The name of the queue or queue name pattern as per queue filter, comma separated values + values: ["SYSTEM","$SYS"] +metrics: + "mq.message.retry.count": # Number of message retries + enabled: true + "mq.status": # Channel status + enabled: true + "mq.max.sharing.conversations": # Maximum number of conversations permitted on this channel instance. + enabled: true + "mq.current.sharing.conversations": # Current number of conversations permitted on this channel instance. + enabled: true + "mq.byte.received": # Number of bytes received + enabled: true + "mq.byte.sent": # Number of bytes sent + enabled: true + "mq.buffers.received": # Buffers received + enabled: true + "mq.buffers.sent": # Buffers sent + enabled: true + "mq.message.count": # Message count + enabled: true + "mq.open.input.count": # Count of applications sending messages to the queue + enabled: true + "mq.open.output.count": # Count of applications consuming messages from the queue + enabled: true + "mq.high.queue.depth": # The current high queue depth + enabled: true + "mq.service.interval": # The queue service interval + enabled: true + "mq.queue.depth.full.event": # The number of full queue events + enabled: true + "mq.queue.depth.high.event": # The number of high queue events + enabled: true + "mq.queue.depth.low.event": # The number of low queue events + enabled: true + "mq.uncommitted.messages": # Number of uncommitted messages + enabled: true + "mq.oldest.msg.age": # Queue message oldest age + enabled: true + "mq.current.max.queue.filesize": # Current maximum queue file size + enabled: true + "mq.current.queue.filesize": # Current queue file size + enabled: true + "mq.instances.per.client": # Instances per client + enabled: true + "mq.message.deq.count": # Message dequeue count + enabled: true + "mq.message.enq.count": # Message enqueue count + enabled: true + "mq.queue.depth": # Current queue depth + enabled: true + "mq.service.interval.event": # Queue service interval event + enabled: true + "mq.reusable.log.size": # The amount of space occupied, in megabytes, by log extents available to be reused. + enabled: true + "mq.manager.active.channels": # The queue manager active maximum channels limit + enabled: true + "mq.restart.log.size": # Size of the log data required for restart recovery in megabytes. + enabled: true + "mq.max.queue.depth": # Maximum queue depth + enabled: true + "mq.onqtime.1": # Amount of time, in microseconds, that a message spent on the queue, over a short period + enabled: true + "mq.onqtime.2": # Amount of time, in microseconds, that a message spent on the queue, over a longer period + enabled: true + "mq.message.received.count": # Number of messages received + enabled: true + "mq.message.sent.count": # Number of messages sent + enabled: true + "mq.max.instances": # Max channel instances + enabled: true + "mq.connection.count": # Active connections count + enabled: true + "mq.manager.status": # Queue manager status + enabled: true + "mq.heartbeat": # Queue manager heartbeat + enabled: true + "mq.archive.log.size": # Queue manager archive log size + enabled: true + "mq.manager.max.active.channels": # Queue manager max active channels + enabled: true + "mq.manager.statistics.interval": # Queue manager statistics interval + enabled: true + "mq.publish.count": # Topic publication count + enabled: true + "mq.subscription.count": # Topic subscription count + enabled: true + "mq.listener.status": # Listener status + enabled: true + "mq.unauthorized.event": # Number of authentication error events + enabled: true + "mq.manager.max.handles": # Max open handles + enabled: true + +sslConnection: + trustStorePath: "" + trustStorePassword: "" + + keyStorePath: "" + keyStorePassword: "" + +otlpExporter: + otel.metric.export.interval: 20s + otel.exporter.otlp.protocol: http/protobuf + otel.exporter.otlp.endpoint: http://0.0.0.0:4318 + otel.logs.exporter: none + otel.traces.exporter: none \ No newline at end of file diff --git a/ibm-mq-metrics/golden/data/expected.yaml b/ibm-mq-metrics/golden/data/expected.yaml new file mode 100644 index 000000000..9a51edc49 --- /dev/null +++ b/ibm-mq-metrics/golden/data/expected.yaml @@ -0,0 +1,1404 @@ +resourceMetrics: + - resource: {} + scopeMetrics: + - metrics: + - description: Channel status + gauge: + dataPoints: + - asInt: "3" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.status + unit: "1" + - description: Buffers sent + gauge: + dataPoints: + - asInt: "47" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.buffers.sent + unit: '{buffers}' + - description: Count of applications consuming messages from the queue + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.open.output.count + unit: '{applications}' + - description: Instances per client + gauge: + dataPoints: + - asInt: "999999999" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: channel.name + value: + stringValue: DEV.APP.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.instances.per.client + unit: '{instances}' + - description: Active connections count + gauge: + dataPoints: + - asInt: "25" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.connection.count + unit: '{connections}' + - description: Number of message retries + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.APP.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.retry.count + unit: '{messages}' + - description: Message count + gauge: + dataPoints: + - asInt: "44" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.count + unit: '{messages}' + - description: Count of applications sending messages to the queue + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.open.input.count + unit: '{applications}' + - description: The queue manager active maximum channels limit + gauge: + dataPoints: + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.manager.active.channels + unit: '{channels}' + - gauge: + dataPoints: + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.heartbeat + unit: "1" + - description: Max channel instances + gauge: + dataPoints: + - asInt: "999999999" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: channel.name + value: + stringValue: DEV.APP.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.max.instances + unit: '{instances}' + - description: Message enqueue count + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.enq.count + unit: '{messages}' + - description: Maximum number of conversations permitted on this channel instance. + gauge: + dataPoints: + - asInt: "10" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.max.sharing.conversations + unit: '{conversations}' + - description: Number of uncommitted messages + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.uncommitted.messages + unit: '{messages}' + - description: Maximum queue depth + gauge: + dataPoints: + - asInt: "5000" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.APP.MODEL.QUEUE + - key: queue.type + value: + stringValue: model-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "5000" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "5000" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "5000" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "5000" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.max.queue.depth + unit: '{messages}' + - description: Topic subscription count + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: topic.name + value: + stringValue: dev + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: topic.name + value: + stringValue: dev/ + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.subscription.count + unit: '{subscriptions}' + - description: Queue service interval event + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.APP.MODEL.QUEUE + - key: queue.type + value: + stringValue: model-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.service.interval.event + unit: "1" + - description: Topic publication count + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: topic.name + value: + stringValue: dev + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: topic.name + value: + stringValue: dev/ + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.publish.count + unit: '{publications}' + - description: Amount of time, in microseconds, that a message spent on the queue, over a short period + gauge: + dataPoints: + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.onqtime.1 + unit: microseconds + - description: The queue service interval + gauge: + dataPoints: + - asInt: "999999999" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.APP.MODEL.QUEUE + - key: queue.type + value: + stringValue: model-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "999999999" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.service.interval + unit: '{percent}' + - description: Amount of time, in microseconds, that a message spent on the queue, over a longer period + gauge: + dataPoints: + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.onqtime.2 + unit: microseconds + - description: Current queue depth + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.queue.depth + unit: '{messages}' + - description: Size of the log data required for restart recovery in megabytes. + gauge: + dataPoints: + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.restart.log.size + unit: mib + - description: Queue message oldest age + gauge: + dataPoints: + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "-1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.oldest.msg.age + unit: microseconds + - description: Buffers received + gauge: + dataPoints: + - asInt: "49" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.buffers.received + unit: '{buffers}' + - description: Queue manager archive log size + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.archive.log.size + unit: mib + - description: Queue manager status + gauge: + dataPoints: + - asInt: "2" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.manager.status + unit: "1" + - description: Queue manager statistics interval + gauge: + dataPoints: + - asInt: "1800" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.manager.statistics.interval + unit: "1" + - description: Current maximum queue file size + gauge: + dataPoints: + - asInt: "2088960" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "2088960" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "2088960" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "2088960" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.current.max.queue.filesize + unit: mib + - description: Message dequeue count + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.deq.count + unit: '{messages}' + - description: Queue manager max active channels + gauge: + dataPoints: + - asInt: "4200" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.manager.max.active.channels + unit: '{channels}' + - description: Current number of conversations permitted on this channel instance. + gauge: + dataPoints: + - asInt: "1" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.current.sharing.conversations + unit: '{conversations}' + - description: Number of bytes received + gauge: + dataPoints: + - asInt: "11536" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.byte.received + unit: '{bytes}' + - description: Number of messages sent + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.APP.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.sent.count + unit: '{messages}' + - description: The amount of space occupied, in megabytes, by log extents available to be reused. + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.reusable.log.size + unit: mib + - description: The current high queue depth + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.high.queue.depth + unit: '{percent}' + - description: Number of bytes sent + gauge: + dataPoints: + - asInt: "29616" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.start.time + value: + intValue: "1748590747" + - key: channel.type + value: + stringValue: server-connection + - key: job.name + value: + stringValue: "0000074600000005" + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.byte.sent + unit: '{bytes}' + - description: Number of messages received + gauge: + dataPoints: + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.ADMIN.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "0" + attributes: + - key: channel.name + value: + stringValue: DEV.APP.SVRCONN + - key: channel.type + value: + stringValue: server-connection + - key: queue.manager + value: + stringValue: QM1 + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.message.received.count + unit: '{messages}' + - description: Current queue file size + gauge: + dataPoints: + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.DEAD.LETTER.QUEUE + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.1 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.2 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + - asInt: "1" + attributes: + - key: queue.manager + value: + stringValue: QM1 + - key: queue.name + value: + stringValue: DEV.QUEUE.3 + - key: queue.type + value: + stringValue: local-normal + startTimeUnixNano: "1000000" + timeUnixNano: "2000000" + name: mq.current.queue.filesize + unit: mib + scope: + name: websphere/mq diff --git a/ibm-mq-metrics/golden/docker-compose.yaml b/ibm-mq-metrics/golden/docker-compose.yaml new file mode 100644 index 000000000..f359c6be8 --- /dev/null +++ b/ibm-mq-metrics/golden/docker-compose.yaml @@ -0,0 +1,52 @@ +services: + mq: + image: icr.io/ibm-messaging/mq:9.4.2.1-r1 + ports: + - 1414:1414 + - 9443:9443 + environment: + LICENSE: accept + MQ_QMGR_NAME: QM1 + MQ_ADMIN_USER: admin + MQ_ADMIN_PASSWORD: passw0rd + MQ_APP_USER: app + MQ_APP_PASSWORD: passw0rd # deprecated, but needed for app user in some setups + MQ_ENABLE_METRICS: true + command: >- + --name ibm-mq-test + --health-cmd "echo > /dev/tcp/localhost/1414" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + healthcheck: + test: curl -k https://localhost:9443/ || exit 1 + interval: 5s + retries: 20 + collector: + image: ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:0.131.0 + ports: + - 4317:4317 + - 4318:4318 + volumes: + - ./otelconf.yaml:/etc/otelcol-contrib/config.yaml + golden: + container_name: golden + image: ghcr.io/open-telemetry/opentelemetry-collector-contrib/golden:v0.132.0 + volumes: + - ./data:/var/data + command: >- + --expected /var/data/expected.yaml + --otlp-http-endpoint 0.0.0.0:4318 + --otlp-endpoint 0.0.0.0:4317 + --ignore-timestamp + --ignore-start-timestamp + --timeout 2m + --ignore-metric-attribute-value channel.start.time + --ignore-metric-attribute-value job.name + --ignore-resource-metrics-order + --ignore-scope-metrics-order + --ignore-metrics-order + --ignore-metrics-data-points-order + --ignore-metric-values + --ignore-data-points-attributes-order +# --write-expected diff --git a/ibm-mq-metrics/golden/otelconf.yaml b/ibm-mq-metrics/golden/otelconf.yaml new file mode 100644 index 000000000..122091973 --- /dev/null +++ b/ibm-mq-metrics/golden/otelconf.yaml @@ -0,0 +1,34 @@ +receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 +exporters: + debug: + verbosity: detailed + otlp: + endpoint: http://golden:4317 + tls: + insecure: true + retry_on_failure: + enabled: false + sending_queue: + enabled: false +processors: + groupbyattrs: + batch: + send_batch_size: 5000 + timeout: 10s +service: + pipelines: + metrics: + receivers: + - otlp + processors: + - batch + - groupbyattrs + exporters: + - debug + - otlp \ No newline at end of file diff --git a/ibm-mq-metrics/golden/run.sh b/ibm-mq-metrics/golden/run.sh new file mode 100755 index 000000000..8edd9160d --- /dev/null +++ b/ibm-mq-metrics/golden/run.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -eu + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +java -cp "$SCRIPT_DIR/../build/libs/opentelemetry-ibm-mq-metrics-1.49.0-alpha-SNAPSHOT-all.jar:$SCRIPT_DIR/../build/libs/com.ibm.mq.allclient.jar" \ + -Dotel.logs.exporter=none -Dotel.traces.exporter=none \ + io.opentelemetry.ibm.mq.opentelemetry.Main "$SCRIPT_DIR/config.yml"